From b7fcf33b05c6b8b2762eebbb5e369428fe6c66c9 Mon Sep 17 00:00:00 2001 From: coolsnowwolf Date: Tue, 30 Jan 2024 17:00:15 +0800 Subject: [PATCH] ipq60xx: rename target to qualcommax --- .../files/{ipq807x => qualcommax} | 33 +- target/linux/ipq60xx/Makefile | 21 - .../ipq60xx/base-files/etc/board.d/01_leds | 25 - .../ipq60xx/base-files/etc/board.d/02_network | 51 - .../etc/hotplug.d/firmware/11-ath11k-caldata | 81 - .../hotplug.d/ieee80211/10-fix-mac-address | 16 - .../lib/preinit/69_mount_factory_data | 19 - .../base-files/lib/upgrade/platform.sh | 104 - target/linux/ipq60xx/config-5.15 | 506 - .../arch/arm64/boot/dts/qcom/ipq6018-ax18.dts | 67 - .../arm64/boot/dts/qcom/ipq6018-cmiot.dtsi | 200 - .../boot/dts/qcom/ipq6018-eap610-outdoor.dts | 136 - .../arch/arm64/boot/dts/qcom/ipq6018-ess.dtsi | 412 - .../arch/arm64/boot/dts/qcom/ipq6018-m2.dts | 66 - .../arm64/boot/dts/qcom/ipq6018-mr7350.dts | 249 - .../boot/dts/qcom/ipq6018-upstreamable.dtsi | 120 - .../arch/arm64/boot/dts/qcom/ipq6018-v6.dts | 249 - target/linux/ipq60xx/generic/target.mk | 1 - target/linux/ipq60xx/image/Makefile | 18 - target/linux/ipq60xx/image/generic.mk | 93 - ...-arm64-dts-qcom-ipq8074-add-SPMI-bus.patch | 43 - ...pdate-BAM-DMA-node-name-per-DT-schem.patch | 27 - ...4-dts-qcom-ipq8074-Add-QUP5-I2C-node.patch | 40 - ...sm8996-Move-clock-cells-to-QMP-PHY-c.patch | 53 - ...-arm64-dts-qcom-ipq8074-add-MDIO-bus.patch | 36 - ...64-dts-qcom-ipq8074-add-SMEM-support.patch | 51 - ...ipq8074-add-the-reserved-memory-node.patch | 30 - ...om-ipq8074-enable-the-GICv2m-support.patch | 36 - ...pq8074-drop-the-clock-frequency-prop.patch | 26 - ...lign-dmas-in-I2C-SPI-UART-with-DT-sc.patch | 62 - ...lign-clocks-in-I2C-SPI-with-DT-schem.patch | 69 - ...orrect-DWC3-node-names-and-unit-addr.patch | 37 - ...pq8074-add-dedicated-qcom-ipq8074-dw.patch | 36 - ...align-DWC3-USB-clocks-with-DT-schema.patch | 39 - ...64-dts-qcom-adjust-whitespace-around.patch | 36 - ...ts-qcom-Fix-sdhci-node-names-use-mmc.patch | 34 - ...ix-ordering-of-clocks-clock-names-fo.patch | 47 - ...ck-qcom-ipq8074-add-PPE-crypto-clock.patch | 25 - ...lk-qcom-ipq8074-add-PPE-crypto-clock.patch | 52 - ...ngs-clock-qcom-ipq8074-add-USB-GDSCs.patch | 25 - ...-v6.0-clk-qcom-ipq8074-add-USB-GDSCs.patch | 79 - ...s-qcom-ipq8074-add-USB-power-domains.patch | 43 - ...pq8074-move-ARMv8-timer-out-of-SoC-n.patch | 51 - ...-dts-qcom-ipq8074-add-reset-to-SDHCI.patch | 27 - ...com-ipq8074-drop-USB-PHY-clock-index.patch | 36 - ...arm64-dts-qcom-ipq8074-add-APCS-node.patch | 37 - ...pq8074-add-size-address-cells-to-DTS.patch | 55 - ...ipq8074-add-interrupt-parent-to-DTSI.patch | 50 - ...or-qcom_spmi-add-support-for-HT_P150.patch | 58 - ...or-qcom_spmi-add-support-for-HT_P600.patch | 59 - ...pmi-add-support-for-PMP8074-regulato.patch | 69 - ...om-pmic-gpio-add-support-for-PMP8074.patch | 25 - ...-pmic-Sort-compatibles-in-the-driver.patch | 60 - ...ic-Add-missing-PMICs-supported-by-so.patch | 66 - ...i-adc5-add-ADC5_VREF_VADC-to-rev2-AD.patch | 27 - ...ie-make-pipe-clock-rate-configurable.patch | 47 - ...e-add-IPQ8074-PCIe-Gen3-QMP-PHY-supp.patch | 201 - ...qcom-socinfo-Add-IPQ8074-family-ID-s.patch | 50 - ...ve-GEN3_RELATED-DBI-register-to-comm.patch | 45 - ...slot-capabilities-using-PCI_EXP_SLTC.patch | 46 - ...44-v6.0-PCI-qcom-Add-IPQ60xx-support.patch | 212 - ...ts-ipq8074-add-reserved-memory-nodes.patch | 70 - ...1-clk-qcom-clk-rcg2-add-rcg2-mux-ops.patch | 49 - ...apss-ipq6018-fix-apcs_alias0_clk_src.patch | 61 - ...q-pll-use-OF-match-data-for-Alpha-PL.patch | 68 - ...q-pll-update-IPQ6018-Alpha-PLL-confi.patch | 38 - ...apss-ipq-pll-add-support-for-IPQ8074.patch | 51 - ...pq8074-correct-APCS-register-space-s.patch | 31 - ...64-dts-qcom-ipq8074-add-A53-PLL-node.patch | 30 - ...s-ipc-add-IPQ8074-APSS-clock-support.patch | 50 - ...-dts-qcom-ipq8074-add-clocks-to-APCS.patch | 29 - ...11-PCI-qcom-add-IPQ8074-Gen3-support.patch | 45 - ...remoteproc-qcom-Add-PRNG-proxy-clock.patch | 155 - ...moteproc-qcom-Add-secure-PIL-support.patch | 143 - ...Add-support-for-split-q6-m3-wlan-fir.patch | 104 - ...oc-qcom-Add-ssr-subdevice-identifier.patch | 24 - ...Update-regmap-offsets-for-halt-regis.patch | 80 - ...tsens-Add-support-for-combined-inter.patch | 138 - ...tsens-allow-configuring-min-and-max-.patch | 100 - ...rs-thermal-tsens-add-IPQ8074-support.patch | 72 - ...-arm64-dts-ipq8074-add-thermal-nodes.patch | 131 - ...om-spmi-pmic-add-support-for-PMP8074.patch | 25 - ...0123-arm64-dts-qcom-add-PMP8074-DTSI.patch | 158 - ...s-qcom-ipq8074-hk01-add-VQMMC-supply.patch | 35 - ...0125-arm64-dts-ipq8074-add-CPU-clock.patch | 59 - ...-arm64-dts-ipq8074-add-label-to-cpus.patch | 25 - ...q8074-add-cooling-cells-to-CPU-nodes.patch | 48 - ...ngs-clock-qcom-Add-reset-for-WCSSAON.patch | 26 - .../0129-clk-qcom-Add-WCSSAON-reset.patch | 25 - ...c-wcss-disable-auto-boot-for-IPQ8074.patch | 47 - ...com-Enable-Q6v5-WCSS-for-ipq8074-SoC.patch | 120 - ...0132-arm64-dts-ipq8074-Add-WLAN-node.patch | 135 - ...pq8074-add-missing-networking-resets.patch | 63 - ...rm64-dts-ipq8074-add-label-to-clocks.patch | 24 - .../0136-power-Add-Qualcomm-APM.patch | 1047 -- ...egulator-add-Qualcomm-CPR-regulators.patch | 12146 ---------------- ...qcom-ipq6018-add-usb3-DT-description.patch | 110 - ...ve-unused-qcom_config-pipe-trust-reg.patch | 42 - ...018-Remove-unused-iface_clk-property.patch | 45 - ...qcom-ipq6018-add-pcie-max-link-speed.patch | 26 - ...com-ipq6018-fix-usb-reference-period.patch | 29 - ...e-reference-clock-to-set-dwc3-period.patch | 34 - ...m-ipq6018-enable-the-GICv2m-supporte.patch | 40 - ...18-drop-the-clock-frequency-property.patch | 26 - ...-dmas-in-I2C-SPI-UART-with-DT-schema.patch | 39 - ...ign-clocks-in-I2C-SPI-with-DT-schema.patch | 42 - ...s-qcom-ipq6018-Fix-qmp-usb3-phy-node.patch | 48 - ...t-DWC3-node-names-and-unit-addresses.patch | 45 - ...align-DWC3-USB-clocks-with-DT-schema.patch | 37 - ...align-OPP-table-names-with-DT-schema.patch | 32 - ...om-timer-should-use-only-32-bit-size.patch | 94 - ...4-dts-qcom-adjust-whitespace-around-.patch | 36 - ...ipq6018-add-label-to-remoteproc-node.patch | 26 - ...pq6018-correct-QUP-peripheral-labels.patch | 82 - ...s-qcom-extend-scm-compatible-strings.patch | 26 - ...com-ipq6018-drop-USB-PHY-clock-index.patch | 27 - ...8-add-missing-TCSR-syscon-compatible.patch | 25 - ...4-dts-qcom-ipq6018-add-QUP6-I2C-node.patch | 36 - ...ts-qcom-ipq6018-add-MP5496-LDO2-node.patch | 27 - ...om-ipq6018-add-SDHCI-controller-node.patch | 47 - ...m64-dts-qcom-ipq6018-add-QFPROM-node.patch | 33 - ...lign-SPI-NOR-node-name-with-dtschema.patch | 25 - ...p01-c1-fix-Micron-SPI-NOR-compatible.patch | 27 - ...qcom-cp01-c1-enable-SDHCI-controller.patch | 61 - ...-qcom-cp01-c1-remove-bootargs-append.patch | 23 - ...-qcom-cp01-c1-use-okay-instead-of-ok.patch | 26 - ...arm64-dts-qcom-cp01-c1-enable-USB3.0.patch | 33 - ...6-arm64-dts-qcom-cp01-c1-enable-PCIe.patch | 30 - ...rm64-dts-qcom-cp01-c1-add-MDIO-PHY-s.patch | 81 - .../0600-5.15-qca-nss-ecm-support-CORE.patch | 615 - ...ter-export-udp_get_timeouts-function.patch | 35 - ...2-5.15-qca-add-pppoe-offload-support.patch | 602 - ...-identify-ingress-shaping-done-for-e.patch | 75 - ...5-qca-add-add-nss-bridge-mgr-support.patch | 95 - ...-qca-nss-ecm-bonding-add-bond_get_id.patch | 81 - ...dd-bridge-join-and-leave-netdev-cmds.patch | 11 - ...s-ssdk-delete-fdb-entry-using-netdev.patch | 32 - ...a-cache-routines-with-same-API-as-32.patch | 29 - ...-__dma_inv_area-and-__dma_clean_area.patch | 56 - ...1000-arm64-dts-add-OpenWrt-DTS-files.patch | 28 - ...com-ipq6018-Add-mdio-bus-description.patch | 35 - ...om-add-support-for-hw-controlled-RCG.patch | 143 - ...qcom-ipq6018-add-missing-clock-flags.patch | 147 - ...m-ipq6018-update-Huayra-PLL-settings.patch | 54 - ...com-ipq6018-Add-missing-fixed-clocks.patch | 48 - ...-rproc-Add-non-secure-Q6-bringup-seq.patch | 55 - target/linux/qualcommax/Makefile | 2 +- target/linux/qualcommax/config-6.1 | 1 + .../arm64/boot/dts/qcom/ipq6000-360v6.dts | 207 + .../arm64/boot/dts/qcom/ipq6000-mr7350.dts | 298 + .../arm64/boot/dts/qcom/ipq6000-rm1800.dts | 208 + .../arm64/boot/dts/qcom/ipq6018-256m.dtsi | 15 + .../arm64/boot/dts/qcom/ipq6018-512m.dtsi | 15 + .../arch/arm64/boot/dts/qcom/ipq6018-ess.dtsi | 495 + target/linux/qualcommax/image/ipq60xx.mk | 48 + .../ipq60xx/base-files/etc/board.d/02_network | 56 + .../etc/hotplug.d/firmware/11-ath11k-caldata | 21 + .../etc/hotplug.d/ieee80211/11_fix_wifi_mac | 23 + .../ipq60xx/base-files/etc/init.d/bootcount | 11 + .../base-files/lib/upgrade/platform.sh | 31 + .../linux/qualcommax/ipq60xx/config-default | 10 + target/linux/qualcommax/ipq60xx/target.mk | 7 + ...dts-qcom-ipq6018-fix-NAND-node-name.patch} | 8 +- ...q6018-align-TLMM-pin-configuration-.patch} | 8 +- ...m-ipq8074-add-compatible-fallback-to.patch | 26 + ...q-qcom-nvmem-add-support-for-IPQ6018.patch | 123 + ...-qcom-nvmem-add-support-for-IPQ8074.patch} | 23 +- ...pq8074-include-the-GPLL0-as-clock-pr.patch | 6 +- ...ipq6018-move-ARMv8-timer-out-of-SoC.patch} | 12 +- ...dts-qcom-ipq6018-Sort-nodes-properly.patch | 605 + ...com-ipq6018-Add-remove-some-newlines.patch | 92 + ...4-dts-qcom-ipq6018-Use-lowercase-hex.patch | 25 + ...m-ipq6018-align-RPM-G-Link-node-with.patch | 28 + ...m-ipq6018-cp01-c1-drop-SPI-cs-select.patch | 27 + ...-add-few-more-reserved-memory-region.patch | 92 + ...com-enable-the-download-mode-support.patch | 49 + ...om-ipq6018-correct-qrng-unit-address.patch | 29 + ...ipq6018-add-unit-address-to-soc-node.patch | 28 + ...m64-dts-qcom-ipq6018-add-QFPROM-node.patch | 34 + ...-qcom-ipq6018-drop-incorrect-SPI-bus.patch | 37 + ...-qcom-ipq8074-drop-incorrect-SPI-bus.patch | 29 + ...pq6018-Use-floor-ops-for-sdcc-clocks.patch | 27 + ...-gcc-ipq6018-drop-redundant-F-define.patch | 27 + ...lk-qcom-gcc-ipq6018-update-UBI32-PLL.patch | 39 + ...pq6018-remove-duplicate-initializers.patch | 38 + ...m-Add-RPM-processor-subsystem-driver.patch | 132 + ...dts-qcom-Add-rpm-proc-node-for-GLINK.patch | 93 + ...ts-qcom-ipq6018-include-the-GPLL0-as.patch | 35 + ...-qcom-gcc-ipq6018-add-QUP6-I2C-clock.patch | 57 + ...4-dts-qcom-ipq6018-use-CPUFreq-NVMEM.patch | 85 + ...ts-ipq8074-add-reserved-memory-nodes.patch | 22 +- ...ck-qcom-Remove-IPQ6018-SOC-specific-.patch | 30 + ...river-for-qualcomm-ipq6018-pwm-block.patch | 337 + ...-arm64-dts-qcom-ipq6018-add-pwm-node.patch | 45 + ...-ipq6018-Add-remaining-QUP-UART-node.patch | 66 + ...com-Enable-Q6v5-WCSS-for-ipq8074-SoC.patch | 8 +- ...s-Add-ipq6018-support-in-remoteproc.patch} | 28 +- ...-Add-non-secure-Q6-bringup-sequence.patch} | 199 +- ...0133-arm64-dts-ipq6018-Add-WLAN-node.patch | 122 + ...ts-ipq6018-add-reserved-memory-nodes.patch | 19 + ...dts-qcom-ipq6018-add-LDOA2-regulator.patch | 15 + ...4-dts-qcom-ipq6018-enable-sdhci-node.patch | 29 + ...4-dts-qcom-ipq6018-add-thermal-nodes.patch | 146 + ...rm64-dts-qcom-ipq6018-rework-cpufreq.patch | 216 + ...lk-qcom-gcc-ipq6018-workaround-ssdk.patch} | 51 +- ...0139-clk-ipq6018-Add-missing-clocks.patch} | 87 +- ...rm64-dts-ipq6018-add-label-to-clocks.patch | 11 + ...t-advertise-OSI-support-for-IPQ6018.patch} | 6 +- 208 files changed, 4471 insertions(+), 23795 deletions(-) rename package/boot/uboot-envtools/files/{ipq807x => qualcommax} (67%) delete mode 100644 target/linux/ipq60xx/Makefile delete mode 100644 target/linux/ipq60xx/base-files/etc/board.d/01_leds delete mode 100644 target/linux/ipq60xx/base-files/etc/board.d/02_network delete mode 100644 target/linux/ipq60xx/base-files/etc/hotplug.d/firmware/11-ath11k-caldata delete mode 100644 target/linux/ipq60xx/base-files/etc/hotplug.d/ieee80211/10-fix-mac-address delete mode 100644 target/linux/ipq60xx/base-files/lib/preinit/69_mount_factory_data delete mode 100644 target/linux/ipq60xx/base-files/lib/upgrade/platform.sh delete mode 100644 target/linux/ipq60xx/config-5.15 delete mode 100644 target/linux/ipq60xx/files/arch/arm64/boot/dts/qcom/ipq6018-ax18.dts delete mode 100644 target/linux/ipq60xx/files/arch/arm64/boot/dts/qcom/ipq6018-cmiot.dtsi delete mode 100644 target/linux/ipq60xx/files/arch/arm64/boot/dts/qcom/ipq6018-eap610-outdoor.dts delete mode 100644 target/linux/ipq60xx/files/arch/arm64/boot/dts/qcom/ipq6018-ess.dtsi delete mode 100644 target/linux/ipq60xx/files/arch/arm64/boot/dts/qcom/ipq6018-m2.dts delete mode 100644 target/linux/ipq60xx/files/arch/arm64/boot/dts/qcom/ipq6018-mr7350.dts delete mode 100644 target/linux/ipq60xx/files/arch/arm64/boot/dts/qcom/ipq6018-upstreamable.dtsi delete mode 100644 target/linux/ipq60xx/files/arch/arm64/boot/dts/qcom/ipq6018-v6.dts delete mode 100644 target/linux/ipq60xx/generic/target.mk delete mode 100644 target/linux/ipq60xx/image/Makefile delete mode 100644 target/linux/ipq60xx/image/generic.mk delete mode 100644 target/linux/ipq60xx/patches-5.15/0001-v5.16-arm64-dts-qcom-ipq8074-add-SPMI-bus.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0002-v5.16-arm64-dts-qcom-Update-BAM-DMA-node-name-per-DT-schem.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0003-v5.16-arm64-dts-qcom-ipq8074-Add-QUP5-I2C-node.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0004-v5.16-arm64-dts-qcom-msm8996-Move-clock-cells-to-QMP-PHY-c.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0007-v5.17-arm64-dts-qcom-ipq8074-add-MDIO-bus.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0009-v5.18-arm64-dts-qcom-ipq8074-add-SMEM-support.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0010-v5.18-arm64-dts-qcom-ipq8074-add-the-reserved-memory-node.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0011-v5.18-arm64-dts-qcom-ipq8074-enable-the-GICv2m-support.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0012-v5.18-arm64-dts-qcom-ipq8074-drop-the-clock-frequency-prop.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0013-v5.19-arm64-dts-qcom-align-dmas-in-I2C-SPI-UART-with-DT-sc.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0014-v5.19-arm64-dts-qcom-align-clocks-in-I2C-SPI-with-DT-schem.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0015-v5.19-arm64-dts-qcom-correct-DWC3-node-names-and-unit-addr.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0016-v5.19-arm64-dts-qcom-ipq8074-add-dedicated-qcom-ipq8074-dw.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0017-v5.19-arm64-dts-qcom-align-DWC3-USB-clocks-with-DT-schema.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0018-v6.0-arm64-dts-qcom-adjust-whitespace-around.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0019-v6.0-arm64-dts-qcom-Fix-sdhci-node-names-use-mmc.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0020-v6.0-arm64-dts-qcom-Fix-ordering-of-clocks-clock-names-fo.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0021-v6.0-dt-bindings-clock-qcom-ipq8074-add-PPE-crypto-clock.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0022-v6.0-clk-qcom-ipq8074-add-PPE-crypto-clock.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0023-v6.0-dt-bindings-clock-qcom-ipq8074-add-USB-GDSCs.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0024-v6.0-clk-qcom-ipq8074-add-USB-GDSCs.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0025-v6.0-arm64-dts-qcom-ipq8074-add-USB-power-domains.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0026-v6.0-arm64-dts-qcom-ipq8074-move-ARMv8-timer-out-of-SoC-n.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0027-v6.0-arm64-dts-qcom-ipq8074-add-reset-to-SDHCI.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0028-v6.0-arm64-dts-qcom-ipq8074-drop-USB-PHY-clock-index.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0029-v6.0-arm64-dts-qcom-ipq8074-add-APCS-node.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0030-v6.0-arm64-dts-qcom-ipq8074-add-size-address-cells-to-DTS.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0031-v6.0-arm64-dts-qcom-ipq8074-add-interrupt-parent-to-DTSI.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0032-v6.0-regulator-qcom_spmi-add-support-for-HT_P150.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0033-v6.0-regulator-qcom_spmi-add-support-for-HT_P600.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0034-v6.0-regulator-qcom_spmi-add-support-for-PMP8074-regulato.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0035-v6.0-pinctrl-qcom-pmic-gpio-add-support-for-PMP8074.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0036-v5.16-mfd-qcom-spmi-pmic-Sort-compatibles-in-the-driver.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0037-v5.16-mfd-qcom-spmi-pmic-Add-missing-PMICs-supported-by-so.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0038-v6.0-iio-adc-qcom-spmi-adc5-add-ADC5_VREF_VADC-to-rev2-AD.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0039-v6.0-phy-qcom-qmp-pcie-make-pipe-clock-rate-configurable.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0040-v6.0-phy-qcom-qmp-pcie-add-IPQ8074-PCIe-Gen3-QMP-PHY-supp.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0041-v5.16-soc-qcom-socinfo-Add-IPQ8074-family-ID-s.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0042-v6.0-PCI-dwc-tegra-move-GEN3_RELATED-DBI-register-to-comm.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0043-v6.0-PCI-qcom-Define-slot-capabilities-using-PCI_EXP_SLTC.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0044-v6.0-PCI-qcom-Add-IPQ60xx-support.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0100-arm64-dts-ipq8074-add-reserved-memory-nodes.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0101-clk-qcom-clk-rcg2-add-rcg2-mux-ops.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0102-clk-qcom-apss-ipq6018-fix-apcs_alias0_clk_src.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0104-clk-qcom-apss-ipq-pll-use-OF-match-data-for-Alpha-PL.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0105-clk-qcom-apss-ipq-pll-update-IPQ6018-Alpha-PLL-confi.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0106-clk-qcom-apss-ipq-pll-add-support-for-IPQ8074.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0107-arm64-dts-qcom-ipq8074-correct-APCS-register-space-s.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0108-arm64-dts-qcom-ipq8074-add-A53-PLL-node.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0109-mailbox-qcom-apcs-ipc-add-IPQ8074-APSS-clock-support.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0110-arm64-dts-qcom-ipq8074-add-clocks-to-APCS.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0111-PCI-qcom-add-IPQ8074-Gen3-support.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0113-remoteproc-qcom-Add-PRNG-proxy-clock.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0114-remoteproc-qcom-Add-secure-PIL-support.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0115-remoteproc-qcom-Add-support-for-split-q6-m3-wlan-fir.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0116-remoteproc-qcom-Add-ssr-subdevice-identifier.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0117-remoteproc-qcom-Update-regmap-offsets-for-halt-regis.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0118-drivers-thermal-tsens-Add-support-for-combined-inter.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0119-drivers-thermal-tsens-allow-configuring-min-and-max-.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0120-drivers-thermal-tsens-add-IPQ8074-support.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0121-arm64-dts-ipq8074-add-thermal-nodes.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0122-mfd-qcom-spmi-pmic-add-support-for-PMP8074.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0123-arm64-dts-qcom-add-PMP8074-DTSI.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0124-arm64-dts-qcom-ipq8074-hk01-add-VQMMC-supply.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0125-arm64-dts-ipq8074-add-CPU-clock.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0126-arm64-dts-ipq8074-add-label-to-cpus.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0127-arm64-dts-ipq8074-add-cooling-cells-to-CPU-nodes.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0128-dt-bindings-clock-qcom-Add-reset-for-WCSSAON.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0129-clk-qcom-Add-WCSSAON-reset.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0130-remoteproc-wcss-disable-auto-boot-for-IPQ8074.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0131-arm64-dts-qcom-Enable-Q6v5-WCSS-for-ipq8074-SoC.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0132-arm64-dts-ipq8074-Add-WLAN-node.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0134-clk-qcom-ipq8074-add-missing-networking-resets.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0135-arm64-dts-ipq8074-add-label-to-clocks.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0136-power-Add-Qualcomm-APM.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0137-regulator-add-Qualcomm-CPR-regulators.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0138-arm64-dts-qcom-ipq6018-add-usb3-DT-description.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0140-arm64-dts-qcom-ipq6018-Remove-unused-qcom_config-pipe-trust-reg.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0141-arm64-dts-qcom-ipq6018-Remove-unused-iface_clk-property.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0142-arm64-dts-qcom-ipq6018-add-pcie-max-link-speed.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0143-arm64-dts-qcom-ipq6018-fix-usb-reference-period.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0144-arm64-dts-ipq6018-Use-reference-clock-to-set-dwc3-period.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0145-arm64-dts-qcom-ipq6018-enable-the-GICv2m-supporte.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0146-arm64-dts-qcom-ipq6018-drop-the-clock-frequency-property.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0147-arm64-dts-qcom-align-dmas-in-I2C-SPI-UART-with-DT-schema.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0148-arm64-dts-qcom-align-clocks-in-I2C-SPI-with-DT-schema.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0149-arm64-dts-qcom-ipq6018-Fix-qmp-usb3-phy-node.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0150-arm64-dts-qcom-correct-DWC3-node-names-and-unit-addresses.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0151-arm64-dts-qcom-align-DWC3-USB-clocks-with-DT-schema.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0152-arm64-dts-qcom-align-OPP-table-names-with-DT-schema.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0153-arm64-dts-qcom-timer-should-use-only-32-bit-size.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0154-arm64-dts-qcom-adjust-whitespace-around-.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0155-arm64-dts-qcom-ipq6018-add-label-to-remoteproc-node.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0156-arm64-dts-qcom-ipq6018-correct-QUP-peripheral-labels.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0157-arm64-dts-qcom-extend-scm-compatible-strings.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0158-arm64-dts-qcom-ipq6018-drop-USB-PHY-clock-index.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0159-arm64-dts-qcom-ipq6018-add-missing-TCSR-syscon-compatible.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0163-arm64-dts-qcom-ipq6018-add-QUP6-I2C-node.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0164-arm64-dts-qcom-ipq6018-add-MP5496-LDO2-node.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0165-arm64-dts-qcom-ipq6018-add-SDHCI-controller-node.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0166-arm64-dts-qcom-ipq6018-add-QFPROM-node.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0169-arm64-dts-qcom-align-SPI-NOR-node-name-with-dtschema.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0170-arm64-dts-qcom-ipq6018-cp01-c1-fix-Micron-SPI-NOR-compatible.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0172-arm64-dts-qcom-cp01-c1-enable-SDHCI-controller.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0173-arm64-dts-qcom-cp01-c1-remove-bootargs-append.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0174-arm64-dts-qcom-cp01-c1-use-okay-instead-of-ok.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0175-arm64-dts-qcom-cp01-c1-enable-USB3.0.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0176-arm64-dts-qcom-cp01-c1-enable-PCIe.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0177-arm64-dts-qcom-cp01-c1-add-MDIO-PHY-s.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0600-5.15-qca-nss-ecm-support-CORE.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0601-5.15-netfilter-export-udp_get_timeouts-function.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0602-5.15-qca-add-pppoe-offload-support.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0603-net-core-Flag-to-identify-ingress-shaping-done-for-e.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0605-5.15-qca-add-add-nss-bridge-mgr-support.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0606-5.15-qca-nss-ecm-bonding-add-bond_get_id.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0607-5.15-qca-nss-ecm-Add-bridge-join-and-leave-netdev-cmds.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0800-5.15-qca-nss-ssdk-delete-fdb-entry-using-netdev.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0902-5.15-arm64-provide-dma-cache-routines-with-same-API-as-32.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/0903-5.15-arm64-mm-export-__dma_inv_area-and-__dma_clean_area.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/1000-arm64-dts-add-OpenWrt-DTS-files.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/1001-arm64-dts-qcom-ipq6018-Add-mdio-bus-description.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/1002-clk-qcom-add-support-for-hw-controlled-RCG.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/1003-clk-qcom-ipq6018-add-missing-clock-flags.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/1005-clk-qcom-ipq6018-update-Huayra-PLL-settings.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/1007-arm64-dts-qcom-ipq6018-Add-missing-fixed-clocks.patch delete mode 100644 target/linux/ipq60xx/patches-5.15/1010-Simplify-ipq6018-rproc-Add-non-secure-Q6-bringup-seq.patch create mode 100644 target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq6000-360v6.dts create mode 100644 target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq6000-mr7350.dts create mode 100644 target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq6000-rm1800.dts create mode 100644 target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq6018-256m.dtsi create mode 100644 target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq6018-512m.dtsi create mode 100644 target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq6018-ess.dtsi create mode 100644 target/linux/qualcommax/image/ipq60xx.mk create mode 100644 target/linux/qualcommax/ipq60xx/base-files/etc/board.d/02_network create mode 100644 target/linux/qualcommax/ipq60xx/base-files/etc/hotplug.d/firmware/11-ath11k-caldata create mode 100644 target/linux/qualcommax/ipq60xx/base-files/etc/hotplug.d/ieee80211/11_fix_wifi_mac create mode 100644 target/linux/qualcommax/ipq60xx/base-files/etc/init.d/bootcount create mode 100644 target/linux/qualcommax/ipq60xx/base-files/lib/upgrade/platform.sh create mode 100644 target/linux/qualcommax/ipq60xx/config-default create mode 100644 target/linux/qualcommax/ipq60xx/target.mk rename target/linux/{ipq60xx/patches-5.15/0161-arm64-dts-qcom-ipq6018-fix-NAND-node-name.patch => qualcommax/patches-6.1/0008-v6.2-arm64-dts-qcom-ipq6018-fix-NAND-node-name.patch} (66%) rename target/linux/{ipq60xx/patches-5.15/0167-arm64-dts-qcom-ipq6018-align-TLMM-pin-configuration-with-DT-schema.patch => qualcommax/patches-6.1/0018-v6.2-arm64-dts-qcom-ipq6018-align-TLMM-pin-configuration-.patch} (85%) create mode 100644 target/linux/qualcommax/patches-6.1/0022-v6.4-arm64-dts-qcom-ipq8074-add-compatible-fallback-to.patch create mode 100644 target/linux/qualcommax/patches-6.1/0025-v6.7-cpufreq-qcom-nvmem-add-support-for-IPQ6018.patch rename target/linux/qualcommax/patches-6.1/{0025-v6.7-cpufreq-qcom-nvmem-add-support-for-IPQ8074.patch => 0026-v6.7-cpufreq-qcom-nvmem-add-support-for-IPQ8074.patch} (84%) rename target/linux/{ipq60xx/patches-5.15/0162-arm64-dts-qcom-ipq6018-move-ARMv8-timer-out-of-SoC-node.patch => qualcommax/patches-6.1/0033-v6.2-arm64-dts-qcom-ipq6018-move-ARMv8-timer-out-of-SoC.patch} (80%) create mode 100644 target/linux/qualcommax/patches-6.1/0034-v6.3-arm64-dts-qcom-ipq6018-Sort-nodes-properly.patch create mode 100644 target/linux/qualcommax/patches-6.1/0035-v6.3-arm64-dts-qcom-ipq6018-Add-remove-some-newlines.patch create mode 100644 target/linux/qualcommax/patches-6.1/0036-v6.3-arm64-dts-qcom-ipq6018-Use-lowercase-hex.patch create mode 100644 target/linux/qualcommax/patches-6.1/0037-v6.3-arm64-dts-qcom-ipq6018-align-RPM-G-Link-node-with.patch create mode 100644 target/linux/qualcommax/patches-6.1/0038-v6.4-arm64-dts-qcom-ipq6018-cp01-c1-drop-SPI-cs-select.patch create mode 100644 target/linux/qualcommax/patches-6.1/0039-v6.5-arm64-dts-qcom-add-few-more-reserved-memory-region.patch create mode 100644 target/linux/qualcommax/patches-6.1/0040-v6.5-arm64-dts-qcom-enable-the-download-mode-support.patch create mode 100644 target/linux/qualcommax/patches-6.1/0041-v6.5-arm64-dts-qcom-ipq6018-correct-qrng-unit-address.patch create mode 100644 target/linux/qualcommax/patches-6.1/0042-v6.5-arm64-dts-qcom-ipq6018-add-unit-address-to-soc-node.patch create mode 100644 target/linux/qualcommax/patches-6.1/0043-v6.5-arm64-dts-qcom-ipq6018-add-QFPROM-node.patch create mode 100644 target/linux/qualcommax/patches-6.1/0044-v6.5-arm64-dts-qcom-ipq6018-drop-incorrect-SPI-bus.patch create mode 100644 target/linux/qualcommax/patches-6.1/0045-v6.5-arm64-dts-qcom-ipq8074-drop-incorrect-SPI-bus.patch create mode 100644 target/linux/qualcommax/patches-6.1/0046-v6.6-clk-qcom-gcc-ipq6018-Use-floor-ops-for-sdcc-clocks.patch create mode 100644 target/linux/qualcommax/patches-6.1/0047-v6.6-clk-qcom-gcc-ipq6018-drop-redundant-F-define.patch create mode 100644 target/linux/qualcommax/patches-6.1/0048-v6.6-clk-qcom-gcc-ipq6018-update-UBI32-PLL.patch create mode 100644 target/linux/qualcommax/patches-6.1/0049-v6.6-clk-qcom-gcc-ipq6018-remove-duplicate-initializers.patch create mode 100644 target/linux/qualcommax/patches-6.1/0050-v6.6-soc-qcom-Add-RPM-processor-subsystem-driver.patch create mode 100644 target/linux/qualcommax/patches-6.1/0051-v6.6-arm64-dts-qcom-Add-rpm-proc-node-for-GLINK.patch create mode 100644 target/linux/qualcommax/patches-6.1/0052-v6.7-arm64-dts-qcom-ipq6018-include-the-GPLL0-as.patch create mode 100644 target/linux/qualcommax/patches-6.1/0053-v6.7-clk-qcom-gcc-ipq6018-add-QUP6-I2C-clock.patch create mode 100644 target/linux/qualcommax/patches-6.1/0054-v6.8-arm64-dts-qcom-ipq6018-use-CPUFreq-NVMEM.patch create mode 100644 target/linux/qualcommax/patches-6.1/0103-hwspinlock-qcom-Remove-IPQ6018-SOC-specific-.patch create mode 100644 target/linux/qualcommax/patches-6.1/0104-pwm-driver-for-qualcomm-ipq6018-pwm-block.patch create mode 100644 target/linux/qualcommax/patches-6.1/0105-arm64-dts-qcom-ipq6018-add-pwm-node.patch create mode 100644 target/linux/qualcommax/patches-6.1/0109-arm64-dts-ipq6018-Add-remaining-QUP-UART-node.patch rename target/linux/{ipq60xx/patches-5.15/1008-remoteproc-wcss-Add-ipq6018-support-in-remoteproc.patch => qualcommax/patches-6.1/0131-remoteproc-wcss-Add-ipq6018-support-in-remoteproc.patch} (71%) rename target/linux/{ipq60xx/patches-5.15/1009-ipq6018-rproc-Add-non-secure-Q6-bringup-sequence.patch => qualcommax/patches-6.1/0132-ipq6018-rproc-Add-non-secure-Q6-bringup-sequence.patch} (73%) create mode 100644 target/linux/qualcommax/patches-6.1/0133-arm64-dts-ipq6018-Add-WLAN-node.patch create mode 100644 target/linux/qualcommax/patches-6.1/0133-arm64-dts-ipq6018-add-reserved-memory-nodes.patch create mode 100644 target/linux/qualcommax/patches-6.1/0134-arm64-dts-qcom-ipq6018-add-LDOA2-regulator.patch create mode 100644 target/linux/qualcommax/patches-6.1/0135-arm64-dts-qcom-ipq6018-enable-sdhci-node.patch create mode 100644 target/linux/qualcommax/patches-6.1/0136-arm64-dts-qcom-ipq6018-add-thermal-nodes.patch create mode 100644 target/linux/qualcommax/patches-6.1/0137-arm64-dts-qcom-ipq6018-rework-cpufreq.patch rename target/linux/{ipq60xx/patches-5.15/1006-clk-qcom-pq6018-workaround-networking-clock-parenting.patch => qualcommax/patches-6.1/0138-clk-qcom-gcc-ipq6018-workaround-ssdk.patch} (57%) rename target/linux/{ipq60xx/patches-5.15/1004-clk-qcom-ipq6018-add-missing-clocks.patch => qualcommax/patches-6.1/0139-clk-ipq6018-Add-missing-clocks.patch} (87%) create mode 100644 target/linux/qualcommax/patches-6.1/0903-arm64-dts-ipq6018-add-label-to-clocks.patch rename target/linux/{ipq60xx/patches-5.15/1013-psci-dont-advertise-OSI-support-for-IPQ6018.patch => qualcommax/patches-6.1/0910-psci-dont-advertise-OSI-support-for-IPQ6018.patch} (85%) diff --git a/package/boot/uboot-envtools/files/ipq807x b/package/boot/uboot-envtools/files/qualcommax similarity index 67% rename from package/boot/uboot-envtools/files/ipq807x rename to package/boot/uboot-envtools/files/qualcommax index 6e4fadbdf..581f58b58 100644 --- a/package/boot/uboot-envtools/files/ipq807x +++ b/package/boot/uboot-envtools/files/qualcommax @@ -8,31 +8,38 @@ touch /etc/config/ubootenv board=$(board_name) case "$board" in -dynalink,dl-wrx36) - idx="$(find_mtd_index 0:appsblenv)" - [ -n "$idx" ] && \ - ubootenv_add_uci_config "/dev/mtd$idx" "0x0" "0x40000" "0x20000" "2" - ;; +compex,wpq873|\ edgecore,eap102|\ zyxel,nbg7815) idx="$(find_mtd_index 0:appsblenv)" [ -n "$idx" ] && \ ubootenv_add_uci_config "/dev/mtd$idx" "0x0" "0x10000" "0x10000" "1" ;; +dynalink,dl-wrx36|\ +netgear,rax120v2|\ +netgear,wax218|\ +netgear,wax620|\ +netgear,wax630) + idx="$(find_mtd_index 0:appsblenv)" + [ -n "$idx" ] && \ + ubootenv_add_uci_config "/dev/mtd$idx" "0x0" "0x40000" "0x20000" "2" + ;; edimax,cax1800) idx="$(find_mtd_index 0:appsblenv)" [ -n "$idx" ] && \ ubootenv_add_uci_config "/dev/mtd$idx" "0x0" "0x10000" "0x20000" ;; -redmi,ax6|\ -xiaomi,ax3600|\ -xiaomi,ax9000) - idx="$(find_mtd_index 0:appsblenv)" +linksys,mr7350|\ +linksys,mx4200v1|\ +linksys,mx4200v2) + idx="$(find_mtd_index u_env)" [ -n "$idx" ] && \ - ubootenv_add_uci_config "/dev/mtd$idx" "0x0" "0x10000" "0x20000" - idx2="$(find_mtd_index bdata)" - [ -n "$idx2" ] && \ - ubootenv_add_uci_sys_config "/dev/mtd$idx2" "0x0" "0x10000" "0x20000" + ubootenv_add_uci_config "/dev/mtd$idx" "0x0" "0x40000" "0x20000" "2" + ;; +prpl,haze) + mmcpart="$(find_mmc_part 0:APPSBLENV)" + [ -n "$mmcpart" ] && \ + ubootenv_add_uci_config "$mmcpart" "0x0" "0x40000" "0x400" "0x100" ;; qnap,301w) idx="$(find_mtd_index 0:appsblenv)" diff --git a/target/linux/ipq60xx/Makefile b/target/linux/ipq60xx/Makefile deleted file mode 100644 index 28941c44c..000000000 --- a/target/linux/ipq60xx/Makefile +++ /dev/null @@ -1,21 +0,0 @@ -include $(TOPDIR)/rules.mk - -ARCH:=aarch64 -BOARD:=ipq60xx -BOARDNAME:=Qualcomm Atheros IPQ60xx -FEATURES:=squashfs ramdisk fpu nand rtc emmc -KERNELNAME:=Image dtbs -CPU_TYPE:=cortex-a53 -SUBTARGETS:=generic - -KERNEL_PATCHVER:=5.15 - -include $(INCLUDE_DIR)/target.mk -DEFAULT_PACKAGES += \ - kmod-usb3 kmod-usb-dwc3 kmod-usb-dwc3-qcom \ - kmod-leds-gpio kmod-gpio-button-hotplug \ - uboot-envtools \ - kmod-qca-nss-dp kmod-qca-nss-drv-64 kmod-qca-nss-drv-pppoe-64 \ - nss-firmware-ipq6018 qca-nss-ecm-64 - -$(eval $(call BuildTarget)) diff --git a/target/linux/ipq60xx/base-files/etc/board.d/01_leds b/target/linux/ipq60xx/base-files/etc/board.d/01_leds deleted file mode 100644 index 9f1cec67c..000000000 --- a/target/linux/ipq60xx/base-files/etc/board.d/01_leds +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/sh -# -# Copyright (C) 2015 OpenWrt.org -# - -. /lib/functions/uci-defaults.sh - -board_config_update - -board=$(board_name) - -case "$board" in -cmiot,ax18|\ -zn,m2) - ucidef_set_led_netdev "wan" "WAN" "blue:wan" "eth0" - ucidef_set_led_netdev "wlan2g" "WLAN2G" "blue:wlan2g" "wlan1" - ucidef_set_led_netdev "wlan5g" "WLAN5G" "blue:wlan5g" "wlan0" - ;; -*) - ;; -esac - -board_config_flush - -exit 0 \ No newline at end of file diff --git a/target/linux/ipq60xx/base-files/etc/board.d/02_network b/target/linux/ipq60xx/base-files/etc/board.d/02_network deleted file mode 100644 index 6d7dda955..000000000 --- a/target/linux/ipq60xx/base-files/etc/board.d/02_network +++ /dev/null @@ -1,51 +0,0 @@ -. /lib/functions/uci-defaults.sh -. /lib/functions/system.sh - -setup_network() -{ - local macaddr - - case $(board_name) in - cmiot,ax18|\ - qihoo,v6|\ - zn,m2) - ucidef_set_interfaces_lan_wan "eth1 eth2 eth3" "eth0" - ;; - linksys,mr7350) - ucidef_set_interfaces_lan_wan "eth0 eth1 eth2 eth3" "eth4" - ;; - tplink,eap610-outdoor) - # /tmp/factory_data should be mounted by preinit - macaddr=$(get_mac_binary /tmp/factory_data/default-mac 0) - ucidef_set_interface_macaddr "lan" "$macaddr" - ucidef_set_interface_lan "eth0" "dhcp" - ;; - *) - ucidef_set_interface_lan "eth0" - ;; - esac -} - -setup_macs() -{ - case $(board_name) in - linksys,mr7350) - wan_mac=$(mtd_get_mac_ascii devinfo hw_mac_addr) - lan_mac=$(macaddr_add "$wan_mac" 1) - ;; - qihoo,v6) - lan_mac=$(mtd_get_mac_ascii factory lanMac) - wan_mac=$(macaddr_add "$lan_mac" 1) - ;; - esac - - [ -n "$lan_mac" ] && ucidef_set_interface_macaddr "lan" $lan_mac - [ -n "$wan_mac" ] && ucidef_set_interface_macaddr "wan" $wan_mac -} - -board_config_update -setup_network -setup_macs -board_config_flush - -exit 0 diff --git a/target/linux/ipq60xx/base-files/etc/hotplug.d/firmware/11-ath11k-caldata b/target/linux/ipq60xx/base-files/etc/hotplug.d/firmware/11-ath11k-caldata deleted file mode 100644 index b6a19f272..000000000 --- a/target/linux/ipq60xx/base-files/etc/hotplug.d/firmware/11-ath11k-caldata +++ /dev/null @@ -1,81 +0,0 @@ -#!/bin/sh - -[ -e /lib/firmware/$FIRMWARE ] && exit 0 - -. /lib/functions/caldata.sh -. /lib/functions/system.sh - -board=$(board_name) - -ath11k_generate_macs() { - case "$board" in - linksys,mr7350) - eth=$(mtd_get_mac_ascii devinfo hw_mac_addr) - ;; - *) - eth=$(cat /sys/class/net/eth0/address) - ;; - esac - - touch /lib/firmware/ath11k-macs - mac1=$(macaddr_add $eth 2) - mac2=$(macaddr_add $eth 3) - mac3=$(macaddr_add $eth 4) - echo -ne \\x${mac1//:/\\x} >> /lib/firmware/ath11k-macs - echo -ne \\x${mac2//:/\\x} >> /lib/firmware/ath11k-macs - echo -ne \\x${mac3//:/\\x} >> /lib/firmware/ath11k-macs -} - -ath11kcal_die() { - echo "ath11cal: " "$*" - exit 1 -} - -ath11kcal_extract() { - local part=$1 - local offset=$2 - local count=$3 - local mtd - - mtd=$(find_mtd_chardev $part) - [ -n "$mtd" ] || \ - ath11kcal_die "no mtd device found for partition $part" - - dd if=$mtd of=/lib/firmware/$FIRMWARE iflag=skip_bytes bs=$count skip=$offset count=1 2>/dev/null || \ - ath11kcal_die "failed to extract calibration data from $mtd" -} - -case "$FIRMWARE" in -"ath11k/IPQ6018/hw1.0/cal-ahb-c000000.wifi.bin") - case "$board" in - cmiot,ax18|\ - linksys,mr7350|\ - qihoo,v6|\ - zn,m2) - caldata_extract "0:art" 0x1000 0x10000 - ;; - tplink,eap610-outdoor) - # /tmp/factory_data should be mounted by preinit - cp /tmp/factory_data/radio "/lib/firmware/$FIRMWARE" - ;; - *) - caldata_die "Don't know how to read caldata for $board" - ;; - esac - ;; - -ath11k-macs) - case "$board" in - cmiot,ax18|\ - linksys,mr7350|\ - qihoo,v6|\ - zn,m2) - ath11k_generate_macs - ;; - esac - ;; - -*) - exit 1 - ;; -esac diff --git a/target/linux/ipq60xx/base-files/etc/hotplug.d/ieee80211/10-fix-mac-address b/target/linux/ipq60xx/base-files/etc/hotplug.d/ieee80211/10-fix-mac-address deleted file mode 100644 index 075c1d719..000000000 --- a/target/linux/ipq60xx/base-files/etc/hotplug.d/ieee80211/10-fix-mac-address +++ /dev/null @@ -1,16 +0,0 @@ -[ "$ACTION" == "add" ] || exit 0 - -PHY_NUM=${DEVPATH##*/phy} - -[ -n $PHY_NUM ] || exit 0 - -. /lib/functions.sh -. /lib/functions/system.sh - -case "$(board_name)" in -tplink,eap610-outdoor) - # /tmp/factory_data should have been mounted by preinit - base_mac=$(get_mac_binary /tmp/factory_data/default-mac 0) - macaddr_add $base_mac $(expr "$PHY_NUM" + 1) > /sys${DEVPATH}/macaddress - ;; -esac diff --git a/target/linux/ipq60xx/base-files/lib/preinit/69_mount_factory_data b/target/linux/ipq60xx/base-files/lib/preinit/69_mount_factory_data deleted file mode 100644 index 97608db55..000000000 --- a/target/linux/ipq60xx/base-files/lib/preinit/69_mount_factory_data +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/sh - -preinit_mount_factory_data() { - local mtd_path - - . /lib/functions.sh - . /lib/functions/system.sh - - case $(board_name) in - tplink,eap610-outdoor) - mtd_path=$(find_mtd_chardev "factory_data") - ubiattach --dev-path="$mtd_path" --devn=1 - mkdir /tmp/factory_data - mount -o ro,noatime -t ubifs ubi1:ubi_factory_data /tmp/factory_data - ;; - esac -} - -boot_hook_add preinit_main preinit_mount_factory_data diff --git a/target/linux/ipq60xx/base-files/lib/upgrade/platform.sh b/target/linux/ipq60xx/base-files/lib/upgrade/platform.sh deleted file mode 100644 index f781d8dc5..000000000 --- a/target/linux/ipq60xx/base-files/lib/upgrade/platform.sh +++ /dev/null @@ -1,104 +0,0 @@ - -PART_NAME=firmware -REQUIRE_IMAGE_METADATA=1 - -RAMFS_COPY_BIN='fw_printenv fw_setenv' -RAMFS_COPY_DATA='/etc/fw_env.config /var/lock/fw_printenv.lock' - -linksys_get_boot_part() { - local cur_boot_part - local args - - # Try to find rootfs from kernel arguments - read -r args < /proc/cmdline - for arg in $args; do - local ubi_mtd_arg=${arg#ubi.mtd=} - case "$ubi_mtd_arg" in - rootfs|alt_rootfs) - echo "$ubi_mtd_arg" - return - ;; - esac - done - - # Fallback to u-boot env (e.g. when running sysfs) - cur_boot_part="$(/usr/sbin/fw_printenv -n boot_part)" - case $cur_boot_part in - 1) - echo rootfs - ;; - 2|*) - echo alt_rootfs - ;; - esac -} - -linksys_prepare_ubi() { - local oem_ubivol - local mtdnum - local ubidev - - mtdnum=$(find_mtd_index "$CI_UBIPART") - if [ ! "$mtdnum" ]; then - return - fi - - ubidev=$(nand_find_ubi "$CI_UBIPART") - if [ ! "$ubidev" ]; then - ubiattach --mtdn="$mtdnum" - ubidev=$(nand_find_ubi "$CI_UBIPART") - fi - - if [ "$ubidev" ]; then - oem_ubivol=$(nand_find_volume "$ubidev" squashfs) - [ "$oem_ubivol" ] && ubirmvol "/dev/$ubidev" --name=squashfs - fi -} - -linksys_do_upgrade() { - local current_boot_slot - local new_boot_part - - current_boot_slot=$(linksys_get_boot_part) - case $current_boot_slot in - rootfs) - CI_UBIPART="alt_rootfs" - CI_KERNPART="alt_kernel" - new_boot_part=2 - ;; - alt_rootfs) - CI_UBIPART="rootfs" - CI_KERNPART="kernel" - new_boot_part=1 - ;; - esac - echo "Updating mtd=$CI_UBIPART, boot_part=$new_boot_part" - - fw_setenv -s - <<-EOF - boot_part $new_boot_part - auto_recovery yes - EOF - - linksys_prepare_ubi - nand_do_upgrade "$1" -} - -platform_check_image() { - return 0; -} - -platform_do_upgrade() { - case "$(board_name)" in - linksys,mr7350) - linksys_do_upgrade "$1" - ;; - cmiot,ax18|\ - qihoo,v6|\ - zn,m2) - nand_do_upgrade "$1" - ;; - *) - default_do_upgrade "$1" - ;; - esac -} \ No newline at end of file diff --git a/target/linux/ipq60xx/config-5.15 b/target/linux/ipq60xx/config-5.15 deleted file mode 100644 index 006f0ffa4..000000000 --- a/target/linux/ipq60xx/config-5.15 +++ /dev/null @@ -1,506 +0,0 @@ -CONFIG_64BIT=y -# CONFIG_APQ_GCC_8084 is not set -# CONFIG_APQ_MMCC_8084 is not set -CONFIG_AQUANTIA_PHY=y -CONFIG_ARCH_DMA_ADDR_T_64BIT=y -CONFIG_ARCH_HIBERNATION_POSSIBLE=y -CONFIG_ARCH_KEEP_MEMBLOCK=y -CONFIG_ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE=y -CONFIG_ARCH_MMAP_RND_BITS=18 -CONFIG_ARCH_MMAP_RND_BITS_MAX=24 -CONFIG_ARCH_MMAP_RND_BITS_MIN=18 -CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=11 -CONFIG_ARCH_PROC_KCORE_TEXT=y -CONFIG_ARCH_QCOM=y -CONFIG_ARCH_SPARSEMEM_ENABLE=y -CONFIG_ARCH_STACKWALK=y -CONFIG_ARCH_SUSPEND_POSSIBLE=y -CONFIG_ARCH_WANTS_NO_INSTR=y -CONFIG_ARM64=y -CONFIG_ARM64_4K_PAGES=y -CONFIG_ARM64_CRYPTO=y -CONFIG_ARM64_ERRATUM_1165522=y -CONFIG_ARM64_ERRATUM_1286807=y -CONFIG_ARM64_LD_HAS_FIX_ERRATUM_843419=y -CONFIG_ARM64_PAGE_SHIFT=12 -CONFIG_ARM64_PA_BITS=48 -CONFIG_ARM64_PA_BITS_48=y -CONFIG_ARM64_PTR_AUTH=y -CONFIG_ARM64_PTR_AUTH_KERNEL=y -CONFIG_ARM64_SVE=y -CONFIG_ARM64_TAGGED_ADDR_ABI=y -CONFIG_ARM64_VA_BITS=39 -CONFIG_ARM64_VA_BITS_39=y -CONFIG_ARM64_WORKAROUND_REPEAT_TLBI=y -CONFIG_ARM64_WORKAROUND_SPECULATIVE_AT=y -CONFIG_ARM_AMBA=y -CONFIG_ARM_ARCH_TIMER=y -CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y -CONFIG_ARM_CPUIDLE=y -CONFIG_ARM_GIC=y -CONFIG_ARM_GIC_V2M=y -CONFIG_ARM_GIC_V3=y -CONFIG_ARM_GIC_V3_ITS=y -CONFIG_ARM_GIC_V3_ITS_PCI=y -# CONFIG_ARM_MHU_V2 is not set -CONFIG_ARM_PSCI_CPUIDLE=y -CONFIG_ARM_PSCI_FW=y -# CONFIG_ARM_QCOM_CPUFREQ_HW is not set -# CONFIG_ARM_QCOM_CPUFREQ_NVMEM is not set -CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y -CONFIG_BLK_DEV_LOOP=y -CONFIG_BLK_DEV_SD=y -CONFIG_BLK_MQ_PCI=y -CONFIG_BLK_MQ_VIRTIO=y -CONFIG_BLK_PM=y -CONFIG_CAVIUM_TX2_ERRATUM_219=y -CONFIG_CC_HAVE_STACKPROTECTOR_SYSREG=y -CONFIG_CLONE_BACKWARDS=y -CONFIG_COMMON_CLK=y -CONFIG_COMMON_CLK_QCOM=y -# CONFIG_COMPAT_32BIT_TIME is not set -CONFIG_COREDUMP=y -CONFIG_CPUFREQ_DT=y -CONFIG_CPUFREQ_DT_PLATDEV=y -CONFIG_CPU_FREQ=y -# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set -CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL=y -CONFIG_CPU_FREQ_GOV_ATTR_SET=y -# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set -# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set -CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set -CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y -# CONFIG_CPU_FREQ_GOV_USERSPACE is not set -# CONFIG_CPU_FREQ_STAT is not set -CONFIG_CPU_FREQ_THERMAL=y -CONFIG_CPU_IDLE=y -CONFIG_CPU_IDLE_GOV_MENU=y -CONFIG_CPU_IDLE_MULTIPLE_DRIVERS=y -CONFIG_CPU_PM=y -CONFIG_CPU_RMAP=y -CONFIG_CPU_THERMAL=y -CONFIG_CRC16=y -CONFIG_CRC8=y -CONFIG_CRYPTO_AUTHENC=y -CONFIG_CRYPTO_CBC=y -CONFIG_CRYPTO_DEFLATE=y -CONFIG_CRYPTO_DEV_QCE=y -CONFIG_CRYPTO_DEV_QCE_AEAD=y -# CONFIG_CRYPTO_DEV_QCE_ENABLE_AEAD is not set -CONFIG_CRYPTO_DEV_QCE_ENABLE_ALL=y -# CONFIG_CRYPTO_DEV_QCE_ENABLE_SHA is not set -# CONFIG_CRYPTO_DEV_QCE_ENABLE_SKCIPHER is not set -CONFIG_CRYPTO_DEV_QCE_SHA=y -CONFIG_CRYPTO_DEV_QCE_SKCIPHER=y -CONFIG_CRYPTO_DEV_QCE_SW_MAX_LEN=512 -CONFIG_CRYPTO_DEV_QCOM_RNG=y -CONFIG_CRYPTO_ECB=y -CONFIG_CRYPTO_HASH_INFO=y -CONFIG_CRYPTO_HW=y -CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y -CONFIG_CRYPTO_LIB_DES=y -CONFIG_CRYPTO_LIB_SHA256=y -CONFIG_CRYPTO_LZO=y -CONFIG_CRYPTO_RNG=y -CONFIG_CRYPTO_RNG2=y -CONFIG_CRYPTO_SHA1=y -CONFIG_CRYPTO_SHA256=y -CONFIG_CRYPTO_XTS=y -CONFIG_CRYPTO_ZSTD=y -CONFIG_DCACHE_WORD_ACCESS=y -CONFIG_DEV_COREDUMP=y -CONFIG_DMADEVICES=y -CONFIG_DMA_DIRECT_REMAP=y -CONFIG_DMA_ENGINE=y -CONFIG_DMA_OF=y -CONFIG_DMA_REMAP=y -CONFIG_DMA_VIRTUAL_CHANNELS=y -CONFIG_DTC=y -CONFIG_DT_IDLE_STATES=y -CONFIG_EDAC_SUPPORT=y -CONFIG_FIXED_PHY=y -CONFIG_FIX_EARLYCON_MEM=y -CONFIG_FRAME_POINTER=y -CONFIG_FUJITSU_ERRATUM_010001=y -CONFIG_FWNODE_MDIO=y -CONFIG_FW_LOADER_PAGED_BUF=y -CONFIG_GENERIC_ALLOCATOR=y -CONFIG_GENERIC_ARCH_TOPOLOGY=y -CONFIG_GENERIC_BUG=y -CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y -CONFIG_GENERIC_CLOCKEVENTS=y -CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y -CONFIG_GENERIC_CPU_AUTOPROBE=y -CONFIG_GENERIC_CPU_VULNERABILITIES=y -CONFIG_GENERIC_CSUM=y -CONFIG_GENERIC_EARLY_IOREMAP=y -CONFIG_GENERIC_FIND_FIRST_BIT=y -CONFIG_GENERIC_GETTIMEOFDAY=y -CONFIG_GENERIC_IDLE_POLL_SETUP=y -CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y -CONFIG_GENERIC_IRQ_SHOW=y -CONFIG_GENERIC_IRQ_SHOW_LEVEL=y -CONFIG_GENERIC_LIB_DEVMEM_IS_ALLOWED=y -CONFIG_GENERIC_MSI_IRQ=y -CONFIG_GENERIC_MSI_IRQ_DOMAIN=y -CONFIG_GENERIC_PCI_IOMAP=y -CONFIG_GENERIC_PHY=y -CONFIG_GENERIC_PINCONF=y -CONFIG_GENERIC_PINCTRL_GROUPS=y -CONFIG_GENERIC_PINMUX_FUNCTIONS=y -CONFIG_GENERIC_SCHED_CLOCK=y -CONFIG_GENERIC_SMP_IDLE_THREAD=y -CONFIG_GENERIC_STRNCPY_FROM_USER=y -CONFIG_GENERIC_STRNLEN_USER=y -CONFIG_GENERIC_TIME_VSYSCALL=y -CONFIG_GLOB=y -CONFIG_GPIOLIB_IRQCHIP=y -CONFIG_GPIO_CDEV=y -CONFIG_HANDLE_DOMAIN_IRQ=y -CONFIG_HARDIRQS_SW_RESEND=y -CONFIG_HAS_DMA=y -CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT_MAP=y -CONFIG_HWSPINLOCK=y -CONFIG_HWSPINLOCK_QCOM=y -CONFIG_I2C=y -CONFIG_I2C_BOARDINFO=y -CONFIG_I2C_CHARDEV=y -CONFIG_I2C_HELPER_AUTO=y -# CONFIG_I2C_QCOM_CCI is not set -CONFIG_I2C_QUP=y -CONFIG_IIO=y -CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000 -CONFIG_INITRAMFS_SOURCE="" -CONFIG_IPQ_APSS_6018=y -# CONFIG_IPQ_APSS_8074 is not set -CONFIG_IPQ_APSS_PLL=y -# CONFIG_IPQ_GCC_4019 is not set -CONFIG_IPQ_GCC_6018=y -# CONFIG_IPQ_GCC_806X is not set -# CONFIG_IPQ_GCC_8074 is not set -# CONFIG_IPQ_LCC_806X is not set -CONFIG_IRQCHIP=y -CONFIG_IRQ_DOMAIN=y -CONFIG_IRQ_DOMAIN_HIERARCHY=y -CONFIG_IRQ_FASTEOI_HIERARCHY_HANDLERS=y -CONFIG_IRQ_FORCED_THREADING=y -CONFIG_IRQ_WORK=y -# CONFIG_KPSS_XCC is not set -CONFIG_LIBFDT=y -CONFIG_LOCK_DEBUGGING_SUPPORT=y -CONFIG_LOCK_SPIN_ON_OWNER=y -CONFIG_LZO_COMPRESS=y -CONFIG_LZO_DECOMPRESS=y -CONFIG_MAILBOX=y -# CONFIG_MAILBOX_TEST is not set -CONFIG_MDIO_BUS=y -CONFIG_MDIO_DEVICE=y -CONFIG_MDIO_DEVRES=y -CONFIG_MDIO_IPQ4019=y -# CONFIG_MDM_GCC_9615 is not set -# CONFIG_MDM_LCC_9615 is not set -CONFIG_MEMFD_CREATE=y -# CONFIG_MFD_HI6421_SPMI is not set -# CONFIG_MFD_QCOM_RPM is not set -CONFIG_MFD_SPMI_PMIC=y -CONFIG_MFD_SYSCON=y -CONFIG_MIGRATION=y -CONFIG_MMC=y -CONFIG_MMC_BLOCK=y -CONFIG_MMC_BLOCK_MINORS=32 -CONFIG_MMC_CQHCI=y -CONFIG_MMC_SDHCI=y -CONFIG_MMC_SDHCI_IO_ACCESSORS=y -CONFIG_MMC_SDHCI_MSM=y -# CONFIG_MMC_SDHCI_PCI is not set -CONFIG_MMC_SDHCI_PLTFM=y -CONFIG_MODULES_USE_ELF_RELA=y -# CONFIG_MSM_GCC_8660 is not set -# CONFIG_MSM_GCC_8916 is not set -# CONFIG_MSM_GCC_8939 is not set -# CONFIG_MSM_GCC_8960 is not set -# CONFIG_MSM_GCC_8974 is not set -# CONFIG_MSM_GCC_8994 is not set -# CONFIG_MSM_GCC_8996 is not set -# CONFIG_MSM_GCC_8998 is not set -# CONFIG_MSM_GPUCC_8998 is not set -# CONFIG_MSM_LCC_8960 is not set -# CONFIG_MSM_MMCC_8960 is not set -# CONFIG_MSM_MMCC_8974 is not set -# CONFIG_MSM_MMCC_8996 is not set -# CONFIG_MSM_MMCC_8998 is not set -CONFIG_MTD_NAND_CORE=y -CONFIG_MTD_NAND_ECC=y -CONFIG_MTD_NAND_ECC_SW_HAMMING=y -CONFIG_MTD_NAND_QCOM=y -CONFIG_MTD_QCOMSMEM_PARTS=y -CONFIG_MTD_RAW_NAND=y -CONFIG_MTD_SPI_NOR=y -CONFIG_MTD_UBI=y -CONFIG_MTD_UBI_BEB_LIMIT=20 -CONFIG_MTD_UBI_BLOCK=y -CONFIG_MTD_UBI_WL_THRESHOLD=4096 -CONFIG_MUTEX_SPIN_ON_OWNER=y -CONFIG_NEED_DMA_MAP_STATE=y -CONFIG_NEED_SG_DMA_LENGTH=y -CONFIG_NET_FLOW_LIMIT=y -CONFIG_NET_SELFTESTS=y -CONFIG_NET_SWITCHDEV=y -CONFIG_NLS=y -CONFIG_NO_HZ_COMMON=y -CONFIG_NO_HZ_IDLE=y -CONFIG_NR_CPUS=4 -CONFIG_NVIDIA_CARMEL_CNP_ERRATUM=y -CONFIG_NVMEM=y -# CONFIG_NVMEM_SPMI_SDAM is not set -CONFIG_NVMEM_SYSFS=y -CONFIG_OF=y -CONFIG_OF_ADDRESS=y -CONFIG_OF_EARLY_FLATTREE=y -CONFIG_OF_FLATTREE=y -CONFIG_OF_GPIO=y -CONFIG_OF_IRQ=y -CONFIG_OF_KOBJ=y -CONFIG_OF_MDIO=y -CONFIG_PADATA=y -CONFIG_PARTITION_PERCPU=y -CONFIG_PCI=y -CONFIG_PCIEAER=y -CONFIG_PCIEASPM=y -CONFIG_PCIEASPM_DEFAULT=y -# CONFIG_PCIEASPM_PERFORMANCE is not set -# CONFIG_PCIEASPM_POWERSAVE is not set -# CONFIG_PCIEASPM_POWER_SUPERSAVE is not set -CONFIG_PCIEPORTBUS=y -CONFIG_PCIE_DW=y -CONFIG_PCIE_DW_HOST=y -CONFIG_PCIE_PME=y -CONFIG_PCIE_QCOM=y -CONFIG_PCI_DOMAINS=y -CONFIG_PCI_DOMAINS_GENERIC=y -CONFIG_PCI_MSI=y -CONFIG_PCI_MSI_IRQ_DOMAIN=y -CONFIG_PGTABLE_LEVELS=3 -CONFIG_PHYLIB=y -CONFIG_PHYS_ADDR_T_64BIT=y -# CONFIG_PHY_QCOM_APQ8064_SATA is not set -# CONFIG_PHY_QCOM_IPQ4019_USB is not set -# CONFIG_PHY_QCOM_IPQ806X_SATA is not set -# CONFIG_PHY_QCOM_IPQ806X_USB is not set -# CONFIG_PHY_QCOM_PCIE2 is not set -CONFIG_PHY_QCOM_QMP=y -CONFIG_PHY_QCOM_QUSB2=y -# CONFIG_PHY_QCOM_USB_HS_28NM is not set -# CONFIG_PHY_QCOM_USB_SNPS_FEMTO_V2 is not set -# CONFIG_PHY_QCOM_USB_SS is not set -CONFIG_PINCTRL=y -# CONFIG_PINCTRL_APQ8064 is not set -# CONFIG_PINCTRL_APQ8084 is not set -# CONFIG_PINCTRL_IPQ4019 is not set -CONFIG_PINCTRL_IPQ6018=y -# CONFIG_PINCTRL_IPQ8064 is not set -# CONFIG_PINCTRL_IPQ8074 is not set -# CONFIG_PINCTRL_MDM9615 is not set -CONFIG_PINCTRL_MSM=y -# CONFIG_PINCTRL_MSM8226 is not set -# CONFIG_PINCTRL_MSM8660 is not set -# CONFIG_PINCTRL_MSM8916 is not set -# CONFIG_PINCTRL_MSM8960 is not set -# CONFIG_PINCTRL_MSM8976 is not set -# CONFIG_PINCTRL_MSM8994 is not set -# CONFIG_PINCTRL_MSM8996 is not set -# CONFIG_PINCTRL_MSM8998 is not set -CONFIG_PINCTRL_QCOM_SPMI_PMIC=y -# CONFIG_PINCTRL_QCOM_SSBI_PMIC is not set -# CONFIG_PINCTRL_QCS404 is not set -# CONFIG_PINCTRL_SC7180 is not set -# CONFIG_PINCTRL_SDM660 is not set -# CONFIG_PINCTRL_SDM845 is not set -# CONFIG_PINCTRL_SM8150 is not set -# CONFIG_PINCTRL_SM8250 is not set -CONFIG_PM=y -# CONFIG_PM8916_WATCHDOG is not set -CONFIG_PM_CLK=y -CONFIG_PM_OPP=y -CONFIG_POWER_RESET=y -# CONFIG_POWER_RESET_MSM is not set -# CONFIG_POWER_RESET_QCOM_PON is not set -CONFIG_POWER_SUPPLY=y -CONFIG_PRINTK_TIME=y -CONFIG_PTP_1588_CLOCK_OPTIONAL=y -# CONFIG_QCOM_A53PLL is not set -# CONFIG_QCOM_AOSS_QMP is not set -CONFIG_QCOM_APCS_IPC=y -CONFIG_QCOM_APM=y -# CONFIG_QCOM_APR is not set -CONFIG_QCOM_BAM_DMA=y -# CONFIG_QCOM_CLK_APCC_MSM8996 is not set -# CONFIG_QCOM_CLK_APCS_MSM8916 is not set -# CONFIG_QCOM_CLK_APCS_SDX55 is not set -CONFIG_QCOM_CLK_SMD_RPM=y -# CONFIG_QCOM_COINCELL is not set -# CONFIG_QCOM_COMMAND_DB is not set -# CONFIG_QCOM_CPR is not set -# CONFIG_QCOM_EBI2 is not set -# CONFIG_QCOM_FASTRPC is not set -# CONFIG_QCOM_GENI_SE is not set -# CONFIG_QCOM_GSBI is not set -# CONFIG_QCOM_HFPLL is not set -# CONFIG_QCOM_IPCC is not set -# CONFIG_QCOM_LLCC is not set -CONFIG_QCOM_MDT_LOADER=y -# CONFIG_QCOM_OCMEM is not set -# CONFIG_QCOM_PDC is not set -CONFIG_QCOM_PIL_INFO=y -# CONFIG_QCOM_Q6V5_ADSP is not set -CONFIG_QCOM_Q6V5_COMMON=y -# CONFIG_QCOM_Q6V5_MSS is not set -# CONFIG_QCOM_Q6V5_PAS is not set -CONFIG_QCOM_Q6V5_WCSS=y -CONFIG_QCOM_QFPROM=y -# CONFIG_QCOM_RMTFS_MEM is not set -CONFIG_QCOM_RPMCC=y -# CONFIG_QCOM_RPMH is not set -CONFIG_QCOM_RPMPD=y -CONFIG_QCOM_RPROC_COMMON=y -CONFIG_QCOM_SCM=y -# CONFIG_QCOM_SCM_DOWNLOAD_MODE_DEFAULT is not set -CONFIG_QCOM_SMD_RPM=y -CONFIG_QCOM_SMEM=y -CONFIG_QCOM_SMEM_STATE=y -CONFIG_QCOM_SMP2P=y -# CONFIG_QCOM_SMSM is not set -CONFIG_QCOM_SOCINFO=y -CONFIG_QCOM_SPMI_ADC5=y -# CONFIG_QCOM_SYSMON is not set -CONFIG_QCOM_TSENS=y -CONFIG_QCOM_VADC_COMMON=y -# CONFIG_QCOM_WCNSS_CTRL is not set -# CONFIG_QCOM_WCNSS_PIL is not set -CONFIG_QCOM_WDT=y -# CONFIG_QCS_GCC_404 is not set -# CONFIG_QCS_Q6SSTOP_404 is not set -# CONFIG_QCS_TURING_404 is not set -CONFIG_QUEUED_RWLOCKS=y -CONFIG_QUEUED_SPINLOCKS=y -CONFIG_RAS=y -CONFIG_RATIONAL=y -CONFIG_REGMAP=y -CONFIG_REGMAP_MMIO=y -CONFIG_REGMAP_SPMI=y -CONFIG_REGULATOR=y -CONFIG_REGULATOR_CPR3=y -# CONFIG_REGULATOR_CPR3_NPU is not set -CONFIG_REGULATOR_CPR4_APSS=y -# CONFIG_REGULATOR_QCOM_LABIBB is not set -CONFIG_REGULATOR_QCOM_SMD_RPM=y -CONFIG_REGULATOR_QCOM_SPMI=y -# CONFIG_REGULATOR_QCOM_USB_VBUS is not set -# CONFIG_REGULATOR_VQMMC_IPQ4019 is not set -CONFIG_RELOCATABLE=y -CONFIG_REMOTEPROC=y -CONFIG_REMOTEPROC_CDEV=y -CONFIG_RESET_CONTROLLER=y -# CONFIG_RESET_QCOM_AOSS is not set -# CONFIG_RESET_QCOM_PDC is not set -CONFIG_RFS_ACCEL=y -CONFIG_RODATA_FULL_DEFAULT_ENABLED=y -CONFIG_RPMSG=y -CONFIG_RPMSG_CHAR=y -# CONFIG_RPMSG_NS is not set -CONFIG_RPMSG_QCOM_GLINK=y -CONFIG_RPMSG_QCOM_GLINK_RPM=y -CONFIG_RPMSG_QCOM_GLINK_SMEM=y -CONFIG_RPMSG_QCOM_SMD=y -CONFIG_RPS=y -CONFIG_RTC_CLASS=y -CONFIG_RTC_DRV_PM8XXX=y -CONFIG_RTC_I2C_AND_SPI=y -CONFIG_RWSEM_SPIN_ON_OWNER=y -# CONFIG_SCHED_CORE is not set -CONFIG_SCHED_MC=y -CONFIG_SCHED_SMT=y -CONFIG_SCHED_THERMAL_PRESSURE=y -CONFIG_SCSI=y -CONFIG_SCSI_COMMON=y -# CONFIG_SCSI_LOWLEVEL is not set -# CONFIG_SCSI_PROC_FS is not set -# CONFIG_SC_DISPCC_7180 is not set -# CONFIG_SC_GCC_7180 is not set -# CONFIG_SC_GPUCC_7180 is not set -# CONFIG_SC_LPASS_CORECC_7180 is not set -# CONFIG_SC_MSS_7180 is not set -# CONFIG_SC_VIDEOCC_7180 is not set -# CONFIG_SDM_CAMCC_845 is not set -# CONFIG_SDM_DISPCC_845 is not set -# CONFIG_SDM_GCC_660 is not set -# CONFIG_SDM_GCC_845 is not set -# CONFIG_SDM_GPUCC_845 is not set -# CONFIG_SDM_LPASSCC_845 is not set -# CONFIG_SDM_VIDEOCC_845 is not set -CONFIG_SERIAL_8250_FSL=y -CONFIG_SERIAL_MCTRL_GPIO=y -CONFIG_SERIAL_MSM=y -CONFIG_SERIAL_MSM_CONSOLE=y -CONFIG_SGL_ALLOC=y -CONFIG_SG_POOL=y -CONFIG_SMP=y -# CONFIG_SM_GCC_8150 is not set -# CONFIG_SM_GCC_8250 is not set -# CONFIG_SM_GPUCC_8150 is not set -# CONFIG_SM_GPUCC_8250 is not set -# CONFIG_SM_VIDEOCC_8150 is not set -# CONFIG_SM_VIDEOCC_8250 is not set -CONFIG_SOCK_RX_QUEUE_MAPPING=y -CONFIG_SOC_BUS=y -CONFIG_SPARSEMEM=y -CONFIG_SPARSEMEM_EXTREME=y -CONFIG_SPARSEMEM_VMEMMAP=y -CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y -CONFIG_SPARSE_IRQ=y -CONFIG_SPI=y -CONFIG_SPI_MASTER=y -CONFIG_SPI_MEM=y -CONFIG_SPI_QUP=y -CONFIG_SPMI=y -# CONFIG_SPMI_HISI3670 is not set -CONFIG_SPMI_MSM_PMIC_ARB=y -# CONFIG_SPMI_PMIC_CLKDIV is not set -CONFIG_SRCU=y -CONFIG_SWIOTLB=y -CONFIG_SWPHY=y -CONFIG_SYSCTL_EXCEPTION_TRACE=y -CONFIG_THERMAL=y -CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y -CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0 -CONFIG_THERMAL_GOV_STEP_WISE=y -CONFIG_THERMAL_OF=y -CONFIG_THREAD_INFO_IN_TASK=y -CONFIG_TICK_CPU_ACCOUNTING=y -CONFIG_TIMER_OF=y -CONFIG_TIMER_PROBE=y -CONFIG_TREE_RCU=y -CONFIG_TREE_SRCU=y -CONFIG_UBIFS_FS=y -CONFIG_UBIFS_FS_ADVANCED_COMPR=y -# CONFIG_UCLAMP_TASK is not set -CONFIG_UNMAP_KERNEL_AT_EL0=y -CONFIG_USB=y -CONFIG_USB_COMMON=y -CONFIG_USB_SUPPORT=y -CONFIG_VIRTIO=y -# CONFIG_VIRTIO_BLK is not set -# CONFIG_VIRTIO_NET is not set -CONFIG_VMAP_STACK=y -CONFIG_WANT_DEV_COREDUMP=y -CONFIG_WATCHDOG_CORE=y -CONFIG_WATCHDOG_SYSFS=y -CONFIG_XPS=y -CONFIG_XXHASH=y -CONFIG_ZLIB_DEFLATE=y -CONFIG_ZLIB_INFLATE=y -CONFIG_ZONE_DMA32=y -CONFIG_ZSTD_COMPRESS=y -CONFIG_ZSTD_DECOMPRESS=y diff --git a/target/linux/ipq60xx/files/arch/arm64/boot/dts/qcom/ipq6018-ax18.dts b/target/linux/ipq60xx/files/arch/arm64/boot/dts/qcom/ipq6018-ax18.dts deleted file mode 100644 index bf902da82..000000000 --- a/target/linux/ipq60xx/files/arch/arm64/boot/dts/qcom/ipq6018-ax18.dts +++ /dev/null @@ -1,67 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0+) - -/dts-v1/; - -#include "ipq6018-cmiot.dtsi" - -/ { - model = "CMIOT AX18"; - compatible = "cmiot,ax18", "qcom,ipq6018"; - - aliases { - led-boot = &led_power; - led-failsafe = &led_power; - led-running = &led_power; - led-upgrade = &led_power; - }; - - leds { - compatible = "gpio-leds"; - pinctrl-0 = <&leds_pins>; - pinctrl-names = "default"; - - led_power: power { - label = "ax18:blue:power"; - gpio = <&tlmm 73 GPIO_ACTIVE_HIGH>; - }; - - wan { - label = "ax18:blue:wan"; - gpio = <&tlmm 74 GPIO_ACTIVE_HIGH>; - }; - - wlan2g { - label = "ax18:blue:wlan2g"; - gpio = <&tlmm 37 GPIO_ACTIVE_HIGH>; - }; - - wlan5g { - label = "ax18:blue:wlan5g"; - gpio = <&tlmm 35 GPIO_ACTIVE_HIGH>; - }; - - wps { - label = "ax18:red:wps"; - gpio = <&tlmm 69 GPIO_ACTIVE_HIGH>; - }; - }; -}; - -&tlmm { - leds_pins: leds_pins { - mux_0 { - pins = "gpio35", "gpio37", - "gpio69", "gpio74"; - function = "gpio"; - drive-strength = <8>; - bias-pull-down; - }; - - mux_1 { - pins = "gpio73"; - function = "gpio"; - drive-strength = <8>; - bias-pull-up; - }; - }; -}; diff --git a/target/linux/ipq60xx/files/arch/arm64/boot/dts/qcom/ipq6018-cmiot.dtsi b/target/linux/ipq60xx/files/arch/arm64/boot/dts/qcom/ipq6018-cmiot.dtsi deleted file mode 100644 index de514efab..000000000 --- a/target/linux/ipq60xx/files/arch/arm64/boot/dts/qcom/ipq6018-cmiot.dtsi +++ /dev/null @@ -1,200 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0+) - -/dts-v1/; - -#include "ipq6018.dtsi" -#include "ipq6018-upstreamable.dtsi" -#include "ipq6018-ess.dtsi" - -#include -#include - -/ { - qcom,msm-id = <0x192 0x0>; - - aliases { - serial0 = &blsp1_uart3; - - /* Aliases as required by u-boot to patch MAC addresses */ - ethernet0 = &dp1; - ethernet1 = &dp2; - ethernet2 = &dp3; - ethernet3 = &dp4; - }; - - chosen { - bootargs-append = " root=/dev/ubiblock0_1 swiotlb=1"; - }; - - keys { - compatible = "gpio-keys"; - - reset { - label = "reset"; - gpios = <&tlmm 60 GPIO_ACTIVE_LOW>; - linux,code = ; - }; - - wps { - label = "wps"; - gpios = <&tlmm 9 GPIO_ACTIVE_LOW>; - linux,code = ; - }; - }; -}; - -&blsp1_uart3 { - pinctrl-0 = <&serial_3_pins>; - pinctrl-names = "default"; - status = "okay"; -}; - -&tlmm { - mdio_pins: mdio-pins { - mdc { - pins = "gpio64"; - function = "mdc"; - drive-strength = <8>; - bias-pull-up; - }; - - mdio { - pins = "gpio65"; - function = "mdio"; - drive-strength = <8>; - bias-pull-up; - }; - }; - - button_pins: button_pins { - wps_button { - pins = "gpio9"; - function = "gpio"; - drive-strength = <8>; - bias-pull-up; - }; - - reset_button { - pins = "gpio60"; - function = "gpio"; - drive-strength = <8>; - bias-pull-up; - }; - }; -}; - -&soc { - dp1: dp@1 { - compatible = "qcom,nss-dp"; - reg = <0x0 0x3a001000 0x0 0x200>; - qcom,mactype = <0>; - qcom,id = <5>; - local-mac-address = [000000000000]; - phy-handle = <&phy_0>; - phy-mode = "sgmii"; - }; - - dp2: dp2 { - compatible = "qcom,nss-dp"; - reg = <0x0 0x3a001200 0x0 0x200>; - qcom,mactype = <0>; - qcom,id = <1>; - local-mac-address = [000000000000]; - phy-handle = <&phy_1>; - phy-mode = "sgmii"; - }; - - dp3: dp3 { - compatible = "qcom,nss-dp"; - reg = <0x0 0x3a001400 0x0 0x200>; - qcom,mactype = <0>; - qcom,id = <2>; - local-mac-address = [000000000000]; - phy-handle = <&phy_2>; - phy-mode = "sgmii"; - }; - - dp4: dp4 { - compatible = "qcom,nss-dp"; - reg = <0x0 0x3a001600 0x0 0x200>; - qcom,mactype = <0>; - qcom,id = <4>; - local-mac-address = [000000000000]; - phy-handle = <&phy_3>; - phy-mode = "sgmii"; - }; -}; - -&edma { - status = "okay"; -}; - -&mdio { - status = "okay"; - pinctrl-0 = <&mdio_pins>; - pinctrl-names = "default"; - reset-gpios = <&tlmm 75 GPIO_ACTIVE_LOW>; - - phy_0: ethernet-phy@0 { - reg = <4>; - }; - - phy_1: ethernet-phy@1 { - reg = <0>; - }; - - phy_2: ethernet-phy@2 { - reg = <1>; - }; - - phy_3: ethernet-phy@3 { - reg = <3>; - }; -}; - -&switch { - status = "okay"; - - switch_mac_mode = <0x0>; /* mac mode for uniphy instance0*/ - switch_mac_mode1 = <0xff>; /* mac mode for uniphy instance1*/ - switch_mac_mode2 = <0xff>; /* mac mode for uniphy instance2*/ - - qcom,port_phyinfo { - port@0 { - port_id = <0x01>; - phy_address = <0x00>; - }; - port@1 { - port_id = <0x02>; - phy_address = <0x01>; - }; - port@2 { - port_id = <0x04>; - phy_address = <0x03>; - }; - port@3 { - port_id = <0x05>; - phy_address = <0x04>; - }; - }; -}; - -&qpic_bam { - status = "okay"; -}; - -&qpic_nand { - status = "okay"; - - nand@0 { - reg = <0>; - - nand-ecc-strength = <4>; - nand-ecc-step-size = <512>; - nand-bus-width = <8>; - }; -}; - -&wifi { - status = "okay"; -}; diff --git a/target/linux/ipq60xx/files/arch/arm64/boot/dts/qcom/ipq6018-eap610-outdoor.dts b/target/linux/ipq60xx/files/arch/arm64/boot/dts/qcom/ipq6018-eap610-outdoor.dts deleted file mode 100644 index 26f5deb62..000000000 --- a/target/linux/ipq60xx/files/arch/arm64/boot/dts/qcom/ipq6018-eap610-outdoor.dts +++ /dev/null @@ -1,136 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0+) - -/dts-v1/; - -#include "ipq6018.dtsi" -#include "ipq6018-upstreamable.dtsi" -#include "ipq6018-ess.dtsi" - -#include -#include - -/ { - model = "TP-Link EAP610-Outdoor"; - compatible = "tplink,eap610-outdoor", "qcom,ipq6018"; - - aliases { - serial0 = &blsp1_uart3; - led-boot = &led_power; - led-failsafe = &led_power; - led-running = &led_power; - led-upgrade = &led_power; - }; - - chosen { - stdout-path = "serial0:115200n8"; - }; - - keys { - compatible = "gpio-keys"; - - reset { - label = "reset"; - gpios = <&tlmm 9 GPIO_ACTIVE_LOW>; - linux,code = ; - }; - }; - - leds { - compatible = "gpio-leds"; - - led_power: led-1 { - label = "green:power"; - gpios = <&tlmm 36 GPIO_ACTIVE_HIGH>; - }; - }; -}; - -&blsp1_uart3 { - pinctrl-0 = <&serial_3_pins>; - pinctrl-names = "default"; - status = "okay"; -}; - -&tlmm { - mdio_pins: mdio-pins { - mdc { - pins = "gpio64"; - function = "mdc"; - drive-strength = <8>; - bias-pull-up; - }; - - mdio { - pins = "gpio65"; - function = "mdio"; - drive-strength = <8>; - bias-pull-up; - }; - }; -}; - -&soc { - dp5: dp@5 { - compatible = "qcom,nss-dp"; - reg = <0x0 0x3a001800 0x0 0x200>; - qcom,mactype = <0>; - qcom,id = <5>; - - phy-handle = <&rtl8211f_4>; - phy-mode = "sgmii"; - }; -}; - -&edma { - status = "okay"; -}; - -&mdio { - status = "okay"; - pinctrl-0 = <&mdio_pins>; - pinctrl-names = "default"; - phy-reset-gpio = <&tlmm 0x4b GPIO_ACTIVE_HIGH>; - - rtl8211f_4: ethernet-phy@4 { - reg = <4>; - reset-gpios = <&tlmm 77 GPIO_ACTIVE_LOW>; - }; -}; - -&switch { - status = "okay"; - - switch_lan_bmp = <0x20>; - switch_wan_bmp = <0x20>; - switch_mac_mode = <0xff>; - switch_mac_mode1 = <0x0f>; - switch_mac_mode2 = <0xff>; - - qcom,port_phyinfo { - port@4 { - port_id = <0x05>; - phy_address = <0x04>; - port_mac_sel = "QGMAC_PORT"; - }; - }; -}; - -&qpic_bam { - status = "okay"; -}; - -&qpic_nand { - status = "okay"; - - nand@0 { - reg = <0>; - - nand-ecc-strength = <4>; - nand-ecc-step-size = <512>; - nand-bus-width = <8>; - }; -}; - -&wifi { - status = "okay"; -}; diff --git a/target/linux/ipq60xx/files/arch/arm64/boot/dts/qcom/ipq6018-ess.dtsi b/target/linux/ipq60xx/files/arch/arm64/boot/dts/qcom/ipq6018-ess.dtsi deleted file mode 100644 index a7a54a886..000000000 --- a/target/linux/ipq60xx/files/arch/arm64/boot/dts/qcom/ipq6018-ess.dtsi +++ /dev/null @@ -1,412 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0+) - -&soc { - switch: ess-switch@3a000000 { - compatible = "qcom,ess-switch-ipq60xx"; - reg = <0x3a000000 0x1000000>; - switch_access_mode = "local bus"; - mdio-bus = <&mdio>; - status = "disabled"; - - switch_cpu_bmp = <0x1>; - switch_inner_bmp = <0xc0>; - bm_tick_mode = <0>; - tm_tick_mode = <0>; - - clocks = <&gcc GCC_CMN_12GPLL_AHB_CLK>, - <&gcc GCC_CMN_12GPLL_SYS_CLK>, - <&gcc GCC_UNIPHY0_AHB_CLK>, - <&gcc GCC_UNIPHY0_SYS_CLK>, - <&gcc GCC_UNIPHY1_AHB_CLK>, - <&gcc GCC_UNIPHY1_SYS_CLK>, - <&gcc GCC_PORT1_MAC_CLK>, - <&gcc GCC_PORT2_MAC_CLK>, - <&gcc GCC_PORT3_MAC_CLK>, - <&gcc GCC_PORT4_MAC_CLK>, - <&gcc GCC_PORT5_MAC_CLK>, - <&gcc GCC_NSS_PPE_CLK>, - <&gcc GCC_NSS_PPE_CFG_CLK>, - <&gcc GCC_NSSNOC_PPE_CLK>, - <&gcc GCC_NSSNOC_PPE_CFG_CLK>, - <&gcc GCC_NSS_EDMA_CLK>, - <&gcc GCC_NSS_EDMA_CFG_CLK>, - <&gcc GCC_NSS_PPE_IPE_CLK>, - <&gcc GCC_MDIO_AHB_CLK>, - <&gcc GCC_NSS_NOC_CLK>, - <&gcc GCC_NSSNOC_SNOC_CLK>, - <&gcc GCC_NSS_CRYPTO_CLK>, - <&gcc GCC_NSS_PTP_REF_CLK>, - <&gcc GCC_NSS_PORT1_RX_CLK>, - <&gcc GCC_NSS_PORT1_TX_CLK>, - <&gcc GCC_NSS_PORT2_RX_CLK>, - <&gcc GCC_NSS_PORT2_TX_CLK>, - <&gcc GCC_NSS_PORT3_RX_CLK>, - <&gcc GCC_NSS_PORT3_TX_CLK>, - <&gcc GCC_NSS_PORT4_RX_CLK>, - <&gcc GCC_NSS_PORT4_TX_CLK>, - <&gcc GCC_NSS_PORT5_RX_CLK>, - <&gcc GCC_NSS_PORT5_TX_CLK>, - <&gcc GCC_UNIPHY0_PORT1_RX_CLK>, - <&gcc GCC_UNIPHY0_PORT1_TX_CLK>, - <&gcc GCC_UNIPHY0_PORT2_RX_CLK>, - <&gcc GCC_UNIPHY0_PORT2_TX_CLK>, - <&gcc GCC_UNIPHY0_PORT3_RX_CLK>, - <&gcc GCC_UNIPHY0_PORT3_TX_CLK>, - <&gcc GCC_UNIPHY0_PORT4_RX_CLK>, - <&gcc GCC_UNIPHY0_PORT4_TX_CLK>, - <&gcc GCC_UNIPHY0_PORT5_RX_CLK>, - <&gcc GCC_UNIPHY0_PORT5_TX_CLK>, - <&gcc GCC_UNIPHY1_PORT5_RX_CLK>, - <&gcc GCC_UNIPHY1_PORT5_TX_CLK>, - <&gcc NSS_PORT5_RX_CLK_SRC>, - <&gcc NSS_PORT5_TX_CLK_SRC>, - <&gcc GCC_SNOC_NSSNOC_CLK>; - clock-names = "cmn_ahb_clk", "cmn_sys_clk", "uniphy0_ahb_clk", - "uniphy0_sys_clk", "uniphy1_ahb_clk", - "uniphy1_sys_clk", "port1_mac_clk", - "port2_mac_clk", "port3_mac_clk", "port4_mac_clk", - "port5_mac_clk", "nss_ppe_clk", "nss_ppe_cfg_clk", - "nssnoc_ppe_clk", "nssnoc_ppe_cfg_clk", - "nss_edma_clk", "nss_edma_cfg_clk", - "nss_ppe_ipe_clk", "gcc_mdio_ahb_clk", - "gcc_nss_noc_clk", "gcc_nssnoc_snoc_clk", - "gcc_nss_crypto_clk", "gcc_nss_ptp_ref_clk", - "nss_port1_rx_clk", "nss_port1_tx_clk", - "nss_port2_rx_clk", "nss_port2_tx_clk", - "nss_port3_rx_clk", "nss_port3_tx_clk", - "nss_port4_rx_clk", "nss_port4_tx_clk", - "nss_port5_rx_clk", "nss_port5_tx_clk", - "uniphy0_port1_rx_clk", "uniphy0_port1_tx_clk", - "uniphy0_port2_rx_clk", "uniphy0_port2_tx_clk", - "uniphy0_port3_rx_clk", "uniphy0_port3_tx_clk", - "uniphy0_port4_rx_clk", "uniphy0_port4_tx_clk", - "uniphy0_port5_rx_clk", "uniphy0_port5_tx_clk", - "uniphy1_port5_rx_clk", "uniphy1_port5_tx_clk", - "nss_port5_rx_clk_src", "nss_port5_tx_clk_src", - "gcc_snoc_nssnoc_clk"; - resets = <&gcc GCC_PPE_FULL_RESET>, - <&gcc GCC_UNIPHY0_SOFT_RESET>, - <&gcc GCC_UNIPHY0_XPCS_RESET>, - <&gcc GCC_UNIPHY1_SOFT_RESET>, - <&gcc GCC_UNIPHY1_XPCS_RESET>, - <&gcc GCC_NSSPORT1_RESET>, - <&gcc GCC_NSSPORT2_RESET>, - <&gcc GCC_NSSPORT3_RESET>, - <&gcc GCC_NSSPORT4_RESET>, - <&gcc GCC_NSSPORT5_RESET>, - <&gcc GCC_UNIPHY0_PORT1_ARES>, - <&gcc GCC_UNIPHY0_PORT2_ARES>, - <&gcc GCC_UNIPHY0_PORT3_ARES>, - <&gcc GCC_UNIPHY0_PORT4_ARES>, - <&gcc GCC_UNIPHY0_PORT5_ARES>, - <&gcc GCC_UNIPHY0_PORT_4_5_RESET>, - <&gcc GCC_UNIPHY0_PORT_4_RESET>; - reset-names = "ppe_rst", "uniphy0_soft_rst", "uniphy0_xpcs_rst", - "uniphy1_soft_rst", "uniphy1_xpcs_rst", - "nss_port1_rst", "nss_port2_rst", "nss_port3_rst", - "nss_port4_rst", "nss_port5_rst", - "uniphy0_port1_dis", "uniphy0_port2_dis", - "uniphy0_port3_dis", "uniphy0_port4_dis", - "uniphy0_port5_dis", "uniphy0_port_4_5_rst", - "uniphy0_port_4_rst"; - }; - - ess-uniphy@7a00000 { - compatible = "qcom,ess-uniphy"; - reg = <0x7a00000 0x30000>; - uniphy_access_mode = "local bus"; - }; - - edma: edma@3ab00000 { - compatible = "qcom,edma"; - reg = <0x0 0x3ab00000 0x0 0xabe00>; - reg-names = "edma-reg-base"; - qcom,txdesc-ring-start = <23>; - qcom,txdesc-rings = <1>; - qcom,txcmpl-ring-start = <23>; - qcom,txcmpl-rings = <1>; - qcom,rxfill-ring-start = <7>; - qcom,rxfill-rings = <1>; - qcom,rxdesc-ring-start = <15>; - qcom,rxdesc-rings = <1>; - interrupts = , - , - , - ; - resets = <&gcc GCC_EDMA_HW_RESET>; - reset-names = "edma_rst"; - status = "disabled"; - }; -}; - -&switch { - port_scheduler_resource { - port@0 { - port_id = <0>; - ucast_queue = <0 143>; - mcast_queue = <256 271>; - l0sp = <0 35>; - l0cdrr = <0 47>; - l0edrr = <0 47>; - l1cdrr = <0 7>; - l1edrr = <0 7>; - }; - port@1 { - port_id = <1>; - ucast_queue = <144 159>; - mcast_queue = <272 275>; - l0sp = <36 39>; - l0cdrr = <48 63>; - l0edrr = <48 63>; - l1cdrr = <8 11>; - l1edrr = <8 11>; - }; - port@2 { - port_id = <2>; - ucast_queue = <160 175>; - mcast_queue = <276 279>; - l0sp = <40 43>; - l0cdrr = <64 79>; - l0edrr = <64 79>; - l1cdrr = <12 15>; - l1edrr = <12 15>; - }; - port@3 { - port_id = <3>; - ucast_queue = <176 191>; - mcast_queue = <280 283>; - l0sp = <44 47>; - l0cdrr = <80 95>; - l0edrr = <80 95>; - l1cdrr = <16 19>; - l1edrr = <16 19>; - }; - port@4 { - port_id = <4>; - ucast_queue = <192 207>; - mcast_queue = <284 287>; - l0sp = <48 51>; - l0cdrr = <96 111>; - l0edrr = <96 111>; - l1cdrr = <20 23>; - l1edrr = <20 23>; - }; - port@5 { - port_id = <5>; - ucast_queue = <208 223>; - mcast_queue = <288 291>; - l0sp = <52 55>; - l0cdrr = <112 127>; - l0edrr = <112 127>; - l1cdrr = <24 27>; - l1edrr = <24 27>; - }; - port@6 { - port_id = <6>; - ucast_queue = <224 239>; - mcast_queue = <292 295>; - l0sp = <56 59>; - l0cdrr = <128 143>; - l0edrr = <128 143>; - l1cdrr = <28 31>; - l1edrr = <28 31>; - }; - port@7 { - port_id = <7>; - ucast_queue = <240 255>; - mcast_queue = <296 299>; - l0sp = <60 63>; - l0cdrr = <144 159>; - l0edrr = <144 159>; - l1cdrr = <32 35>; - l1edrr = <32 35>; - }; - }; - - port_scheduler_config { - port@0 { - port_id = <0>; - l1scheduler { - group@0 { - sp = <0 1>; - cfg = <0 0 0 0>; - }; - }; - l0scheduler { - group@0 { - ucast_queue = <0 4 8>; - mcast_queue = <256 260>; - cfg = <0 0 0 0 0>; - }; - group@1 { - ucast_queue = <1 5 9>; - mcast_queue = <257 261>; - cfg = <0 1 1 1 1>; - }; - group@2 { - ucast_queue = <2 6 10>; - mcast_queue = <258 262>; - cfg = <0 2 2 2 2>; - }; - group@3 { - ucast_queue = <3 7 11>; - mcast_queue = <259 263>; - cfg = <0 3 3 3 3>; - }; - }; - }; - port@1 { - port_id = <1>; - l1scheduler { - group@0 { - sp = <36>; - cfg = <0 8 0 8>; - }; - group@1 { - sp = <37>; - cfg = <1 9 1 9>; - }; - }; - l0scheduler { - group@0 { - ucast_queue = <144>; - ucast_loop_pri = <16>; - mcast_queue = <272>; - mcast_loop_pri = <4>; - cfg = <36 0 48 0 48>; - }; - }; - }; - port@2 { - port_id = <2>; - l1scheduler { - group@0 { - sp = <40>; - cfg = <0 12 0 12>; - }; - group@1 { - sp = <41>; - cfg = <1 13 1 13>; - }; - }; - l0scheduler { - group@0 { - ucast_queue = <160>; - ucast_loop_pri = <16>; - mcast_queue = <276>; - mcast_loop_pri = <4>; - cfg = <40 0 64 0 64>; - }; - }; - }; - port@3 { - port_id = <3>; - l1scheduler { - group@0 { - sp = <44>; - cfg = <0 16 0 16>; - }; - group@1 { - sp = <45>; - cfg = <1 17 1 17>; - }; - }; - l0scheduler { - group@0 { - ucast_queue = <176>; - ucast_loop_pri = <16>; - mcast_queue = <280>; - mcast_loop_pri = <4>; - cfg = <44 0 80 0 80>; - }; - }; - }; - port@4 { - port_id = <4>; - l1scheduler { - group@0 { - sp = <48>; - cfg = <0 20 0 20>; - }; - group@1 { - sp = <49>; - cfg = <1 21 1 21>; - }; - }; - l0scheduler { - group@0 { - ucast_queue = <192>; - ucast_loop_pri = <16>; - mcast_queue = <284>; - mcast_loop_pri = <4>; - cfg = <48 0 96 0 96>; - }; - }; - }; - port@5 { - port_id = <5>; - l1scheduler { - group@0 { - sp = <52>; - cfg = <0 24 0 24>; - }; - group@1 { - sp = <53>; - cfg = <1 25 1 25>; - }; - }; - l0scheduler { - group@0 { - ucast_queue = <208>; - ucast_loop_pri = <16>; - mcast_queue = <288>; - mcast_loop_pri = <4>; - cfg = <52 0 112 0 112>; - }; - }; - }; - port@6 { - port_id = <6>; - l1scheduler { - group@0 { - sp = <56>; - cfg = <0 28 0 28>; - }; - group@1 { - sp = <57>; - cfg = <1 29 1 29>; - }; - }; - l0scheduler { - group@0 { - ucast_queue = <224>; - ucast_loop_pri = <16>; - mcast_queue = <292>; - mcast_loop_pri = <4>; - cfg = <56 0 128 0 128>; - }; - }; - }; - port@7 { - port_id = <7>; - l1scheduler { - group@0 { - sp = <60>; - cfg = <0 32 0 32>; - }; - group@1 { - sp = <61>; - cfg = <1 33 1 33>; - }; - }; - l0scheduler { - group@0 { - ucast_queue = <240>; - ucast_loop_pri = <16>; - mcast_queue = <296>; - cfg = <60 0 144 0 144>; - }; - }; - }; - }; -}; diff --git a/target/linux/ipq60xx/files/arch/arm64/boot/dts/qcom/ipq6018-m2.dts b/target/linux/ipq60xx/files/arch/arm64/boot/dts/qcom/ipq6018-m2.dts deleted file mode 100644 index 16cc4137e..000000000 --- a/target/linux/ipq60xx/files/arch/arm64/boot/dts/qcom/ipq6018-m2.dts +++ /dev/null @@ -1,66 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0+) - -/dts-v1/; - -#include "ipq6018-cmiot.dtsi" - -/ { - model = "ZN M2"; - compatible = "zn,m2", "qcom,ipq6018"; - - aliases { - led-boot = &led_power; - led-failsafe = &led_power; - led-running = &led_power; - led-upgrade = &led_power; - }; - - leds { - compatible = "gpio-leds"; - pinctrl-0 = <&leds_pins>; - pinctrl-names = "default"; - - led_power: power { - label = "m2:blue:power"; - gpio = <&tlmm 58 GPIO_ACTIVE_HIGH>; - }; - - mesh { - label = "m2:blue:mesh"; - gpio = <&tlmm 73 GPIO_ACTIVE_HIGH>; - }; - - lan { - label = "m2:blue:lan"; - gpio = <&tlmm 74 GPIO_ACTIVE_HIGH>; - }; - - wan { - label = "m2:blue:wan"; - gpio = <&tlmm 37 GPIO_ACTIVE_HIGH>; - }; - - wlan5g { - label = "m2:blue:wlan5g"; - gpio = <&tlmm 35 GPIO_ACTIVE_HIGH>; - }; - - wlan2g { - label = "m2:blue:wlan2g"; - gpio = <&tlmm 70 GPIO_ACTIVE_HIGH>; - }; - }; -}; - -&tlmm { - leds_pins: leds_pins { - mux { - pins = "gpio35", "gpio37", - "gpio58", "gpio70", - "gpio73", "gpio74"; - function = "gpio"; - drive-strength = <8>; - bias-pull-down; - }; - }; -}; diff --git a/target/linux/ipq60xx/files/arch/arm64/boot/dts/qcom/ipq6018-mr7350.dts b/target/linux/ipq60xx/files/arch/arm64/boot/dts/qcom/ipq6018-mr7350.dts deleted file mode 100644 index 8e5cc8453..000000000 --- a/target/linux/ipq60xx/files/arch/arm64/boot/dts/qcom/ipq6018-mr7350.dts +++ /dev/null @@ -1,249 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0+) - -/dts-v1/; - -#include "ipq6018.dtsi" -#include "ipq6018-upstreamable.dtsi" -#include "ipq6018-ess.dtsi" - -#include -#include - -/ { - model = "Linksys MR7350"; - compatible = "linksys,mr7350", "qcom,ipq6018"; - - aliases { - serial0 = &blsp1_uart3; -// led-boot = &led_power; -// led-failsafe = &led_power; -// led-running = &led_power; -// led-upgrade = &led_power; - }; - - chosen { - stdout-path = "serial0:115200n8"; - }; - - keys { - compatible = "gpio-keys"; - - reset { - label = "reset"; - gpios = <&tlmm 57 GPIO_ACTIVE_LOW>; - linux,code = ; - }; - - wps { - label = "reset"; - gpios = <&tlmm 56 GPIO_ACTIVE_LOW>; - linux,code = ; - }; - }; -}; - -&blsp1_uart3 { - pinctrl-0 = <&serial_3_pins>; - pinctrl-names = "default"; - status = "okay"; -}; - -&tlmm { - i2c_1_pins: i2c-1-pins { - pins = "gpio42", "gpio43"; - function = "blsp2_i2c"; - drive-strength = <8>; - }; - - mdio_pins: mdio-pins { - mdc { - pins = "gpio64"; - function = "mdc"; - drive-strength = <8>; - bias-pull-up; - }; - - mdio { - pins = "gpio65"; - function = "mdio"; - drive-strength = <8>; - bias-pull-up; - }; - }; -}; - -&soc { - dp1: dp@1 { - compatible = "qcom,nss-dp"; - reg = <0x0 0x3a001000 0x0 0x200>; - qcom,mactype = <0>; - qcom,id = <1>; - - phy-handle = <&phy_0>; - phy-mode = "sgmii"; - }; - - dp2 { - compatible = "qcom,nss-dp"; - reg = <0x0 0x3a001200 0x0 0x200>; - qcom,mactype = <0>; - qcom,id = <2>; - - phy-handle = <&phy_1>; - phy-mode = "sgmii"; - }; - - dp3 { - compatible = "qcom,nss-dp"; - reg = <0x0 0x3a001400 0x0 0x200>; - qcom,mactype = <0>; - qcom,id = <3>; - - phy-handle = <&phy_2>; - phy-mode = "sgmii"; - }; - - dp4 { - compatible = "qcom,nss-dp"; - reg = <0x0 0x3a001600 0x0 0x200>; - qcom,mactype = <0>; - qcom,id = <4>; - - phy-handle = <&phy_3>; - phy-mode = "sgmii"; - }; - - dp5 { - compatible = "qcom,nss-dp"; - reg = <0x0 0x3a001800 0x0 0x200>; - qcom,mactype = <0>; - qcom,id = <5>; - - phy-handle = <&phy_4>; - phy-mode = "sgmii"; - }; -}; - -&edma { - status = "okay"; -}; - -&mdio { - status = "okay"; - pinctrl-0 = <&mdio_pins>; - pinctrl-names = "default"; - reset-gpios = <&tlmm 75 GPIO_ACTIVE_LOW>; - - phy_0: ethernet-phy@0 { - reg = <0>; -// reset-gpios = <&tlmm 77 GPIO_ACTIVE_LOW>; - }; - - phy_1: ethernet-phy@1 { - reg = <1>; - }; - - phy_2: ethernet-phy@2 { - reg = <2>; - }; - - phy_3: ethernet-phy@3 { - reg = <3>; - }; - - phy_4: ethernet-phy@4 { - reg = <4>; - }; - -}; - -&switch { - status = "okay"; - - switch_lan_bmp = <0x1e>; - switch_wan_bmp = <0x20>; - switch_mac_mode = <0x00>; - switch_mac_mode1 = <0xff>; - switch_mac_mode2 = <0xff>; - - qcom,port_phyinfo { - port@0 { - port_id = <0x01>; - phy_address = <0x00>; - }; - port@1 { - port_id = <0x02>; - phy_address = <0x01>; - }; - port@2 { - port_id = <0x03>; - phy_address = <0x02>; - }; - port@3 { - port_id = <0x04>; - phy_address = <0x03>; - }; - port@4 { - port_id = <0x05>; - phy_address = <0x04>; - }; - }; -}; - -&qpic_bam { - status = "okay"; -}; - -&qpic_nand { - status = "okay"; - - nand@0 { - reg = <0>; - - nand-ecc-strength = <4>; - nand-ecc-step-size = <512>; - nand-bus-width = <8>; - }; -}; - -&qusb_phy_0 { - status = "okay"; -}; - -&ssphy_0 { - status = "okay"; -}; - -&usb3 { - status = "okay"; -}; - -&wifi { - status = "okay"; -}; - -&blsp1_i2c3 { - pinctrl-0 = <&i2c_1_pins>; - pinctrl-names = "default"; - status = "okay"; - - pca9633: pca9633 { - compatible = "nxp,pca9633"; - #address-cells = <1>; - #size-cells = <0>; - reg = <0x62>; - - red@0 { - label = "red"; - reg = <0>; - }; - green@1 { - label = "green"; - reg = <1>; - }; - blue@2 { - label = "blue"; - reg = <2>; - }; - }; -}; diff --git a/target/linux/ipq60xx/files/arch/arm64/boot/dts/qcom/ipq6018-upstreamable.dtsi b/target/linux/ipq60xx/files/arch/arm64/boot/dts/qcom/ipq6018-upstreamable.dtsi deleted file mode 100644 index dd03e63d3..000000000 --- a/target/linux/ipq60xx/files/arch/arm64/boot/dts/qcom/ipq6018-upstreamable.dtsi +++ /dev/null @@ -1,120 +0,0 @@ -/ { - reserved-memory { - #address-cells = <2>; - #size-cells = <2>; - ranges; - - nss@40000000 { - reg = <0x00 0x40000000 0x00 0x1000000>; - no-map; - }; - - uboot@4a100000 { - reg = <0x00 0x4a100000 0x00 0x400000>; - no-map; - }; - - sbl@4a500000 { - reg = <0x00 0x4a500000 0x00 0x100000>; - no-map; - }; - }; -}; - -&soc { - wifi: wifi@c000000 { - compatible = "qcom,ipq6018-wifi"; - reg = <0x0 0xc000000 0x0 0x1000000>; - qcom,rproc = <&q6v5_wcss>; - interrupts = , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - ; - interrupt-names = "misc-pulse1", "misc-latch", "sw-exception", - "watchdog", "ce0", "ce1", "ce2", "ce3", "ce4", - "ce5", "ce6", "ce7", "ce8", "ce9", "ce10", - "ce11", "host2wbm-desc-feed", - "host2reo-re-injection", "host2reo-command", - "host2rxdma-monitor-ring3", - "host2rxdma-monitor-ring2", - "host2rxdma-monitor-ring1", - "reo2ost-exception", "wbm2host-rx-release", - "reo2host-status", - "reo2host-destination-ring4", - "reo2host-destination-ring3", - "reo2host-destination-ring2", - "reo2host-destination-ring1", - "rxdma2host-monitor-destination-mac3", - "rxdma2host-monitor-destination-mac2", - "rxdma2host-monitor-destination-mac1", - "ppdu-end-interrupts-mac3", - "ppdu-end-interrupts-mac2", - "ppdu-end-interrupts-mac1", - "rxdma2host-monitor-status-ring-mac3", - "rxdma2host-monitor-status-ring-mac2", - "rxdma2host-monitor-status-ring-mac1", - "host2rxdma-host-buf-ring-mac3", - "host2rxdma-host-buf-ring-mac2", - "host2rxdma-host-buf-ring-mac1", - "rxdma2host-destination-ring-mac3", - "rxdma2host-destination-ring-mac2", - "rxdma2host-destination-ring-mac1", - "host2tcl-input-ring4", - "host2tcl-input-ring3", - "host2tcl-input-ring2", - "host2tcl-input-ring1", - "wbm2host-tx-completions-ring3", - "wbm2host-tx-completions-ring2", - "wbm2host-tx-completions-ring1", - "tcl2host-status-ring"; - status = "disabled"; - }; -}; diff --git a/target/linux/ipq60xx/files/arch/arm64/boot/dts/qcom/ipq6018-v6.dts b/target/linux/ipq60xx/files/arch/arm64/boot/dts/qcom/ipq6018-v6.dts deleted file mode 100644 index cf0333f5c..000000000 --- a/target/linux/ipq60xx/files/arch/arm64/boot/dts/qcom/ipq6018-v6.dts +++ /dev/null @@ -1,249 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0+) - -/dts-v1/; - -#include "ipq6018.dtsi" -#include "ipq6018-upstreamable.dtsi" -#include "ipq6018-ess.dtsi" - -#include -#include - -/ { - model = "Qihoo 360 V6"; - compatible = "qihoo,v6", "qcom,ipq6018"; - - aliases { - serial0 = &blsp1_uart3; - led-boot = &led_system_orange; - led-failsafe = &led_system_red; - led-running = &led_system_green; - led-upgrade = &led_system_orange; - }; - - chosen { - stdout-path = "serial0:115200n8"; - }; - - leds { - compatible = "gpio-leds"; - pinctrl-0 = <&leds_pins>; - pinctrl-names = "default"; - - led_system_red: system-red { - label = "v6:red:status"; - gpios = <&tlmm 71 GPIO_ACTIVE_HIGH>; - }; - - led_system_orange: system-orange { - label = "v6:orange:status"; - gpios = <&tlmm 72 GPIO_ACTIVE_HIGH>; - }; - - led_system_green: system-green { - label = "v6:green:status"; - gpios = <&tlmm 73 GPIO_ACTIVE_HIGH>; - }; - }; - - keys { - compatible = "gpio-keys"; - - reset { - label = "reset"; - gpios = <&tlmm 68 GPIO_ACTIVE_LOW>; - linux,code = ; - }; - - wps { - label = "wps"; - gpios = <&tlmm 19 GPIO_ACTIVE_LOW>; - linux,code = ; - }; - }; -}; - -&blsp1_uart3 { - pinctrl-0 = <&serial_3_pins>; - pinctrl-names = "default"; - status = "okay"; -}; - -&tlmm { - - mdio_pins: mdio-pins { - mdc { - pins = "gpio64"; - function = "mdc"; - drive-strength = <8>; - bias-pull-up; - }; - - mdio { - pins = "gpio65"; - function = "mdio"; - drive-strength = <8>; - bias-pull-up; - }; - }; - - leds_pins: leds_pins { - mux { - pins = "gpio71", "gpio72", "gpio73"; - function = "gpio"; - drive-strength = <8>; - bias-pull-down; - }; - }; - -}; - -&soc { - dp1: dp@1 { - compatible = "qcom,nss-dp"; - reg = <0x0 0x3a001000 0x0 0x200>; - qcom,mactype = <0>; - qcom,id = <1>; - - phy-handle = <&phy_0>; - phy-mode = "sgmii"; - }; - - dp2 { - compatible = "qcom,nss-dp"; - reg = <0x0 0x3a001200 0x0 0x200>; - qcom,mactype = <0>; - qcom,id = <2>; - - phy-handle = <&phy_1>; - phy-mode = "sgmii"; - }; - - dp3 { - compatible = "qcom,nss-dp"; - reg = <0x0 0x3a001400 0x0 0x200>; - qcom,mactype = <0>; - qcom,id = <3>; - - phy-handle = <&phy_2>; - phy-mode = "sgmii"; - }; - - dp4 { - compatible = "qcom,nss-dp"; - reg = <0x0 0x3a001600 0x0 0x200>; - qcom,mactype = <0>; - qcom,id = <4>; - - phy-handle = <&phy_3>; - phy-mode = "sgmii"; - }; - - dp5 { - compatible = "qcom,nss-dp"; - reg = <0x0 0x3a001800 0x0 0x200>; - qcom,mactype = <0>; - qcom,id = <5>; - - phy-handle = <&phy_4>; - phy-mode = "sgmii"; - }; -}; - -&edma { - status = "okay"; -}; - -&mdio { - status = "okay"; - pinctrl-0 = <&mdio_pins>; - pinctrl-names = "default"; - reset-gpios = <&tlmm 75 GPIO_ACTIVE_LOW>; - - phy_0: ethernet-phy@0 { - reg = <0>; -// reset-gpios = <&tlmm 77 GPIO_ACTIVE_LOW>; - }; - - phy_1: ethernet-phy@1 { - reg = <1>; - }; - - phy_2: ethernet-phy@2 { - reg = <2>; - }; - - phy_3: ethernet-phy@3 { - reg = <3>; - }; - - phy_4: ethernet-phy@4 { - reg = <4>; - }; - -}; - -&switch { - status = "okay"; - - switch_lan_bmp = <0x1e>; - switch_wan_bmp = <0x20>; - switch_mac_mode = <0x00>; - switch_mac_mode1 = <0xff>; - switch_mac_mode2 = <0xff>; - - qcom,port_phyinfo { - port@0 { - port_id = <0x01>; - phy_address = <0x00>; - }; - port@1 { - port_id = <0x02>; - phy_address = <0x01>; - }; - port@2 { - port_id = <0x03>; - phy_address = <0x02>; - }; - port@3 { - port_id = <0x04>; - phy_address = <0x03>; - }; - port@4 { - port_id = <0x05>; - phy_address = <0x04>; - }; - }; -}; - -&qpic_bam { - status = "okay"; -}; - -&qpic_nand { - status = "okay"; - - nand@0 { - reg = <0>; - - nand-ecc-strength = <4>; - nand-ecc-step-size = <512>; - nand-bus-width = <8>; - }; -}; - -&wifi { - status = "okay"; -}; - -&ssphy_0 { - status = "ok"; -}; - -&qusb_phy_0 { - status = "ok"; -}; - -&usb3 { - status = "ok"; -}; diff --git a/target/linux/ipq60xx/generic/target.mk b/target/linux/ipq60xx/generic/target.mk deleted file mode 100644 index f5cb1fb19..000000000 --- a/target/linux/ipq60xx/generic/target.mk +++ /dev/null @@ -1 +0,0 @@ -BOARDNAME:=Generic diff --git a/target/linux/ipq60xx/image/Makefile b/target/linux/ipq60xx/image/Makefile deleted file mode 100644 index 4b0a657c0..000000000 --- a/target/linux/ipq60xx/image/Makefile +++ /dev/null @@ -1,18 +0,0 @@ -include $(TOPDIR)/rules.mk -include $(INCLUDE_DIR)/image.mk - -define Device/Default - PROFILES := Default - KERNEL_DEPENDS = $$(wildcard $(DTS_DIR)/$$(DEVICE_DTS).dts) - KERNEL_LOADADDR := 0x41000000 - DEVICE_DTS = $$(SOC)-$(lastword $(subst _, ,$(1))) - DEVICE_DTS_CONFIG := config@1 - DEVICE_DTS_DIR := $(DTS_DIR)/qcom - IMAGES := sysupgrade.bin - IMAGE/sysupgrade.bin = sysupgrade-tar | append-metadata - IMAGE/sysupgrade.bin/squashfs := -endef - -include $(SUBTARGET).mk - -$(eval $(call BuildImage)) diff --git a/target/linux/ipq60xx/image/generic.mk b/target/linux/ipq60xx/image/generic.mk deleted file mode 100644 index 934c38858..000000000 --- a/target/linux/ipq60xx/image/generic.mk +++ /dev/null @@ -1,93 +0,0 @@ -define Device/FitImage - KERNEL_SUFFIX := -fit-uImage.itb - KERNEL = kernel-bin | gzip | fit gzip $$(DEVICE_DTS_DIR)/$$(DEVICE_DTS).dtb - KERNEL_NAME := Image -endef - -define Device/FitImageLzma - KERNEL_SUFFIX := -fit-uImage.itb - KERNEL = kernel-bin | lzma | fit lzma $$(DEVICE_DTS_DIR)/$$(DEVICE_DTS).dtb - KERNEL_NAME := Image -endef - -define Device/FitzImage - KERNEL_SUFFIX := -fit-zImage.itb - KERNEL = kernel-bin | fit none $$(DEVICE_DTS_DIR)/$$(DEVICE_DTS).dtb - KERNEL_NAME := zImage -endef - -define Device/UbiFit - KERNEL_IN_UBI := 1 - IMAGES := nand-factory.ubi nand-sysupgrade.bin - IMAGE/nand-factory.ubi := append-ubi - IMAGE/nand-sysupgrade.bin := sysupgrade-tar | append-metadata -endef - -define Device/cmiot_ax18 - $(call Device/FitImage) - $(call Device/UbiFit) - DEVICE_VENDOR := CMIOT - DEVICE_MODEL := AX18 - BLOCKSIZE := 128k - PAGESIZE := 2048 - DEVICE_DTS_CONFIG := config@cp03-c1 - SOC := ipq6018 -endef -TARGET_DEVICES += cmiot_ax18 - -define Device/linksys_mr7350 - $(call Device/FitImage) - $(call Device/UbiFit) - DEVICE_VENDOR := Linksys - DEVICE_MODEL := MR7350 - BLOCKSIZE := 128k - PAGESIZE := 2048 - SOC := ipq6018 - DEVICE_PACKAGES := kmod-leds-pca963x -endef -TARGET_DEVICES += linksys_mr7350 - -#define Device/cp01-c1 -# $(call Device/FitImage) -# DEVICE_VENDOR := Qualcomm Technologies -# DEVICE_MODEL := AP-CP01-C1 -# SOC := ipq6018 -#endef -#TARGET_DEVICES += cp01-c1 - -#define Device/eap610-outdoor -# $(call Device/FitImage) -# $(call Device/UbiFit) -# DEVICE_VENDOR := TP-Link -# DEVICE_MODEL := EAP610-Outdoor -# BLOCKSIZE := 128k -# PAGESIZE := 2048 -# SOC := ipq6018 -# IMAGE/nand-factory.ubi := append-ubi | qsdk-ipq-factory-nand -#endef -#TARGET_DEVICES += eap610-outdoor - -define Device/360_v6 - $(call Device/FitImage) - $(call Device/UbiFit) - DEVICE_VENDOR := Qihoo 360 - DEVICE_MODEL := V6 - BLOCKSIZE := 128k - PAGESIZE := 2048 - DEVICE_DTS_CONFIG := config@cp03-c1 - DEVICE_PACKAGES := ath11k-wifi-qihoo_v6 - SOC := ipq6018 -endef -TARGET_DEVICES += 360_v6 - -define Device/zn_m2 - $(call Device/FitImage) - $(call Device/UbiFit) - DEVICE_VENDOR := ZN - DEVICE_MODEL := M2 - BLOCKSIZE := 128k - PAGESIZE := 2048 - DEVICE_DTS_CONFIG := config@cp03-c1 - SOC := ipq6018 -endef -TARGET_DEVICES += zn_m2 diff --git a/target/linux/ipq60xx/patches-5.15/0001-v5.16-arm64-dts-qcom-ipq8074-add-SPMI-bus.patch b/target/linux/ipq60xx/patches-5.15/0001-v5.16-arm64-dts-qcom-ipq8074-add-SPMI-bus.patch deleted file mode 100644 index 1eb8640a4..000000000 --- a/target/linux/ipq60xx/patches-5.15/0001-v5.16-arm64-dts-qcom-ipq8074-add-SPMI-bus.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 3f3f712b16c7d374cfb079ca83684f12fda7884c Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Sun, 5 Sep 2021 18:58:16 +0200 -Subject: [PATCH 01/44] arm64: dts: qcom: ipq8074: add SPMI bus - -IPQ8074 uses SPMI for communication with the PMIC, so -since its already supported add the DT node for it. - -Signed-off-by: Robert Marko -Signed-off-by: Bjorn Andersson -Link: https://lore.kernel.org/r/20210905165816.655275-1-robimarko@gmail.com ---- - arch/arm64/boot/dts/qcom/ipq8074.dtsi | 19 +++++++++++++++++++ - 1 file changed, 19 insertions(+) - ---- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -320,6 +320,25 @@ - #reset-cells = <0x1>; - }; - -+ spmi_bus: spmi@200f000 { -+ compatible = "qcom,spmi-pmic-arb"; -+ reg = <0x0200f000 0x001000>, -+ <0x02400000 0x800000>, -+ <0x02c00000 0x800000>, -+ <0x03800000 0x200000>, -+ <0x0200a000 0x000700>; -+ reg-names = "core", "chnls", "obsrvr", "intr", "cnfg"; -+ interrupts = ; -+ interrupt-names = "periph_irq"; -+ qcom,ee = <0>; -+ qcom,channel = <0>; -+ #address-cells = <2>; -+ #size-cells = <0>; -+ interrupt-controller; -+ #interrupt-cells = <4>; -+ cell-index = <0>; -+ }; -+ - sdhc_1: sdhci@7824900 { - compatible = "qcom,sdhci-msm-v4"; - reg = <0x7824900 0x500>, <0x7824000 0x800>; diff --git a/target/linux/ipq60xx/patches-5.15/0002-v5.16-arm64-dts-qcom-Update-BAM-DMA-node-name-per-DT-schem.patch b/target/linux/ipq60xx/patches-5.15/0002-v5.16-arm64-dts-qcom-Update-BAM-DMA-node-name-per-DT-schem.patch deleted file mode 100644 index fbec7cf1d..000000000 --- a/target/linux/ipq60xx/patches-5.15/0002-v5.16-arm64-dts-qcom-Update-BAM-DMA-node-name-per-DT-schem.patch +++ /dev/null @@ -1,27 +0,0 @@ -From e5698ba1e94af28e5f54943bcd6de278efc84500 Mon Sep 17 00:00:00 2001 -From: Shawn Guo -Date: Tue, 31 Aug 2021 13:23:25 +0800 -Subject: [PATCH 02/44] arm64: dts: qcom: Update BAM DMA node name per DT - schema - -Follow dma-controller.yaml schema to use `dma-controller` as node name -of BAM DMA devices. - -Signed-off-by: Shawn Guo -Signed-off-by: Bjorn Andersson -Link: https://lore.kernel.org/r/20210831052325.21229-1-shawn.guo@linaro.org ---- - arch/arm64/boot/dts/qcom/ipq8074.dtsi | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -239,7 +239,7 @@ - status = "disabled"; - }; - -- cryptobam: dma@704000 { -+ cryptobam: dma-controller@704000 { - compatible = "qcom,bam-v1.7.0"; - reg = <0x00704000 0x20000>; - interrupts = ; diff --git a/target/linux/ipq60xx/patches-5.15/0003-v5.16-arm64-dts-qcom-ipq8074-Add-QUP5-I2C-node.patch b/target/linux/ipq60xx/patches-5.15/0003-v5.16-arm64-dts-qcom-ipq8074-Add-QUP5-I2C-node.patch deleted file mode 100644 index e48b2d1e9..000000000 --- a/target/linux/ipq60xx/patches-5.15/0003-v5.16-arm64-dts-qcom-ipq8074-Add-QUP5-I2C-node.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 187368d2936edad6342151ae1ac34d95dc2de2c1 Mon Sep 17 00:00:00 2001 -From: Chukun Pan -Date: Fri, 1 Oct 2021 22:54:21 +0800 -Subject: [PATCH 03/44] arm64: dts: qcom: ipq8074: Add QUP5 I2C node - -Add node to support the QUP5 I2C controller inside of IPQ8074. -It is exactly the same as QUP2 controllers. -Some routers like ZTE MF269 use this bus. - -Signed-off-by: Chukun Pan -Signed-off-by: Bjorn Andersson -Link: https://lore.kernel.org/r/20211001145421.18302-1-amadeus@jmu.edu.cn ---- - arch/arm64/boot/dts/qcom/ipq8074.dtsi | 15 +++++++++++++++ - 1 file changed, 15 insertions(+) - ---- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -457,6 +457,21 @@ - status = "disabled"; - }; - -+ blsp1_i2c5: i2c@78b9000 { -+ compatible = "qcom,i2c-qup-v2.2.1"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ reg = <0x78b9000 0x600>; -+ interrupts = ; -+ clocks = <&gcc GCC_BLSP1_AHB_CLK>, -+ <&gcc GCC_BLSP1_QUP5_I2C_APPS_CLK>; -+ clock-names = "iface", "core"; -+ clock-frequency = <400000>; -+ dmas = <&blsp_dma 21>, <&blsp_dma 20>; -+ dma-names = "rx", "tx"; -+ status = "disabled"; -+ }; -+ - blsp1_i2c6: i2c@78ba000 { - compatible = "qcom,i2c-qup-v2.2.1"; - #address-cells = <1>; diff --git a/target/linux/ipq60xx/patches-5.15/0004-v5.16-arm64-dts-qcom-msm8996-Move-clock-cells-to-QMP-PHY-c.patch b/target/linux/ipq60xx/patches-5.15/0004-v5.16-arm64-dts-qcom-msm8996-Move-clock-cells-to-QMP-PHY-c.patch deleted file mode 100644 index a5865baba..000000000 --- a/target/linux/ipq60xx/patches-5.15/0004-v5.16-arm64-dts-qcom-msm8996-Move-clock-cells-to-QMP-PHY-c.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 4ef751128de689e12e3eccb5d4e2562ef8b42758 Mon Sep 17 00:00:00 2001 -From: Shawn Guo -Date: Wed, 29 Sep 2021 11:42:46 +0800 -Subject: [PATCH 04/44] arm64: dts: qcom: msm8996: Move '#clock-cells' to QMP - PHY child node - -'#clock-cells' is a required property of QMP PHY child node, not itself. -Move it to fix the dtbs_check warnings. - -There are only '#clock-cells' removal from SM8350 QMP PHY nodes, because -child nodes already have the property. - -Signed-off-by: Shawn Guo -Signed-off-by: Bjorn Andersson -Link: https://lore.kernel.org/r/20210929034253.24570-4-shawn.guo@linaro.org ---- - arch/arm64/boot/dts/qcom/ipq8074.dtsi | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -91,7 +91,6 @@ - ssphy_1: phy@58000 { - compatible = "qcom,ipq8074-qmp-usb3-phy"; - reg = <0x00058000 0x1c4>; -- #clock-cells = <1>; - #address-cells = <1>; - #size-cells = <1>; - ranges; -@@ -112,6 +111,7 @@ - <0x00058800 0x1f8>, /* PCS */ - <0x00058600 0x044>; /* PCS misc*/ - #phy-cells = <0>; -+ #clock-cells = <1>; - clocks = <&gcc GCC_USB1_PIPE_CLK>; - clock-names = "pipe0"; - clock-output-names = "usb3phy_1_cc_pipe_clk"; -@@ -134,7 +134,6 @@ - ssphy_0: phy@78000 { - compatible = "qcom,ipq8074-qmp-usb3-phy"; - reg = <0x00078000 0x1c4>; -- #clock-cells = <1>; - #address-cells = <1>; - #size-cells = <1>; - ranges; -@@ -155,6 +154,7 @@ - <0x00078800 0x1f8>, /* PCS */ - <0x00078600 0x044>; /* PCS misc*/ - #phy-cells = <0>; -+ #clock-cells = <1>; - clocks = <&gcc GCC_USB0_PIPE_CLK>; - clock-names = "pipe0"; - clock-output-names = "usb3phy_0_cc_pipe_clk"; diff --git a/target/linux/ipq60xx/patches-5.15/0007-v5.17-arm64-dts-qcom-ipq8074-add-MDIO-bus.patch b/target/linux/ipq60xx/patches-5.15/0007-v5.17-arm64-dts-qcom-ipq8074-add-MDIO-bus.patch deleted file mode 100644 index 9b481dcdd..000000000 --- a/target/linux/ipq60xx/patches-5.15/0007-v5.17-arm64-dts-qcom-ipq8074-add-MDIO-bus.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 9757a0d4e05b807074f6868ed594a9bf0111d74d Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Thu, 7 Oct 2021 13:58:46 +0200 -Subject: [PATCH 07/44] arm64: dts: qcom: ipq8074: add MDIO bus - -IPQ8074 uses an IPQ4019 compatible MDIO controller that is already -supported in the kernel, so add the DT node in order to use it. - -Signed-off-by: Robert Marko -Signed-off-by: Bjorn Andersson -Link: https://lore.kernel.org/r/20211007115846.26255-1-robimarko@gmail.com ---- - arch/arm64/boot/dts/qcom/ipq8074.dtsi | 12 ++++++++++++ - 1 file changed, 12 insertions(+) - ---- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -231,6 +231,18 @@ - }; - }; - -+ mdio: mdio@90000 { -+ compatible = "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"; -+ }; -+ - prng: rng@e3000 { - compatible = "qcom,prng-ee"; - reg = <0x000e3000 0x1000>; diff --git a/target/linux/ipq60xx/patches-5.15/0009-v5.18-arm64-dts-qcom-ipq8074-add-SMEM-support.patch b/target/linux/ipq60xx/patches-5.15/0009-v5.18-arm64-dts-qcom-ipq8074-add-SMEM-support.patch deleted file mode 100644 index 74602ef5f..000000000 --- a/target/linux/ipq60xx/patches-5.15/0009-v5.18-arm64-dts-qcom-ipq8074-add-SMEM-support.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 0064ce4f52ed8fc010c1794114205daa9f598828 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Thu, 6 Jan 2022 22:25:12 +0100 -Subject: [PATCH 09/44] arm64: dts: qcom: ipq8074: add SMEM support - -IPQ8074 uses SMEM like other modern QCA SoC-s, so since its already -supported by the kernel add the required DT nodes. - -Signed-off-by: Robert Marko -Signed-off-by: Bjorn Andersson -Link: https://lore.kernel.org/r/20220106212512.1970828-1-robimarko@gmail.com ---- - arch/arm64/boot/dts/qcom/ipq8074.dtsi | 20 ++++++++++++++++++++ - 1 file changed, 20 insertions(+) - ---- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -76,6 +76,20 @@ - method = "smc"; - }; - -+ reserved-memory { -+ #address-cells = <2>; -+ #size-cells = <2>; -+ ranges; -+ -+ smem@4ab00000 { -+ compatible = "qcom,smem"; -+ reg = <0x0 0x4ab00000 0x0 0x00100000>; -+ no-map; -+ -+ hwlocks = <&tcsr_mutex 0>; -+ }; -+ }; -+ - firmware { - scm { - compatible = "qcom,scm-ipq8074", "qcom,scm"; -@@ -332,6 +346,12 @@ - #reset-cells = <0x1>; - }; - -+ tcsr_mutex: hwlock@1905000 { -+ compatible = "qcom,tcsr-mutex"; -+ reg = <0x01905000 0x20000>; -+ #hwlock-cells = <1>; -+ }; -+ - spmi_bus: spmi@200f000 { - compatible = "qcom,spmi-pmic-arb"; - reg = <0x0200f000 0x001000>, diff --git a/target/linux/ipq60xx/patches-5.15/0010-v5.18-arm64-dts-qcom-ipq8074-add-the-reserved-memory-node.patch b/target/linux/ipq60xx/patches-5.15/0010-v5.18-arm64-dts-qcom-ipq8074-add-the-reserved-memory-node.patch deleted file mode 100644 index 6b617f955..000000000 --- a/target/linux/ipq60xx/patches-5.15/0010-v5.18-arm64-dts-qcom-ipq8074-add-the-reserved-memory-node.patch +++ /dev/null @@ -1,30 +0,0 @@ -From d58eeedd46d47db44a5932f7d74efae881d54c9b Mon Sep 17 00:00:00 2001 -From: Kathiravan T -Date: Fri, 7 Jan 2022 18:24:38 +0530 -Subject: [PATCH 10/44] arm64: dts: qcom: ipq8074: add the reserved-memory node - -On IPQ8074, 4MB of memory is needed for TZ. So mark that region -as reserved. - -Signed-off-by: Kathiravan T -[bjorn: Squash with existing reserved-memory node] -Signed-off-by: Bjorn Andersson -Link: https://lore.kernel.org/r/1641560078-860-1-git-send-email-quic_kathirav@quicinc.com ---- - arch/arm64/boot/dts/qcom/ipq8074.dtsi | 5 +++++ - 1 file changed, 5 insertions(+) - ---- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -88,6 +88,11 @@ - - hwlocks = <&tcsr_mutex 0>; - }; -+ -+ memory@4ac00000 { -+ no-map; -+ reg = <0x0 0x4ac00000 0x0 0x00400000>; -+ }; - }; - - firmware { diff --git a/target/linux/ipq60xx/patches-5.15/0011-v5.18-arm64-dts-qcom-ipq8074-enable-the-GICv2m-support.patch b/target/linux/ipq60xx/patches-5.15/0011-v5.18-arm64-dts-qcom-ipq8074-enable-the-GICv2m-support.patch deleted file mode 100644 index cd4631834..000000000 --- a/target/linux/ipq60xx/patches-5.15/0011-v5.18-arm64-dts-qcom-ipq8074-enable-the-GICv2m-support.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 4f0959ded385c8ed518659aa08cedbd83ae0726a Mon Sep 17 00:00:00 2001 -From: Kathiravan T -Date: Tue, 8 Feb 2022 21:05:24 +0530 -Subject: [PATCH 11/44] arm64: dts: qcom: ipq8074: enable the GICv2m support - -GIC used in the IPQ8074 SoCs has one instance of the GICv2m extension, -which supports upto 32 MSI interrupts. Lets add support for the same. - -Signed-off-by: Kathiravan T -Signed-off-by: Bjorn Andersson -Link: https://lore.kernel.org/r/1644334525-11577-2-git-send-email-quic_kathirav@quicinc.com ---- - arch/arm64/boot/dts/qcom/ipq8074.dtsi | 9 +++++++++ - 1 file changed, 9 insertions(+) - ---- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -635,9 +635,18 @@ - - intc: interrupt-controller@b000000 { - compatible = "qcom,msm-qgic2"; -+ #address-cells = <1>; -+ #size-cells = <1>; - interrupt-controller; - #interrupt-cells = <0x3>; - reg = <0x0b000000 0x1000>, <0x0b002000 0x1000>; -+ ranges = <0 0xb00a000 0xffd>; -+ -+ v2m@0 { -+ compatible = "arm,gic-v2m-frame"; -+ msi-controller; -+ reg = <0x0 0xffd>; -+ }; - }; - - timer { diff --git a/target/linux/ipq60xx/patches-5.15/0012-v5.18-arm64-dts-qcom-ipq8074-drop-the-clock-frequency-prop.patch b/target/linux/ipq60xx/patches-5.15/0012-v5.18-arm64-dts-qcom-ipq8074-drop-the-clock-frequency-prop.patch deleted file mode 100644 index be2a64923..000000000 --- a/target/linux/ipq60xx/patches-5.15/0012-v5.18-arm64-dts-qcom-ipq8074-drop-the-clock-frequency-prop.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 2e21d1f48dc0d0cdbd53ac33b9859c7cb575eecc Mon Sep 17 00:00:00 2001 -From: Kathiravan T -Date: Wed, 2 Feb 2022 22:05:08 +0530 -Subject: [PATCH 12/44] arm64: dts: qcom: ipq8074: drop the clock-frequency - property - -Drop the clock-frequency property from the MMIO timer node, since it -is already configured by the bootloader. - -Signed-off-by: Kathiravan T -Signed-off-by: Bjorn Andersson -Link: https://lore.kernel.org/r/1643819709-5410-2-git-send-email-quic_kathirav@quicinc.com ---- - arch/arm64/boot/dts/qcom/ipq8074.dtsi | 1 - - 1 file changed, 1 deletion(-) - ---- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -671,7 +671,6 @@ - ranges; - compatible = "arm,armv7-timer-mem"; - reg = <0x0b120000 0x1000>; -- clock-frequency = <19200000>; - - frame@b120000 { - frame-number = <0>; diff --git a/target/linux/ipq60xx/patches-5.15/0013-v5.19-arm64-dts-qcom-align-dmas-in-I2C-SPI-UART-with-DT-sc.patch b/target/linux/ipq60xx/patches-5.15/0013-v5.19-arm64-dts-qcom-align-dmas-in-I2C-SPI-UART-with-DT-sc.patch deleted file mode 100644 index 88035077c..000000000 --- a/target/linux/ipq60xx/patches-5.15/0013-v5.19-arm64-dts-qcom-align-dmas-in-I2C-SPI-UART-with-DT-sc.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 4647475f588c85138ddf47a17305dd41834e1105 Mon Sep 17 00:00:00 2001 -From: Krzysztof Kozlowski -Date: Tue, 5 Apr 2022 08:34:43 +0200 -Subject: [PATCH 13/44] arm64: dts: qcom: align dmas in I2C/SPI/UART with DT - schema - -The DT schema expects dma channels in tx-rx order. No functional -change. - -Signed-off-by: Krzysztof Kozlowski -Signed-off-by: Bjorn Andersson -Link: https://lore.kernel.org/r/20220405063451.12011-2-krzysztof.kozlowski@linaro.org ---- - arch/arm64/boot/dts/qcom/ipq8074.dtsi | 16 ++++++++-------- - 1 file changed, 8 insertions(+), 8 deletions(-) - ---- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -472,8 +472,8 @@ - <&gcc GCC_BLSP1_QUP2_I2C_APPS_CLK>; - clock-names = "iface", "core"; - clock-frequency = <400000>; -- dmas = <&blsp_dma 15>, <&blsp_dma 14>; -- dma-names = "rx", "tx"; -+ dmas = <&blsp_dma 14>, <&blsp_dma 15>; -+ dma-names = "tx", "rx"; - pinctrl-0 = <&i2c_0_pins>; - pinctrl-names = "default"; - status = "disabled"; -@@ -489,8 +489,8 @@ - <&gcc GCC_BLSP1_QUP3_I2C_APPS_CLK>; - clock-names = "iface", "core"; - clock-frequency = <100000>; -- dmas = <&blsp_dma 17>, <&blsp_dma 16>; -- dma-names = "rx", "tx"; -+ dmas = <&blsp_dma 16>, <&blsp_dma 17>; -+ dma-names = "tx", "rx"; - status = "disabled"; - }; - -@@ -504,8 +504,8 @@ - <&gcc GCC_BLSP1_QUP5_I2C_APPS_CLK>; - clock-names = "iface", "core"; - clock-frequency = <400000>; -- dmas = <&blsp_dma 21>, <&blsp_dma 20>; -- dma-names = "rx", "tx"; -+ dmas = <&blsp_dma 20>, <&blsp_dma 21>; -+ dma-names = "tx", "rx"; - status = "disabled"; - }; - -@@ -519,8 +519,8 @@ - <&gcc GCC_BLSP1_QUP6_I2C_APPS_CLK>; - clock-names = "iface", "core"; - clock-frequency = <100000>; -- dmas = <&blsp_dma 23>, <&blsp_dma 22>; -- dma-names = "rx", "tx"; -+ dmas = <&blsp_dma 22>, <&blsp_dma 23>; -+ dma-names = "tx", "rx"; - status = "disabled"; - }; - diff --git a/target/linux/ipq60xx/patches-5.15/0014-v5.19-arm64-dts-qcom-align-clocks-in-I2C-SPI-with-DT-schem.patch b/target/linux/ipq60xx/patches-5.15/0014-v5.19-arm64-dts-qcom-align-clocks-in-I2C-SPI-with-DT-schem.patch deleted file mode 100644 index e2934f2e7..000000000 --- a/target/linux/ipq60xx/patches-5.15/0014-v5.19-arm64-dts-qcom-align-clocks-in-I2C-SPI-with-DT-schem.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 553f1ea4128453cead2d38d5773ec6044c6e7626 Mon Sep 17 00:00:00 2001 -From: Krzysztof Kozlowski -Date: Tue, 5 Apr 2022 08:34:44 +0200 -Subject: [PATCH 14/44] arm64: dts: qcom: align clocks in I2C/SPI with DT - schema - -The DT schema expects clocks core-iface order. No functional change. - -Signed-off-by: Krzysztof Kozlowski -Signed-off-by: Bjorn Andersson -Link: https://lore.kernel.org/r/20220405063451.12011-3-krzysztof.kozlowski@linaro.org ---- - arch/arm64/boot/dts/qcom/ipq8074.dtsi | 24 ++++++++++++------------ - 1 file changed, 12 insertions(+), 12 deletions(-) - ---- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -468,9 +468,9 @@ - #size-cells = <0>; - reg = <0x078b6000 0x600>; - interrupts = ; -- clocks = <&gcc GCC_BLSP1_AHB_CLK>, -- <&gcc GCC_BLSP1_QUP2_I2C_APPS_CLK>; -- clock-names = "iface", "core"; -+ clocks = <&gcc GCC_BLSP1_QUP2_I2C_APPS_CLK>, -+ <&gcc GCC_BLSP1_AHB_CLK>; -+ clock-names = "core", "iface"; - clock-frequency = <400000>; - dmas = <&blsp_dma 14>, <&blsp_dma 15>; - dma-names = "tx", "rx"; -@@ -485,9 +485,9 @@ - #size-cells = <0>; - reg = <0x078b7000 0x600>; - interrupts = ; -- clocks = <&gcc GCC_BLSP1_AHB_CLK>, -- <&gcc GCC_BLSP1_QUP3_I2C_APPS_CLK>; -- clock-names = "iface", "core"; -+ clocks = <&gcc GCC_BLSP1_QUP3_I2C_APPS_CLK>, -+ <&gcc GCC_BLSP1_AHB_CLK>; -+ clock-names = "core", "iface"; - clock-frequency = <100000>; - dmas = <&blsp_dma 16>, <&blsp_dma 17>; - dma-names = "tx", "rx"; -@@ -500,9 +500,9 @@ - #size-cells = <0>; - reg = <0x78b9000 0x600>; - interrupts = ; -- clocks = <&gcc GCC_BLSP1_AHB_CLK>, -- <&gcc GCC_BLSP1_QUP5_I2C_APPS_CLK>; -- clock-names = "iface", "core"; -+ clocks = <&gcc GCC_BLSP1_QUP5_I2C_APPS_CLK>, -+ <&gcc GCC_BLSP1_AHB_CLK>; -+ clock-names = "core", "iface"; - clock-frequency = <400000>; - dmas = <&blsp_dma 20>, <&blsp_dma 21>; - dma-names = "tx", "rx"; -@@ -515,9 +515,9 @@ - #size-cells = <0>; - reg = <0x078ba000 0x600>; - interrupts = ; -- clocks = <&gcc GCC_BLSP1_AHB_CLK>, -- <&gcc GCC_BLSP1_QUP6_I2C_APPS_CLK>; -- clock-names = "iface", "core"; -+ clocks = <&gcc GCC_BLSP1_QUP6_I2C_APPS_CLK>, -+ <&gcc GCC_BLSP1_AHB_CLK>; -+ clock-names = "core", "iface"; - clock-frequency = <100000>; - dmas = <&blsp_dma 22>, <&blsp_dma 23>; - dma-names = "tx", "rx"; diff --git a/target/linux/ipq60xx/patches-5.15/0015-v5.19-arm64-dts-qcom-correct-DWC3-node-names-and-unit-addr.patch b/target/linux/ipq60xx/patches-5.15/0015-v5.19-arm64-dts-qcom-correct-DWC3-node-names-and-unit-addr.patch deleted file mode 100644 index 91be192bd..000000000 --- a/target/linux/ipq60xx/patches-5.15/0015-v5.19-arm64-dts-qcom-correct-DWC3-node-names-and-unit-addr.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 04e91eb95f7a0a9dceed2c1fcb47fbbe7f96ec52 Mon Sep 17 00:00:00 2001 -From: Krzysztof Kozlowski -Date: Wed, 4 May 2022 15:19:16 +0200 -Subject: [PATCH 15/44] arm64: dts: qcom: correct DWC3 node names and unit - addresses - -Align DWC3 USB node names with DT schema ("usb" is expected) and correct -the unit addresses to match the "reg" property. This also implies -overriding nodes by label, instead of full path. - -Signed-off-by: Krzysztof Kozlowski -Link: https://lore.kernel.org/r/20220504131923.214367-7-krzysztof.kozlowski@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - arch/arm64/boot/dts/qcom/ipq8074.dtsi | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -579,7 +579,7 @@ - resets = <&gcc GCC_USB0_BCR>; - status = "disabled"; - -- dwc_0: dwc3@8a00000 { -+ dwc_0: usb@8a00000 { - compatible = "snps,dwc3"; - reg = <0x8a00000 0xcd00>; - interrupts = ; -@@ -619,7 +619,7 @@ - resets = <&gcc GCC_USB1_BCR>; - status = "disabled"; - -- dwc_1: dwc3@8c00000 { -+ dwc_1: usb@8c00000 { - compatible = "snps,dwc3"; - reg = <0x8c00000 0xcd00>; - interrupts = ; diff --git a/target/linux/ipq60xx/patches-5.15/0016-v5.19-arm64-dts-qcom-ipq8074-add-dedicated-qcom-ipq8074-dw.patch b/target/linux/ipq60xx/patches-5.15/0016-v5.19-arm64-dts-qcom-ipq8074-add-dedicated-qcom-ipq8074-dw.patch deleted file mode 100644 index e88febabc..000000000 --- a/target/linux/ipq60xx/patches-5.15/0016-v5.19-arm64-dts-qcom-ipq8074-add-dedicated-qcom-ipq8074-dw.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 65b572a6c5bad2c9f3c784ff42d4eddedcfd85cd Mon Sep 17 00:00:00 2001 -From: Krzysztof Kozlowski -Date: Wed, 4 May 2022 15:19:17 +0200 -Subject: [PATCH 16/44] arm64: dts: qcom: ipq8074: add dedicated - qcom,ipq8074-dwc3 compatible - -Add dedicated compatible for DWC3 USB node name to allow more accurate -DT schema matching. - -Signed-off-by: Krzysztof Kozlowski -Link: https://lore.kernel.org/r/20220504131923.214367-8-krzysztof.kozlowski@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - arch/arm64/boot/dts/qcom/ipq8074.dtsi | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -554,7 +554,7 @@ - }; - - usb_0: usb@8af8800 { -- compatible = "qcom,dwc3"; -+ compatible = "qcom,ipq8074-dwc3", "qcom,dwc3"; - reg = <0x08af8800 0x400>; - #address-cells = <1>; - #size-cells = <1>; -@@ -594,7 +594,7 @@ - }; - - usb_1: usb@8cf8800 { -- compatible = "qcom,dwc3"; -+ compatible = "qcom,ipq8074-dwc3", "qcom,dwc3"; - reg = <0x08cf8800 0x400>; - #address-cells = <1>; - #size-cells = <1>; diff --git a/target/linux/ipq60xx/patches-5.15/0017-v5.19-arm64-dts-qcom-align-DWC3-USB-clocks-with-DT-schema.patch b/target/linux/ipq60xx/patches-5.15/0017-v5.19-arm64-dts-qcom-align-DWC3-USB-clocks-with-DT-schema.patch deleted file mode 100644 index 7985d7c25..000000000 --- a/target/linux/ipq60xx/patches-5.15/0017-v5.19-arm64-dts-qcom-align-DWC3-USB-clocks-with-DT-schema.patch +++ /dev/null @@ -1,39 +0,0 @@ -From e8949160470080b4c24139cfb88accc25e589f70 Mon Sep 17 00:00:00 2001 -From: Krzysztof Kozlowski -Date: Wed, 4 May 2022 15:19:22 +0200 -Subject: [PATCH 17/44] arm64: dts: qcom: align DWC3 USB clocks with DT schema - -Align order of clocks and their names with Qualcomm DWC3 USB DT schema. -No functional impact expected. - -Signed-off-by: Krzysztof Kozlowski -Link: https://lore.kernel.org/r/20220504131923.214367-13-krzysztof.kozlowski@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - arch/arm64/boot/dts/qcom/ipq8074.dtsi | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - ---- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -564,8 +564,8 @@ - <&gcc GCC_USB0_MASTER_CLK>, - <&gcc GCC_USB0_SLEEP_CLK>, - <&gcc GCC_USB0_MOCK_UTMI_CLK>; -- clock-names = "sys_noc_axi", -- "master", -+ clock-names = "cfg_noc", -+ "core", - "sleep", - "mock_utmi"; - -@@ -604,8 +604,8 @@ - <&gcc GCC_USB1_MASTER_CLK>, - <&gcc GCC_USB1_SLEEP_CLK>, - <&gcc GCC_USB1_MOCK_UTMI_CLK>; -- clock-names = "sys_noc_axi", -- "master", -+ clock-names = "cfg_noc", -+ "core", - "sleep", - "mock_utmi"; - diff --git a/target/linux/ipq60xx/patches-5.15/0018-v6.0-arm64-dts-qcom-adjust-whitespace-around.patch b/target/linux/ipq60xx/patches-5.15/0018-v6.0-arm64-dts-qcom-adjust-whitespace-around.patch deleted file mode 100644 index c1ef33807..000000000 --- a/target/linux/ipq60xx/patches-5.15/0018-v6.0-arm64-dts-qcom-adjust-whitespace-around.patch +++ /dev/null @@ -1,36 +0,0 @@ -From af38dc1085f574d575c886c0800645c8b7d4b874 Mon Sep 17 00:00:00 2001 -From: Krzysztof Kozlowski -Date: Thu, 26 May 2022 22:42:47 +0200 -Subject: [PATCH 18/44] arm64: dts: qcom: adjust whitespace around '=' - -Fix whitespace coding style: use single space instead of tabs or -multiple spaces around '=' sign in property assignment. No functional -changes (same DTB). - -Signed-off-by: Krzysztof Kozlowski -Signed-off-by: Bjorn Andersson -Link: https://lore.kernel.org/r/20220526204248.832139-1-krzysztof.kozlowski@linaro.org ---- - arch/arm64/boot/dts/qcom/ipq8074.dtsi | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -119,7 +119,7 @@ - <&xo>; - clock-names = "aux", "cfg_ahb", "ref"; - -- resets = <&gcc GCC_USB1_PHY_BCR>, -+ resets = <&gcc GCC_USB1_PHY_BCR>, - <&gcc GCC_USB3PHY_1_PHY_BCR>; - reset-names = "phy","common"; - status = "disabled"; -@@ -162,7 +162,7 @@ - <&xo>; - clock-names = "aux", "cfg_ahb", "ref"; - -- resets = <&gcc GCC_USB0_PHY_BCR>, -+ resets = <&gcc GCC_USB0_PHY_BCR>, - <&gcc GCC_USB3PHY_0_PHY_BCR>; - reset-names = "phy","common"; - status = "disabled"; diff --git a/target/linux/ipq60xx/patches-5.15/0019-v6.0-arm64-dts-qcom-Fix-sdhci-node-names-use-mmc.patch b/target/linux/ipq60xx/patches-5.15/0019-v6.0-arm64-dts-qcom-Fix-sdhci-node-names-use-mmc.patch deleted file mode 100644 index d9f76f130..000000000 --- a/target/linux/ipq60xx/patches-5.15/0019-v6.0-arm64-dts-qcom-Fix-sdhci-node-names-use-mmc.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 0d7e4bd5d554ac7471724f80aa67b664f3539f47 Mon Sep 17 00:00:00 2001 -From: Bhupesh Sharma -Date: Sun, 15 May 2022 03:24:19 +0530 -Subject: [PATCH 19/44] arm64: dts: qcom: Fix sdhci node names - use 'mmc@' - -Since the Qualcomm sdhci-msm device-tree binding has been converted -to yaml format, 'make dtbs_check' reports issues with -inconsistent 'sdhci@' convention used for specifying the -sdhci nodes. The generic mmc bindings expect 'mmc@' format -instead. - -Fix the same. - -Cc: Bjorn Andersson -Cc: Rob Herring -Signed-off-by: Bhupesh Sharma -[bjorn: Moved non-arm64 changes to separate commit] -Signed-off-by: Bjorn Andersson -Link: https://lore.kernel.org/r/20220514215424.1007718-2-bhupesh.sharma@linaro.org ---- - arch/arm64/boot/dts/qcom/ipq8074.dtsi | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -376,7 +376,7 @@ - cell-index = <0>; - }; - -- sdhc_1: sdhci@7824900 { -+ sdhc_1: mmc@7824900 { - compatible = "qcom,sdhci-msm-v4"; - reg = <0x7824900 0x500>, <0x7824000 0x800>; - reg-names = "hc_mem", "core_mem"; diff --git a/target/linux/ipq60xx/patches-5.15/0020-v6.0-arm64-dts-qcom-Fix-ordering-of-clocks-clock-names-fo.patch b/target/linux/ipq60xx/patches-5.15/0020-v6.0-arm64-dts-qcom-Fix-ordering-of-clocks-clock-names-fo.patch deleted file mode 100644 index 8cbe34aee..000000000 --- a/target/linux/ipq60xx/patches-5.15/0020-v6.0-arm64-dts-qcom-Fix-ordering-of-clocks-clock-names-fo.patch +++ /dev/null @@ -1,47 +0,0 @@ -From d923ec8397673773a3d22dc3ac0c5fccd22cd405 Mon Sep 17 00:00:00 2001 -From: Bhupesh Sharma -Date: Sun, 15 May 2022 03:24:22 +0530 -Subject: [PATCH 20/44] arm64: dts: qcom: Fix ordering of 'clocks' & - 'clock-names' for sdhci nodes - -Since the Qualcomm sdhci-msm device-tree binding has been converted -to yaml format, 'make dtbs_check' reports a number of issues with -ordering of 'clocks' & 'clock-names' for sdhci nodes: - - arch/arm64/boot/dts/qcom/ipq8074-hk10-c2.dtb: sdhci@7824900: - clock-names:0: 'iface' was expected - - arch/arm64/boot/dts/qcom/ipq8074-hk10-c2.dtb: sdhci@7824900: - clock-names:1: 'core' was expected - - arch/arm64/boot/dts/qcom/ipq8074-hk10-c2.dtb: sdhci@7824900: - clock-names:2: 'xo' was expected - -Fix the same by updating the offending 'dts' files. - -Cc: Bjorn Andersson -Cc: Rob Herring -Signed-off-by: Bhupesh Sharma -Signed-off-by: Bjorn Andersson -Link: https://lore.kernel.org/r/20220514215424.1007718-5-bhupesh.sharma@linaro.org ---- - arch/arm64/boot/dts/qcom/ipq8074.dtsi | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - ---- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -385,10 +385,10 @@ - ; - interrupt-names = "hc_irq", "pwr_irq"; - -- clocks = <&xo>, -- <&gcc GCC_SDCC1_AHB_CLK>, -- <&gcc GCC_SDCC1_APPS_CLK>; -- clock-names = "xo", "iface", "core"; -+ clocks = <&gcc GCC_SDCC1_AHB_CLK>, -+ <&gcc GCC_SDCC1_APPS_CLK>, -+ <&xo>; -+ clock-names = "iface", "core", "xo"; - max-frequency = <384000000>; - mmc-ddr-1_8v; - mmc-hs200-1_8v; diff --git a/target/linux/ipq60xx/patches-5.15/0021-v6.0-dt-bindings-clock-qcom-ipq8074-add-PPE-crypto-clock.patch b/target/linux/ipq60xx/patches-5.15/0021-v6.0-dt-bindings-clock-qcom-ipq8074-add-PPE-crypto-clock.patch deleted file mode 100644 index 3985f363a..000000000 --- a/target/linux/ipq60xx/patches-5.15/0021-v6.0-dt-bindings-clock-qcom-ipq8074-add-PPE-crypto-clock.patch +++ /dev/null @@ -1,25 +0,0 @@ -From f56aefe67c7652d38293afa83333c9228a9fbc35 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Sun, 15 May 2022 23:00:41 +0200 -Subject: [PATCH 21/44] dt-bindings: clock: qcom: ipq8074: add PPE crypto clock - -Add binding for the PPE crypto clock in IPQ8074. - -Signed-off-by: Robert Marko -Acked-by: Krzysztof Kozlowski -Signed-off-by: Bjorn Andersson -Link: https://lore.kernel.org/r/20220515210048.483898-4-robimarko@gmail.com ---- - include/dt-bindings/clock/qcom,gcc-ipq8074.h | 1 + - 1 file changed, 1 insertion(+) - ---- a/include/dt-bindings/clock/qcom,gcc-ipq8074.h -+++ b/include/dt-bindings/clock/qcom,gcc-ipq8074.h -@@ -233,6 +233,7 @@ - #define GCC_PCIE0_AXI_S_BRIDGE_CLK 224 - #define GCC_PCIE0_RCHNG_CLK_SRC 225 - #define GCC_PCIE0_RCHNG_CLK 226 -+#define GCC_CRYPTO_PPE_CLK 227 - - #define GCC_BLSP1_BCR 0 - #define GCC_BLSP1_QUP1_BCR 1 diff --git a/target/linux/ipq60xx/patches-5.15/0022-v6.0-clk-qcom-ipq8074-add-PPE-crypto-clock.patch b/target/linux/ipq60xx/patches-5.15/0022-v6.0-clk-qcom-ipq8074-add-PPE-crypto-clock.patch deleted file mode 100644 index 88b250a74..000000000 --- a/target/linux/ipq60xx/patches-5.15/0022-v6.0-clk-qcom-ipq8074-add-PPE-crypto-clock.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 3c47c458fdf4056d4682cf2474e5599d5a916b61 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Sun, 15 May 2022 23:00:42 +0200 -Subject: [PATCH 22/44] clk: qcom: ipq8074: add PPE crypto clock - -The built-in PPE engine has a dedicated clock for the EIP-197 crypto -engine. - -So, since the required clock currently missing add support for it. - -Signed-off-by: Robert Marko -Signed-off-by: Bjorn Andersson -Link: https://lore.kernel.org/r/20220515210048.483898-5-robimarko@gmail.com ---- - drivers/clk/qcom/gcc-ipq8074.c | 19 +++++++++++++++++++ - 1 file changed, 19 insertions(+) - ---- a/drivers/clk/qcom/gcc-ipq8074.c -+++ b/drivers/clk/qcom/gcc-ipq8074.c -@@ -3177,6 +3177,24 @@ static struct clk_branch gcc_nss_ptp_ref - }, - }; - -+static struct clk_branch gcc_crypto_ppe_clk = { -+ .halt_reg = 0x68310, -+ .halt_bit = 31, -+ .clkr = { -+ .enable_reg = 0x68310, -+ .enable_mask = BIT(0), -+ .hw.init = &(struct clk_init_data){ -+ .name = "gcc_crypto_ppe_clk", -+ .parent_names = (const char *[]){ -+ "nss_ppe_clk_src" -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ - static struct clk_branch gcc_nssnoc_ce_apb_clk = { - .halt_reg = 0x6830c, - .clkr = { -@@ -4649,6 +4667,7 @@ static struct clk_regmap *gcc_ipq8074_cl - [GCC_PCIE0_RCHNG_CLK_SRC] = &pcie0_rchng_clk_src.clkr, - [GCC_PCIE0_RCHNG_CLK] = &gcc_pcie0_rchng_clk.clkr, - [GCC_PCIE0_AXI_S_BRIDGE_CLK] = &gcc_pcie0_axi_s_bridge_clk.clkr, -+ [GCC_CRYPTO_PPE_CLK] = &gcc_crypto_ppe_clk.clkr, - }; - - static const struct qcom_reset_map gcc_ipq8074_resets[] = { diff --git a/target/linux/ipq60xx/patches-5.15/0023-v6.0-dt-bindings-clock-qcom-ipq8074-add-USB-GDSCs.patch b/target/linux/ipq60xx/patches-5.15/0023-v6.0-dt-bindings-clock-qcom-ipq8074-add-USB-GDSCs.patch deleted file mode 100644 index f3253edae..000000000 --- a/target/linux/ipq60xx/patches-5.15/0023-v6.0-dt-bindings-clock-qcom-ipq8074-add-USB-GDSCs.patch +++ /dev/null @@ -1,25 +0,0 @@ -From c0823201046e5a79823e3ff5fa4f0a9b5fcda14d Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Sun, 15 May 2022 23:00:45 +0200 -Subject: [PATCH 23/44] dt-bindings: clock: qcom: ipq8074: add USB GDSCs - -Add bindings for the USB GDSCs found in IPQ8074 GCC. - -Signed-off-by: Robert Marko -Acked-by: Krzysztof Kozlowski -Signed-off-by: Bjorn Andersson -Link: https://lore.kernel.org/r/20220515210048.483898-8-robimarko@gmail.com ---- - include/dt-bindings/clock/qcom,gcc-ipq8074.h | 3 +++ - 1 file changed, 3 insertions(+) - ---- a/include/dt-bindings/clock/qcom,gcc-ipq8074.h -+++ b/include/dt-bindings/clock/qcom,gcc-ipq8074.h -@@ -368,4 +368,7 @@ - #define GCC_PCIE1_AXI_MASTER_STICKY_ARES 130 - #define GCC_PCIE0_AXI_SLAVE_STICKY_ARES 131 - -+#define USB0_GDSC 0 -+#define USB1_GDSC 1 -+ - #endif diff --git a/target/linux/ipq60xx/patches-5.15/0024-v6.0-clk-qcom-ipq8074-add-USB-GDSCs.patch b/target/linux/ipq60xx/patches-5.15/0024-v6.0-clk-qcom-ipq8074-add-USB-GDSCs.patch deleted file mode 100644 index 9e858f530..000000000 --- a/target/linux/ipq60xx/patches-5.15/0024-v6.0-clk-qcom-ipq8074-add-USB-GDSCs.patch +++ /dev/null @@ -1,79 +0,0 @@ -From 248fb3267c23749059baa231e21650a68771abef Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Sun, 15 May 2022 23:00:46 +0200 -Subject: [PATCH 24/44] clk: qcom: ipq8074: add USB GDSCs - -Add GDSC-s for each of the two USB controllers built-in the IPQ8074. - -Signed-off-by: Robert Marko -Signed-off-by: Bjorn Andersson -Link: https://lore.kernel.org/r/20220515210048.483898-9-robimarko@gmail.com ---- - drivers/clk/qcom/Kconfig | 1 + - drivers/clk/qcom/gcc-ipq8074.c | 24 ++++++++++++++++++++++++ - 2 files changed, 25 insertions(+) - ---- a/drivers/clk/qcom/Kconfig -+++ b/drivers/clk/qcom/Kconfig -@@ -167,6 +167,7 @@ config IPQ_LCC_806X - - config IPQ_GCC_8074 - tristate "IPQ8074 Global Clock Controller" -+ select QCOM_GDSC - help - Support for global clock controller on ipq8074 devices. - Say Y if you want to use peripheral devices such as UART, SPI, ---- a/drivers/clk/qcom/gcc-ipq8074.c -+++ b/drivers/clk/qcom/gcc-ipq8074.c -@@ -22,6 +22,7 @@ - #include "clk-alpha-pll.h" - #include "clk-regmap-divider.h" - #include "clk-regmap-mux.h" -+#include "gdsc.h" - #include "reset.h" - - enum { -@@ -4402,6 +4403,22 @@ static struct clk_branch gcc_pcie0_axi_s - }, - }; - -+static struct gdsc usb0_gdsc = { -+ .gdscr = 0x3e078, -+ .pd = { -+ .name = "usb0_gdsc", -+ }, -+ .pwrsts = PWRSTS_OFF_ON, -+}; -+ -+static struct gdsc usb1_gdsc = { -+ .gdscr = 0x3f078, -+ .pd = { -+ .name = "usb1_gdsc", -+ }, -+ .pwrsts = PWRSTS_OFF_ON, -+}; -+ - static const struct alpha_pll_config ubi32_pll_config = { - .l = 0x4e, - .config_ctl_val = 0x200d4aa8, -@@ -4805,6 +4822,11 @@ static const struct qcom_reset_map gcc_i - [GCC_PCIE1_AXI_MASTER_STICKY_ARES] = { 0x76040, 6 }, - }; - -+static struct gdsc *gcc_ipq8074_gdscs[] = { -+ [USB0_GDSC] = &usb0_gdsc, -+ [USB1_GDSC] = &usb1_gdsc, -+}; -+ - static const struct of_device_id gcc_ipq8074_match_table[] = { - { .compatible = "qcom,gcc-ipq8074" }, - { } -@@ -4827,6 +4849,8 @@ static const struct qcom_cc_desc gcc_ipq - .num_resets = ARRAY_SIZE(gcc_ipq8074_resets), - .clk_hws = gcc_ipq8074_hws, - .num_clk_hws = ARRAY_SIZE(gcc_ipq8074_hws), -+ .gdscs = gcc_ipq8074_gdscs, -+ .num_gdscs = ARRAY_SIZE(gcc_ipq8074_gdscs), - }; - - static int gcc_ipq8074_probe(struct platform_device *pdev) diff --git a/target/linux/ipq60xx/patches-5.15/0025-v6.0-arm64-dts-qcom-ipq8074-add-USB-power-domains.patch b/target/linux/ipq60xx/patches-5.15/0025-v6.0-arm64-dts-qcom-ipq8074-add-USB-power-domains.patch deleted file mode 100644 index b4c8d5be9..000000000 --- a/target/linux/ipq60xx/patches-5.15/0025-v6.0-arm64-dts-qcom-ipq8074-add-USB-power-domains.patch +++ /dev/null @@ -1,43 +0,0 @@ -From e8516c04110438230314ddbe94879ecb4a5db5df Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Sun, 15 May 2022 23:00:48 +0200 -Subject: [PATCH 25/44] arm64: dts: qcom: ipq8074: add USB power domains - -Add USB power domains provided by GCC GDSCs. -Add the required #power-domain-cells to the GCC as well. - -Signed-off-by: Robert Marko -Signed-off-by: Bjorn Andersson -Link: https://lore.kernel.org/r/20220515210048.483898-11-robimarko@gmail.com ---- - arch/arm64/boot/dts/qcom/ipq8074.dtsi | 5 +++++ - 1 file changed, 5 insertions(+) - ---- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -348,6 +348,7 @@ - compatible = "qcom,gcc-ipq8074"; - reg = <0x01800000 0x80000>; - #clock-cells = <0x1>; -+ #power-domain-cells = <1>; - #reset-cells = <0x1>; - }; - -@@ -576,6 +577,8 @@ - <133330000>, - <19200000>; - -+ power-domains = <&gcc USB0_GDSC>; -+ - resets = <&gcc GCC_USB0_BCR>; - status = "disabled"; - -@@ -616,6 +619,8 @@ - <133330000>, - <19200000>; - -+ power-domains = <&gcc USB1_GDSC>; -+ - resets = <&gcc GCC_USB1_BCR>; - status = "disabled"; - diff --git a/target/linux/ipq60xx/patches-5.15/0026-v6.0-arm64-dts-qcom-ipq8074-move-ARMv8-timer-out-of-SoC-n.patch b/target/linux/ipq60xx/patches-5.15/0026-v6.0-arm64-dts-qcom-ipq8074-move-ARMv8-timer-out-of-SoC-n.patch deleted file mode 100644 index 9c1777ca3..000000000 --- a/target/linux/ipq60xx/patches-5.15/0026-v6.0-arm64-dts-qcom-ipq8074-move-ARMv8-timer-out-of-SoC-n.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 510f246cf8f6af8c0d7a46d22448b812fd9a14a4 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Mon, 4 Jul 2022 13:33:18 +0200 -Subject: [PATCH 26/44] arm64: dts: qcom: ipq8074: move ARMv8 timer out of SoC - node - -The ARM timer is usually considered not part of SoC node, just like -other ARM designed blocks (PMU, PSCI). This fixes dtbs_check warning: - -arch/arm64/boot/dts/qcom/ipq8072-ax9000.dtb: soc: timer: {'compatible': ['arm,armv8-timer'], 'interrupts': [[1, 2, 3848], [1, 3, 3848], [1, 4, 3848], [1, 1, 3848]]} should not be valid under {'type': 'object'} - From schema: dtschema/schemas/simple-bus.yaml - -Signed-off-by: Robert Marko -Acked-by: Krzysztof Kozlowski -[bjorn: Moved node after "soc" for alphabetical ordering] -Signed-off-by: Bjorn Andersson -Link: https://lore.kernel.org/r/20220704113318.623102-1-robimarko@gmail.com ---- - arch/arm64/boot/dts/qcom/ipq8074.dtsi | 16 ++++++++-------- - 1 file changed, 8 insertions(+), 8 deletions(-) - ---- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -654,14 +654,6 @@ - }; - }; - -- timer { -- compatible = "arm,armv8-timer"; -- interrupts = , -- , -- , -- ; -- }; -- - watchdog: watchdog@b017000 { - compatible = "qcom,kpss-wdt"; - reg = <0xb017000 0x1000>; -@@ -853,4 +845,12 @@ - status = "disabled"; - }; - }; -+ -+ timer { -+ compatible = "arm,armv8-timer"; -+ interrupts = , -+ , -+ , -+ ; -+ }; - }; diff --git a/target/linux/ipq60xx/patches-5.15/0027-v6.0-arm64-dts-qcom-ipq8074-add-reset-to-SDHCI.patch b/target/linux/ipq60xx/patches-5.15/0027-v6.0-arm64-dts-qcom-ipq8074-add-reset-to-SDHCI.patch deleted file mode 100644 index 36e0d6206..000000000 --- a/target/linux/ipq60xx/patches-5.15/0027-v6.0-arm64-dts-qcom-ipq8074-add-reset-to-SDHCI.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 8cef5828706a1584b4dadf3f4b707a392bc8c231 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Mon, 4 Jul 2022 16:35:54 +0200 -Subject: [PATCH 27/44] arm64: dts: qcom: ipq8074: add reset to SDHCI - -Add reset to SDHCI controller so it can be reset to avoid timeout issues -after software reset due to bootloader set configuration. - -Signed-off-by: Robert Marko -Reviewed-by: Konrad Dybcio -Acked-by: Krzysztof Kozlowski -Signed-off-by: Bjorn Andersson -Link: https://lore.kernel.org/r/20220704143554.1180927-2-robimarko@gmail.com ---- - arch/arm64/boot/dts/qcom/ipq8074.dtsi | 1 + - 1 file changed, 1 insertion(+) - ---- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -390,6 +390,7 @@ - <&gcc GCC_SDCC1_APPS_CLK>, - <&xo>; - clock-names = "iface", "core", "xo"; -+ resets = <&gcc GCC_SDCC1_BCR>; - max-frequency = <384000000>; - mmc-ddr-1_8v; - mmc-hs200-1_8v; diff --git a/target/linux/ipq60xx/patches-5.15/0028-v6.0-arm64-dts-qcom-ipq8074-drop-USB-PHY-clock-index.patch b/target/linux/ipq60xx/patches-5.15/0028-v6.0-arm64-dts-qcom-ipq8074-drop-USB-PHY-clock-index.patch deleted file mode 100644 index 76f643b41..000000000 --- a/target/linux/ipq60xx/patches-5.15/0028-v6.0-arm64-dts-qcom-ipq8074-drop-USB-PHY-clock-index.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 2bf80b5de7c2598972af28adc09e8e667b528d11 Mon Sep 17 00:00:00 2001 -From: Johan Hovold -Date: Tue, 5 Jul 2022 13:40:22 +0200 -Subject: [PATCH 28/44] arm64: dts: qcom: ipq8074: drop USB PHY clock index - -The QMP USB PHY provides a single clock so drop the redundant clock -index. - -Signed-off-by: Johan Hovold -Reviewed-by: Dmitry Baryshkov -Signed-off-by: Bjorn Andersson -Link: https://lore.kernel.org/r/20220705114032.22787-5-johan+linaro@kernel.org ---- - arch/arm64/boot/dts/qcom/ipq8074.dtsi | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -130,7 +130,7 @@ - <0x00058800 0x1f8>, /* PCS */ - <0x00058600 0x044>; /* PCS misc*/ - #phy-cells = <0>; -- #clock-cells = <1>; -+ #clock-cells = <0>; - clocks = <&gcc GCC_USB1_PIPE_CLK>; - clock-names = "pipe0"; - clock-output-names = "usb3phy_1_cc_pipe_clk"; -@@ -173,7 +173,7 @@ - <0x00078800 0x1f8>, /* PCS */ - <0x00078600 0x044>; /* PCS misc*/ - #phy-cells = <0>; -- #clock-cells = <1>; -+ #clock-cells = <0>; - clocks = <&gcc GCC_USB0_PIPE_CLK>; - clock-names = "pipe0"; - clock-output-names = "usb3phy_0_cc_pipe_clk"; diff --git a/target/linux/ipq60xx/patches-5.15/0029-v6.0-arm64-dts-qcom-ipq8074-add-APCS-node.patch b/target/linux/ipq60xx/patches-5.15/0029-v6.0-arm64-dts-qcom-ipq8074-add-APCS-node.patch deleted file mode 100644 index 393ef7ac2..000000000 --- a/target/linux/ipq60xx/patches-5.15/0029-v6.0-arm64-dts-qcom-ipq8074-add-APCS-node.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 73ea147a5caa82c94486076186af2c7dc1894a97 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Thu, 7 Jul 2022 19:37:33 +0200 -Subject: [PATCH 29/44] arm64: dts: qcom: ipq8074: add APCS node - -APCS now has support for providing the APSS clocks as the child device -for IPQ8074. - -So, add the required DT node for it as it will later be used as the CPU -clocksource. - -Signed-off-by: Robert Marko -Reviewed-by: Dmitry Baryshkov -[bjorn: Sorted node based on address] -Signed-off-by: Bjorn Andersson -Link: https://lore.kernel.org/r/20220707173733.404947-4-robimarko@gmail.com ---- - arch/arm64/boot/dts/qcom/ipq8074.dtsi | 8 ++++++++ - 1 file changed, 8 insertions(+) - ---- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -663,6 +663,14 @@ - timeout-sec = <30>; - }; - -+ apcs_glb: mailbox@b111000 { -+ compatible = "qcom,ipq8074-apcs-apps-global"; -+ reg = <0x0b111000 0x6000>; -+ -+ #clock-cells = <1>; -+ #mbox-cells = <1>; -+ }; -+ - timer@b120000 { - #address-cells = <1>; - #size-cells = <1>; diff --git a/target/linux/ipq60xx/patches-5.15/0030-v6.0-arm64-dts-qcom-ipq8074-add-size-address-cells-to-DTS.patch b/target/linux/ipq60xx/patches-5.15/0030-v6.0-arm64-dts-qcom-ipq8074-add-size-address-cells-to-DTS.patch deleted file mode 100644 index 02db52eae..000000000 --- a/target/linux/ipq60xx/patches-5.15/0030-v6.0-arm64-dts-qcom-ipq8074-add-size-address-cells-to-DTS.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 254bf23fe2e0c73d75a0bf4f37579e15433b75e0 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Fri, 8 Jul 2022 15:38:45 +0200 -Subject: [PATCH 30/44] arm64: dts: qcom: ipq8074: add #size/address-cells to - DTSI - -Add #size-cells and #address-cells to the SoC DTSI to avoid duplicating -the same properties in board DTS files. - -Remove the mentioned properties from current board DTS files. - -Signed-off-by: Robert Marko -Signed-off-by: Bjorn Andersson -Link: https://lore.kernel.org/r/20220708133846.599735-1-robimarko@gmail.com ---- - arch/arm64/boot/dts/qcom/ipq8074-hk01.dts | 2 -- - arch/arm64/boot/dts/qcom/ipq8074-hk10.dtsi | 3 --- - arch/arm64/boot/dts/qcom/ipq8074.dtsi | 3 +++ - 3 files changed, 3 insertions(+), 5 deletions(-) - ---- a/arch/arm64/boot/dts/qcom/ipq8074-hk01.dts -+++ b/arch/arm64/boot/dts/qcom/ipq8074-hk01.dts -@@ -5,8 +5,6 @@ - #include "ipq8074.dtsi" - - / { -- #address-cells = <0x2>; -- #size-cells = <0x2>; - model = "Qualcomm Technologies, Inc. IPQ8074-HK01"; - compatible = "qcom,ipq8074-hk01", "qcom,ipq8074"; - interrupt-parent = <&intc>; ---- a/arch/arm64/boot/dts/qcom/ipq8074-hk10.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq8074-hk10.dtsi -@@ -7,9 +7,6 @@ - #include "ipq8074.dtsi" - - / { -- #address-cells = <0x2>; -- #size-cells = <0x2>; -- - interrupt-parent = <&intc>; - - aliases { ---- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -7,6 +7,9 @@ - #include - - / { -+ #address-cells = <2>; -+ #size-cells = <2>; -+ - model = "Qualcomm Technologies, Inc. IPQ8074"; - compatible = "qcom,ipq8074"; - diff --git a/target/linux/ipq60xx/patches-5.15/0031-v6.0-arm64-dts-qcom-ipq8074-add-interrupt-parent-to-DTSI.patch b/target/linux/ipq60xx/patches-5.15/0031-v6.0-arm64-dts-qcom-ipq8074-add-interrupt-parent-to-DTSI.patch deleted file mode 100644 index bbe4bf1bd..000000000 --- a/target/linux/ipq60xx/patches-5.15/0031-v6.0-arm64-dts-qcom-ipq8074-add-interrupt-parent-to-DTSI.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 520877b4d26ba4e6d08b5e9579f166ca2a934e81 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Fri, 8 Jul 2022 15:38:46 +0200 -Subject: [PATCH 31/44] arm64: dts: qcom: ipq8074: add interrupt-parent to DTSI - -Add interrupt-parent to the SoC DTSI to avoid duplicating it in each board -DTS file. - -Remove interrupt-parent from existing board DTS files. - -Signed-off-by: Robert Marko -Signed-off-by: Bjorn Andersson -Link: https://lore.kernel.org/r/20220708133846.599735-2-robimarko@gmail.com ---- - arch/arm64/boot/dts/qcom/ipq8074-hk01.dts | 1 - - arch/arm64/boot/dts/qcom/ipq8074-hk10.dtsi | 2 -- - arch/arm64/boot/dts/qcom/ipq8074.dtsi | 1 + - 3 files changed, 1 insertion(+), 3 deletions(-) - ---- a/arch/arm64/boot/dts/qcom/ipq8074-hk01.dts -+++ b/arch/arm64/boot/dts/qcom/ipq8074-hk01.dts -@@ -7,7 +7,6 @@ - / { - model = "Qualcomm Technologies, Inc. IPQ8074-HK01"; - compatible = "qcom,ipq8074-hk01", "qcom,ipq8074"; -- interrupt-parent = <&intc>; - - aliases { - serial0 = &blsp1_uart5; ---- a/arch/arm64/boot/dts/qcom/ipq8074-hk10.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq8074-hk10.dtsi -@@ -7,8 +7,6 @@ - #include "ipq8074.dtsi" - - / { -- interrupt-parent = <&intc>; -- - aliases { - serial0 = &blsp1_uart5; - }; ---- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -12,6 +12,7 @@ - - model = "Qualcomm Technologies, Inc. IPQ8074"; - compatible = "qcom,ipq8074"; -+ interrupt-parent = <&intc>; - - clocks { - sleep_clk: sleep_clk { diff --git a/target/linux/ipq60xx/patches-5.15/0032-v6.0-regulator-qcom_spmi-add-support-for-HT_P150.patch b/target/linux/ipq60xx/patches-5.15/0032-v6.0-regulator-qcom_spmi-add-support-for-HT_P150.patch deleted file mode 100644 index be0479714..000000000 --- a/target/linux/ipq60xx/patches-5.15/0032-v6.0-regulator-qcom_spmi-add-support-for-HT_P150.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 8928dcb644461e72608dbea26af4d072868ae41b Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Mon, 4 Jul 2022 23:23:54 +0200 -Subject: [PATCH 32/44] regulator: qcom_spmi: add support for HT_P150 - -HT_P150 is a LDO PMOS regulator based on LV P150 using HFS430 layout -found in PMP8074 and PMS405 PMIC-s. - -Both PMP8074 and PMS405 define the programmable range as 1.616V to 3.304V -but the actual MAX output voltage depends on the exact LDO in each of -the PMIC-s. - -It has a max current of 150mA, voltage step of 8mV. - -Signed-off-by: Robert Marko -Link: https://lore.kernel.org/r/20220704212402.1715182-4-robimarko@gmail.com -Signed-off-by: Mark Brown ---- - drivers/regulator/qcom_spmi-regulator.c | 7 +++++++ - 1 file changed, 7 insertions(+) - ---- a/drivers/regulator/qcom_spmi-regulator.c -+++ b/drivers/regulator/qcom_spmi-regulator.c -@@ -164,6 +164,7 @@ enum spmi_regulator_subtype { - SPMI_REGULATOR_SUBTYPE_ULT_HF_CTL3 = 0x0f, - SPMI_REGULATOR_SUBTYPE_ULT_HF_CTL4 = 0x10, - SPMI_REGULATOR_SUBTYPE_HFS430 = 0x0a, -+ SPMI_REGULATOR_SUBTYPE_HT_P150 = 0x35, - }; - - enum spmi_common_regulator_registers { -@@ -544,6 +545,10 @@ static struct spmi_voltage_range hfs430_ - SPMI_VOLTAGE_RANGE(0, 320000, 320000, 2040000, 2040000, 8000), - }; - -+static struct spmi_voltage_range ht_p150_ranges[] = { -+ SPMI_VOLTAGE_RANGE(0, 1616000, 1616000, 3304000, 3304000, 8000), -+}; -+ - static DEFINE_SPMI_SET_POINTS(pldo); - static DEFINE_SPMI_SET_POINTS(nldo1); - static DEFINE_SPMI_SET_POINTS(nldo2); -@@ -564,6 +569,7 @@ static DEFINE_SPMI_SET_POINTS(nldo660); - static DEFINE_SPMI_SET_POINTS(ht_lvpldo); - static DEFINE_SPMI_SET_POINTS(ht_nldo); - static DEFINE_SPMI_SET_POINTS(hfs430); -+static DEFINE_SPMI_SET_POINTS(ht_p150); - - static inline int spmi_vreg_read(struct spmi_regulator *vreg, u16 addr, u8 *buf, - int len) -@@ -1458,6 +1464,7 @@ static const struct regulator_ops spmi_h - - static const struct spmi_regulator_mapping supported_regulators[] = { - /* type subtype dig_min dig_max ltype ops setpoints hpm_min */ -+ SPMI_VREG(LDO, HT_P150, 0, INF, HFS430, hfs430, ht_p150, 10000), - SPMI_VREG(BUCK, GP_CTL, 0, INF, SMPS, smps, smps, 100000), - SPMI_VREG(BUCK, HFS430, 0, INF, HFS430, hfs430, hfs430, 10000), - SPMI_VREG(LDO, N300, 0, INF, LDO, ldo, nldo1, 10000), diff --git a/target/linux/ipq60xx/patches-5.15/0033-v6.0-regulator-qcom_spmi-add-support-for-HT_P600.patch b/target/linux/ipq60xx/patches-5.15/0033-v6.0-regulator-qcom_spmi-add-support-for-HT_P600.patch deleted file mode 100644 index a326481ea..000000000 --- a/target/linux/ipq60xx/patches-5.15/0033-v6.0-regulator-qcom_spmi-add-support-for-HT_P600.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 2ba036ce8e99673073adc5ac62e7768a47725567 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Mon, 4 Jul 2022 23:23:55 +0200 -Subject: [PATCH 33/44] regulator: qcom_spmi: add support for HT_P600 - -HT_P600 is a LDO PMOS regulator based on LV P600 using HFS430 layout -found in PMP8074 and PMS405 PMIC-s. - -Both PMP8074 and PMS405 define the programmable range as 1.704 to 1.896V -but the actual MAX output voltage depends on the exact LDO in each of -the PMIC-s. -Their usual voltage that they are used is 1.8V. - -It has a max current of 600mA, voltage step of 8mV. - -Signed-off-by: Robert Marko -Link: https://lore.kernel.org/r/20220704212402.1715182-5-robimarko@gmail.com -Signed-off-by: Mark Brown ---- - drivers/regulator/qcom_spmi-regulator.c | 7 +++++++ - 1 file changed, 7 insertions(+) - ---- a/drivers/regulator/qcom_spmi-regulator.c -+++ b/drivers/regulator/qcom_spmi-regulator.c -@@ -165,6 +165,7 @@ enum spmi_regulator_subtype { - SPMI_REGULATOR_SUBTYPE_ULT_HF_CTL4 = 0x10, - SPMI_REGULATOR_SUBTYPE_HFS430 = 0x0a, - SPMI_REGULATOR_SUBTYPE_HT_P150 = 0x35, -+ SPMI_REGULATOR_SUBTYPE_HT_P600 = 0x3d, - }; - - enum spmi_common_regulator_registers { -@@ -549,6 +550,10 @@ static struct spmi_voltage_range ht_p150 - SPMI_VOLTAGE_RANGE(0, 1616000, 1616000, 3304000, 3304000, 8000), - }; - -+static struct spmi_voltage_range ht_p600_ranges[] = { -+ SPMI_VOLTAGE_RANGE(0, 1704000, 1704000, 1896000, 1896000, 8000), -+}; -+ - static DEFINE_SPMI_SET_POINTS(pldo); - static DEFINE_SPMI_SET_POINTS(nldo1); - static DEFINE_SPMI_SET_POINTS(nldo2); -@@ -570,6 +575,7 @@ static DEFINE_SPMI_SET_POINTS(ht_lvpldo) - static DEFINE_SPMI_SET_POINTS(ht_nldo); - static DEFINE_SPMI_SET_POINTS(hfs430); - static DEFINE_SPMI_SET_POINTS(ht_p150); -+static DEFINE_SPMI_SET_POINTS(ht_p600); - - static inline int spmi_vreg_read(struct spmi_regulator *vreg, u16 addr, u8 *buf, - int len) -@@ -1464,6 +1470,7 @@ static const struct regulator_ops spmi_h - - static const struct spmi_regulator_mapping supported_regulators[] = { - /* type subtype dig_min dig_max ltype ops setpoints hpm_min */ -+ SPMI_VREG(LDO, HT_P600, 0, INF, HFS430, hfs430, ht_p600, 10000), - SPMI_VREG(LDO, HT_P150, 0, INF, HFS430, hfs430, ht_p150, 10000), - SPMI_VREG(BUCK, GP_CTL, 0, INF, SMPS, smps, smps, 100000), - SPMI_VREG(BUCK, HFS430, 0, INF, HFS430, hfs430, hfs430, 10000), diff --git a/target/linux/ipq60xx/patches-5.15/0034-v6.0-regulator-qcom_spmi-add-support-for-PMP8074-regulato.patch b/target/linux/ipq60xx/patches-5.15/0034-v6.0-regulator-qcom_spmi-add-support-for-PMP8074-regulato.patch deleted file mode 100644 index 49eac1065..000000000 --- a/target/linux/ipq60xx/patches-5.15/0034-v6.0-regulator-qcom_spmi-add-support-for-PMP8074-regulato.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 933b687758646242fc7410edb06da70fe7540cdc Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Mon, 4 Jul 2022 23:23:57 +0200 -Subject: [PATCH 34/44] regulator: qcom_spmi: add support for PMP8074 - regulators - -PMP8074 is a companion PMIC for the Qualcomm IPQ8074 WiSoC-s. - -It features 5 HF-SMPS and 13 LDO regulators. - -HF-SMPS regulators are Buck HFS430 regulators. -L1, L2 and L3 are HT_N1200_ST subtype LDO regulators. -L4 is HT_N300_ST subtype LDO regulator. -L5 and L6 are HT_P600 subtype LDO regulators. -L7, L11, L12 and L13 are HT_P150 subtype LDO regulators. -L10 is HT_P50 subtype LDO regulator. - -This commit adds support for all of the buck regulators and LDO-s except -for L10 as I dont have documentation on its output voltage range. - -S3 is the CPU cluster voltage supply, S4 supplies the UBI32 NPU cores -and L11 is the SDIO/eMMC I/O voltage regulator required for high speeds. - -Signed-off-by: Robert Marko -Link: https://lore.kernel.org/r/20220704212402.1715182-7-robimarko@gmail.com -Signed-off-by: Mark Brown ---- - drivers/regulator/qcom_spmi-regulator.c | 23 +++++++++++++++++++++++ - 1 file changed, 23 insertions(+) - ---- a/drivers/regulator/qcom_spmi-regulator.c -+++ b/drivers/regulator/qcom_spmi-regulator.c -@@ -2101,6 +2101,28 @@ static const struct spmi_regulator_data - { } - }; - -+static const struct spmi_regulator_data pmp8074_regulators[] = { -+ { "s1", 0x1400, "vdd_s1"}, -+ { "s2", 0x1700, "vdd_s2"}, -+ { "s3", 0x1a00, "vdd_s3"}, -+ { "s4", 0x1d00, "vdd_s4"}, -+ { "s5", 0x2000, "vdd_s5"}, -+ { "l1", 0x4000, "vdd_l1_l2"}, -+ { "l2", 0x4100, "vdd_l1_l2"}, -+ { "l3", 0x4200, "vdd_l3_l8"}, -+ { "l4", 0x4300, "vdd_l4"}, -+ { "l5", 0x4400, "vdd_l5_l6_l15"}, -+ { "l6", 0x4500, "vdd_l5_l6_l15"}, -+ { "l7", 0x4600, "vdd_l7"}, -+ { "l8", 0x4700, "vdd_l3_l8"}, -+ { "l9", 0x4800, "vdd_l9"}, -+ /* l10 is currently unsupported HT_P50 */ -+ { "l11", 0x4a00, "vdd_l10_l11_l12_l13"}, -+ { "l12", 0x4b00, "vdd_l10_l11_l12_l13"}, -+ { "l13", 0x4c00, "vdd_l10_l11_l12_l13"}, -+ { } -+}; -+ - static const struct spmi_regulator_data pms405_regulators[] = { - { "s3", 0x1a00, "vdd_s3"}, - { } -@@ -2117,6 +2139,7 @@ static const struct of_device_id qcom_sp - { .compatible = "qcom,pmi8994-regulators", .data = &pmi8994_regulators }, - { .compatible = "qcom,pm660-regulators", .data = &pm660_regulators }, - { .compatible = "qcom,pm660l-regulators", .data = &pm660l_regulators }, -+ { .compatible = "qcom,pmp8074-regulators", .data = &pmp8074_regulators }, - { .compatible = "qcom,pms405-regulators", .data = &pms405_regulators }, - { } - }; diff --git a/target/linux/ipq60xx/patches-5.15/0035-v6.0-pinctrl-qcom-pmic-gpio-add-support-for-PMP8074.patch b/target/linux/ipq60xx/patches-5.15/0035-v6.0-pinctrl-qcom-pmic-gpio-add-support-for-PMP8074.patch deleted file mode 100644 index 565d0513c..000000000 --- a/target/linux/ipq60xx/patches-5.15/0035-v6.0-pinctrl-qcom-pmic-gpio-add-support-for-PMP8074.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 55545dc54f015387dccfb3c8fe20115c5f21b8a7 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Mon, 11 Jul 2022 22:34:05 +0200 -Subject: [PATCH 35/44] pinctrl: qcom-pmic-gpio: add support for PMP8074 - -PMP8074 has 12 GPIO-s with holes on GPIO1 and GPIO12. - -Signed-off-by: Robert Marko -Link: https://lore.kernel.org/r/20220711203408.2949888-4-robimarko@gmail.com -Signed-off-by: Linus Walleij ---- - drivers/pinctrl/qcom/pinctrl-spmi-gpio.c | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c -+++ b/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c -@@ -1167,6 +1167,8 @@ static const struct of_device_id pmic_gp - { .compatible = "qcom,pmi8998-gpio", .data = (void *) 14 }, - { .compatible = "qcom,pmk8350-gpio", .data = (void *) 4 }, - { .compatible = "qcom,pmm8155au-gpio", .data = (void *) 10 }, -+ /* pmp8074 has 12 GPIOs with holes on 1 and 12 */ -+ { .compatible = "qcom,pmp8074-gpio", .data = (void *) 12 }, - { .compatible = "qcom,pmr735a-gpio", .data = (void *) 4 }, - { .compatible = "qcom,pmr735b-gpio", .data = (void *) 4 }, - /* pms405 has 12 GPIOs with holes on 1, 9, and 10 */ diff --git a/target/linux/ipq60xx/patches-5.15/0036-v5.16-mfd-qcom-spmi-pmic-Sort-compatibles-in-the-driver.patch b/target/linux/ipq60xx/patches-5.15/0036-v5.16-mfd-qcom-spmi-pmic-Sort-compatibles-in-the-driver.patch deleted file mode 100644 index bbfb22614..000000000 --- a/target/linux/ipq60xx/patches-5.15/0036-v5.16-mfd-qcom-spmi-pmic-Sort-compatibles-in-the-driver.patch +++ /dev/null @@ -1,60 +0,0 @@ -From f76d65737cff6f41f0fab7a46a742d89c08fd652 Mon Sep 17 00:00:00 2001 -From: Bjorn Andersson -Date: Sun, 17 Oct 2021 09:12:16 -0700 -Subject: [PATCH 36/44] mfd: qcom-spmi-pmic: Sort compatibles in the driver - -Sort the compatibles in the driver, to make it easier to validate that -the DT binding and driver are in sync. - -Signed-off-by: Bjorn Andersson -Signed-off-by: Lee Jones -Link: https://lore.kernel.org/r/20211017161218.2378176-2-bjorn.andersson@linaro.org ---- - drivers/mfd/qcom-spmi-pmic.c | 30 +++++++++++++++--------------- - 1 file changed, 15 insertions(+), 15 deletions(-) - ---- a/drivers/mfd/qcom-spmi-pmic.c -+++ b/drivers/mfd/qcom-spmi-pmic.c -@@ -40,27 +40,27 @@ - #define PM660_SUBTYPE 0x1B - - static const struct of_device_id pmic_spmi_id_table[] = { -- { .compatible = "qcom,spmi-pmic", .data = (void *)COMMON_SUBTYPE }, -- { .compatible = "qcom,pm8941", .data = (void *)PM8941_SUBTYPE }, -- { .compatible = "qcom,pm8841", .data = (void *)PM8841_SUBTYPE }, -+ { .compatible = "qcom,pm660", .data = (void *)PM660_SUBTYPE }, -+ { .compatible = "qcom,pm660l", .data = (void *)PM660L_SUBTYPE }, -+ { .compatible = "qcom,pm8004", .data = (void *)PM8004_SUBTYPE }, -+ { .compatible = "qcom,pm8005", .data = (void *)PM8005_SUBTYPE }, - { .compatible = "qcom,pm8019", .data = (void *)PM8019_SUBTYPE }, -- { .compatible = "qcom,pm8226", .data = (void *)PM8226_SUBTYPE }, - { .compatible = "qcom,pm8110", .data = (void *)PM8110_SUBTYPE }, -- { .compatible = "qcom,pma8084", .data = (void *)PMA8084_SUBTYPE }, -- { .compatible = "qcom,pmi8962", .data = (void *)PMI8962_SUBTYPE }, -- { .compatible = "qcom,pmd9635", .data = (void *)PMD9635_SUBTYPE }, -- { .compatible = "qcom,pm8994", .data = (void *)PM8994_SUBTYPE }, -- { .compatible = "qcom,pmi8994", .data = (void *)PMI8994_SUBTYPE }, -- { .compatible = "qcom,pm8916", .data = (void *)PM8916_SUBTYPE }, -- { .compatible = "qcom,pm8004", .data = (void *)PM8004_SUBTYPE }, -+ { .compatible = "qcom,pm8226", .data = (void *)PM8226_SUBTYPE }, -+ { .compatible = "qcom,pm8841", .data = (void *)PM8841_SUBTYPE }, - { .compatible = "qcom,pm8909", .data = (void *)PM8909_SUBTYPE }, -+ { .compatible = "qcom,pm8916", .data = (void *)PM8916_SUBTYPE }, -+ { .compatible = "qcom,pm8941", .data = (void *)PM8941_SUBTYPE }, - { .compatible = "qcom,pm8950", .data = (void *)PM8950_SUBTYPE }, -- { .compatible = "qcom,pmi8950", .data = (void *)PMI8950_SUBTYPE }, -+ { .compatible = "qcom,pm8994", .data = (void *)PM8994_SUBTYPE }, - { .compatible = "qcom,pm8998", .data = (void *)PM8998_SUBTYPE }, -+ { .compatible = "qcom,pma8084", .data = (void *)PMA8084_SUBTYPE }, -+ { .compatible = "qcom,pmd9635", .data = (void *)PMD9635_SUBTYPE }, -+ { .compatible = "qcom,pmi8950", .data = (void *)PMI8950_SUBTYPE }, -+ { .compatible = "qcom,pmi8962", .data = (void *)PMI8962_SUBTYPE }, -+ { .compatible = "qcom,pmi8994", .data = (void *)PMI8994_SUBTYPE }, - { .compatible = "qcom,pmi8998", .data = (void *)PMI8998_SUBTYPE }, -- { .compatible = "qcom,pm8005", .data = (void *)PM8005_SUBTYPE }, -- { .compatible = "qcom,pm660l", .data = (void *)PM660L_SUBTYPE }, -- { .compatible = "qcom,pm660", .data = (void *)PM660_SUBTYPE }, -+ { .compatible = "qcom,spmi-pmic", .data = (void *)COMMON_SUBTYPE }, - { } - }; - diff --git a/target/linux/ipq60xx/patches-5.15/0037-v5.16-mfd-qcom-spmi-pmic-Add-missing-PMICs-supported-by-so.patch b/target/linux/ipq60xx/patches-5.15/0037-v5.16-mfd-qcom-spmi-pmic-Add-missing-PMICs-supported-by-so.patch deleted file mode 100644 index b7fa5d03a..000000000 --- a/target/linux/ipq60xx/patches-5.15/0037-v5.16-mfd-qcom-spmi-pmic-Add-missing-PMICs-supported-by-so.patch +++ /dev/null @@ -1,66 +0,0 @@ -From b4f85660d09360b2ef9f04e51890fbf9935bf759 Mon Sep 17 00:00:00 2001 -From: Bjorn Andersson -Date: Sun, 17 Oct 2021 09:12:18 -0700 -Subject: [PATCH 37/44] mfd: qcom-spmi-pmic: Add missing PMICs supported by - socinfo - -The Qualcomm socinfo driver has eight more PMICs described, add these to -the SPMI PMIC driver as well. - -Signed-off-by: Bjorn Andersson -Signed-off-by: Lee Jones -Link: https://lore.kernel.org/r/20211017161218.2378176-4-bjorn.andersson@linaro.org ---- - drivers/mfd/qcom-spmi-pmic.c | 17 +++++++++++++++++ - 1 file changed, 17 insertions(+) - ---- a/drivers/mfd/qcom-spmi-pmic.c -+++ b/drivers/mfd/qcom-spmi-pmic.c -@@ -31,6 +31,8 @@ - #define PM8916_SUBTYPE 0x0b - #define PM8004_SUBTYPE 0x0c - #define PM8909_SUBTYPE 0x0d -+#define PM8028_SUBTYPE 0x0e -+#define PM8901_SUBTYPE 0x0f - #define PM8950_SUBTYPE 0x10 - #define PMI8950_SUBTYPE 0x11 - #define PM8998_SUBTYPE 0x14 -@@ -38,6 +40,13 @@ - #define PM8005_SUBTYPE 0x18 - #define PM660L_SUBTYPE 0x1A - #define PM660_SUBTYPE 0x1B -+#define PM8150_SUBTYPE 0x1E -+#define PM8150L_SUBTYPE 0x1f -+#define PM8150B_SUBTYPE 0x20 -+#define PMK8002_SUBTYPE 0x21 -+#define PM8009_SUBTYPE 0x24 -+#define PM8150C_SUBTYPE 0x26 -+#define SMB2351_SUBTYPE 0x29 - - static const struct of_device_id pmic_spmi_id_table[] = { - { .compatible = "qcom,pm660", .data = (void *)PM660_SUBTYPE }, -@@ -45,9 +54,15 @@ static const struct of_device_id pmic_sp - { .compatible = "qcom,pm8004", .data = (void *)PM8004_SUBTYPE }, - { .compatible = "qcom,pm8005", .data = (void *)PM8005_SUBTYPE }, - { .compatible = "qcom,pm8019", .data = (void *)PM8019_SUBTYPE }, -+ { .compatible = "qcom,pm8028", .data = (void *)PM8028_SUBTYPE }, - { .compatible = "qcom,pm8110", .data = (void *)PM8110_SUBTYPE }, -+ { .compatible = "qcom,pm8150", .data = (void *)PM8150_SUBTYPE }, -+ { .compatible = "qcom,pm8150b", .data = (void *)PM8150B_SUBTYPE }, -+ { .compatible = "qcom,pm8150c", .data = (void *)PM8150C_SUBTYPE }, -+ { .compatible = "qcom,pm8150l", .data = (void *)PM8150L_SUBTYPE }, - { .compatible = "qcom,pm8226", .data = (void *)PM8226_SUBTYPE }, - { .compatible = "qcom,pm8841", .data = (void *)PM8841_SUBTYPE }, -+ { .compatible = "qcom,pm8901", .data = (void *)PM8901_SUBTYPE }, - { .compatible = "qcom,pm8909", .data = (void *)PM8909_SUBTYPE }, - { .compatible = "qcom,pm8916", .data = (void *)PM8916_SUBTYPE }, - { .compatible = "qcom,pm8941", .data = (void *)PM8941_SUBTYPE }, -@@ -60,6 +75,8 @@ static const struct of_device_id pmic_sp - { .compatible = "qcom,pmi8962", .data = (void *)PMI8962_SUBTYPE }, - { .compatible = "qcom,pmi8994", .data = (void *)PMI8994_SUBTYPE }, - { .compatible = "qcom,pmi8998", .data = (void *)PMI8998_SUBTYPE }, -+ { .compatible = "qcom,pmk8002", .data = (void *)PMK8002_SUBTYPE }, -+ { .compatible = "qcom,smb2351", .data = (void *)SMB2351_SUBTYPE }, - { .compatible = "qcom,spmi-pmic", .data = (void *)COMMON_SUBTYPE }, - { } - }; diff --git a/target/linux/ipq60xx/patches-5.15/0038-v6.0-iio-adc-qcom-spmi-adc5-add-ADC5_VREF_VADC-to-rev2-AD.patch b/target/linux/ipq60xx/patches-5.15/0038-v6.0-iio-adc-qcom-spmi-adc5-add-ADC5_VREF_VADC-to-rev2-AD.patch deleted file mode 100644 index a619a291f..000000000 --- a/target/linux/ipq60xx/patches-5.15/0038-v6.0-iio-adc-qcom-spmi-adc5-add-ADC5_VREF_VADC-to-rev2-AD.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 1aa9a70ca9a1d3bb5139030fd9fc340d8525a7d7 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Fri, 19 Aug 2022 00:18:13 +0200 -Subject: [PATCH 38/44] iio: adc: qcom-spmi-adc5: add ADC5_VREF_VADC to rev2 - ADC5 - -Add support for ADC5_VREF_VADC channel to rev2 ADC5 channel list. -This channel measures the VADC reference LDO output. - -Signed-off-by: Robert Marko -Link: https://lore.kernel.org/r/20220818221815.346233-3-robimarko@gmail.com -Signed-off-by: Jonathan Cameron ---- - drivers/iio/adc/qcom-spmi-adc5.c | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/drivers/iio/adc/qcom-spmi-adc5.c -+++ b/drivers/iio/adc/qcom-spmi-adc5.c -@@ -589,6 +589,8 @@ static const struct adc5_channels adc5_c - SCALE_HW_CALIB_DEFAULT) - [ADC5_1P25VREF] = ADC5_CHAN_VOLT("vref_1p25", 0, - SCALE_HW_CALIB_DEFAULT) -+ [ADC5_VREF_VADC] = ADC5_CHAN_VOLT("vref_vadc", 0, -+ SCALE_HW_CALIB_DEFAULT) - [ADC5_VPH_PWR] = ADC5_CHAN_VOLT("vph_pwr", 1, - SCALE_HW_CALIB_DEFAULT) - [ADC5_VBAT_SNS] = ADC5_CHAN_VOLT("vbat_sns", 1, diff --git a/target/linux/ipq60xx/patches-5.15/0039-v6.0-phy-qcom-qmp-pcie-make-pipe-clock-rate-configurable.patch b/target/linux/ipq60xx/patches-5.15/0039-v6.0-phy-qcom-qmp-pcie-make-pipe-clock-rate-configurable.patch deleted file mode 100644 index 12573c7b1..000000000 --- a/target/linux/ipq60xx/patches-5.15/0039-v6.0-phy-qcom-qmp-pcie-make-pipe-clock-rate-configurable.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 8454872e52992108308e44aa974b441558fa1fc9 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Tue, 23 Aug 2022 22:43:51 +0200 -Subject: [PATCH 39/44] phy: qcom-qmp-pcie: make pipe clock rate configurable - -IPQ8074 Gen3 PCIe PHY uses 250MHz as the pipe clock rate instead of 125MHz -like every other PCIe QMP PHY does, so make it configurable as part of the -qmp_phy_cfg. - -Signed-off-by: Robert Marko -Reviewed-by: Dmitry Baryshkov -Link: https://lore.kernel.org/r/20220621195512.1760362-1-robimarko@gmail.com -Signed-off-by: Vinod Koul ---- - drivers/phy/qualcomm/phy-qcom-qmp.c | 14 ++++++++++++-- - 1 file changed, 12 insertions(+), 2 deletions(-) - ---- a/drivers/phy/qualcomm/phy-qcom-qmp.c -+++ b/drivers/phy/qualcomm/phy-qcom-qmp.c -@@ -2842,6 +2842,9 @@ struct qmp_phy_cfg { - /* true, if PHY has secondary tx/rx lanes to be configured */ - bool is_dual_lane_phy; - -+ /* QMP PHY pipe clock interface rate */ -+ unsigned long pipe_clock_rate; -+ - /* true, if PCS block has no separate SW_RESET register */ - bool no_pcs_sw_reset; - }; -@@ -5139,8 +5142,15 @@ static int phy_pipe_clk_register(struct - - init.ops = &clk_fixed_rate_ops; - -- /* controllers using QMP phys use 125MHz pipe clock interface */ -- fixed->fixed_rate = 125000000; -+ /* -+ * Controllers using QMP PHY-s use 125MHz pipe clock interface -+ * unless other frequency is specified in the PHY config. -+ */ -+ if (qmp->phys[0]->cfg->pipe_clock_rate) -+ fixed->fixed_rate = qmp->phys[0]->cfg->pipe_clock_rate; -+ else -+ fixed->fixed_rate = 125000000; -+ - fixed->hw.init = &init; - - ret = devm_clk_hw_register(qmp->dev, &fixed->hw); diff --git a/target/linux/ipq60xx/patches-5.15/0040-v6.0-phy-qcom-qmp-pcie-add-IPQ8074-PCIe-Gen3-QMP-PHY-supp.patch b/target/linux/ipq60xx/patches-5.15/0040-v6.0-phy-qcom-qmp-pcie-add-IPQ8074-PCIe-Gen3-QMP-PHY-supp.patch deleted file mode 100644 index 80c872738..000000000 --- a/target/linux/ipq60xx/patches-5.15/0040-v6.0-phy-qcom-qmp-pcie-add-IPQ8074-PCIe-Gen3-QMP-PHY-supp.patch +++ /dev/null @@ -1,201 +0,0 @@ -From 6702bed8d48e29bd51c4b702b0baf18c5b1814c1 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Tue, 23 Aug 2022 22:47:40 +0200 -Subject: [PATCH 40/44] phy: qcom-qmp-pcie: add IPQ8074 PCIe Gen3 QMP PHY - support - -IPQ8074 has 2 different single lane PCIe PHY-s, one Gen2 and one Gen3. -Gen2 one is already supported, so add the support for the Gen3 one. -It uses the same register layout as IPQ6018. - -Signed-off-by: Robert Marko -Reviewed-by: Dmitry Baryshkov -Link: https://lore.kernel.org/r/20220621195512.1760362-3-robimarko@gmail.com -Signed-off-by: Vinod Koul ---- - drivers/phy/qualcomm/phy-qcom-qmp.c | 160 ++++++++++++++++++++++++++++ - 1 file changed, 160 insertions(+) - ---- a/drivers/phy/qualcomm/phy-qcom-qmp.c -+++ b/drivers/phy/qualcomm/phy-qcom-qmp.c -@@ -812,6 +812,133 @@ static const struct qmp_phy_init_tbl ipq - QMP_PHY_INIT_CFG_L(QPHY_START_CTRL, 0x3), - }; - -+static const struct qmp_phy_init_tbl ipq8074_pcie_gen3_serdes_tbl[] = { -+ QMP_PHY_INIT_CFG(QSERDES_PLL_BIAS_EN_CLKBUFLR_EN, 0x18), -+ QMP_PHY_INIT_CFG(QSERDES_PLL_BIAS_EN_CTRL_BY_PSM, 0x01), -+ QMP_PHY_INIT_CFG(QSERDES_PLL_CLK_SELECT, 0x31), -+ QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_IVCO, 0x0f), -+ QMP_PHY_INIT_CFG(QSERDES_PLL_BG_TRIM, 0x0f), -+ QMP_PHY_INIT_CFG(QSERDES_PLL_CMN_CONFIG, 0x06), -+ QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP_EN, 0x42), -+ QMP_PHY_INIT_CFG(QSERDES_PLL_RESETSM_CNTRL, 0x20), -+ QMP_PHY_INIT_CFG(QSERDES_PLL_SVS_MODE_CLK_SEL, 0x01), -+ QMP_PHY_INIT_CFG(QSERDES_PLL_VCO_TUNE_MAP, 0x04), -+ QMP_PHY_INIT_CFG(QSERDES_PLL_SVS_MODE_CLK_SEL, 0x05), -+ QMP_PHY_INIT_CFG(QSERDES_PLL_VCO_TUNE_TIMER1, 0xff), -+ QMP_PHY_INIT_CFG(QSERDES_PLL_VCO_TUNE_TIMER2, 0x3f), -+ QMP_PHY_INIT_CFG(QSERDES_PLL_CORE_CLK_EN, 0x30), -+ QMP_PHY_INIT_CFG(QSERDES_PLL_HSCLK_SEL, 0x21), -+ QMP_PHY_INIT_CFG(QSERDES_PLL_DEC_START_MODE0, 0x82), -+ QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START3_MODE0, 0x03), -+ QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START2_MODE0, 0x355), -+ QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START1_MODE0, 0x35555), -+ QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP2_MODE0, 0x1a), -+ QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP1_MODE0, 0x1a0a), -+ QMP_PHY_INIT_CFG(QSERDES_PLL_CP_CTRL_MODE0, 0xb), -+ QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_RCTRL_MODE0, 0x16), -+ QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_CCTRL_MODE0, 0x28), -+ QMP_PHY_INIT_CFG(QSERDES_PLL_INTEGLOOP_GAIN1_MODE0, 0x0), -+ QMP_PHY_INIT_CFG(QSERDES_PLL_INTEGLOOP_GAIN0_MODE0, 0x40), -+ QMP_PHY_INIT_CFG(QSERDES_PLL_VCO_TUNE2_MODE0, 0x02), -+ QMP_PHY_INIT_CFG(QSERDES_PLL_VCO_TUNE1_MODE0, 0x24), -+ QMP_PHY_INIT_CFG(QSERDES_PLL_SVS_MODE_CLK_SEL, 0x05), -+ QMP_PHY_INIT_CFG(QSERDES_PLL_CORE_CLK_EN, 0x20), -+ QMP_PHY_INIT_CFG(QSERDES_PLL_CORECLK_DIV, 0xa), -+ QMP_PHY_INIT_CFG(QSERDES_PLL_CLK_SELECT, 0x32), -+ QMP_PHY_INIT_CFG(QSERDES_PLL_SYS_CLK_CTRL, 0x02), -+ QMP_PHY_INIT_CFG(QSERDES_PLL_SYSCLK_BUF_ENABLE, 0x07), -+ QMP_PHY_INIT_CFG(QSERDES_PLL_SYSCLK_EN_SEL, 0x08), -+ QMP_PHY_INIT_CFG(QSERDES_PLL_BG_TIMER, 0xa), -+ QMP_PHY_INIT_CFG(QSERDES_PLL_HSCLK_SEL, 0x1), -+ QMP_PHY_INIT_CFG(QSERDES_PLL_DEC_START_MODE1, 0x68), -+ QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START3_MODE1, 0x2), -+ QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START2_MODE1, 0x2aa), -+ QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START1_MODE1, 0x2aaab), -+ QMP_PHY_INIT_CFG(QSERDES_PLL_CLK_ENABLE1, 0x90), -+ QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP2_MODE1, 0x34), -+ QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP1_MODE1, 0x3414), -+ QMP_PHY_INIT_CFG(QSERDES_PLL_CP_CTRL_MODE1, 0x0b), -+ QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_RCTRL_MODE1, 0x16), -+ QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_CCTRL_MODE1, 0x28), -+ QMP_PHY_INIT_CFG(QSERDES_PLL_INTEGLOOP_GAIN1_MODE1, 0x0), -+ QMP_PHY_INIT_CFG(QSERDES_PLL_INTEGLOOP_GAIN0_MODE1, 0x40), -+ QMP_PHY_INIT_CFG(QSERDES_PLL_VCO_TUNE2_MODE1, 0x03), -+ QMP_PHY_INIT_CFG(QSERDES_PLL_VCO_TUNE1_MODE1, 0xb4), -+ QMP_PHY_INIT_CFG(QSERDES_PLL_SVS_MODE_CLK_SEL, 0x05), -+ QMP_PHY_INIT_CFG(QSERDES_PLL_CORE_CLK_EN, 0x0), -+ QMP_PHY_INIT_CFG(QSERDES_PLL_CORECLK_DIV_MODE1, 0x08), -+ QMP_PHY_INIT_CFG(QSERDES_PLL_CLK_EP_DIV_MODE0, 0x19), -+ QMP_PHY_INIT_CFG(QSERDES_PLL_CLK_EP_DIV_MODE1, 0x28), -+ QMP_PHY_INIT_CFG(QSERDES_PLL_CLK_ENABLE1, 0x90), -+}; -+ -+static const struct qmp_phy_init_tbl ipq8074_pcie_gen3_tx_tbl[] = { -+ QMP_PHY_INIT_CFG(QSERDES_TX0_RES_CODE_LANE_OFFSET_TX, 0x02), -+ QMP_PHY_INIT_CFG(QSERDES_TX0_RCV_DETECT_LVL_2, 0x12), -+ QMP_PHY_INIT_CFG(QSERDES_TX0_HIGHZ_DRVR_EN, 0x10), -+ QMP_PHY_INIT_CFG(QSERDES_TX0_LANE_MODE_1, 0x06), -+}; -+ -+static const struct qmp_phy_init_tbl ipq8074_pcie_gen3_rx_tbl[] = { -+ QMP_PHY_INIT_CFG(QSERDES_RX0_SIGDET_CNTRL, 0x03), -+ QMP_PHY_INIT_CFG(QSERDES_RX0_SIGDET_ENABLES, 0x1c), -+ QMP_PHY_INIT_CFG(QSERDES_RX0_SIGDET_DEGLITCH_CNTRL, 0x14), -+ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_EQU_ADAPTOR_CNTRL2, 0xe), -+ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_EQU_ADAPTOR_CNTRL3, 0x4), -+ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_EQU_ADAPTOR_CNTRL4, 0x1b), -+ QMP_PHY_INIT_CFG(QSERDES_RX0_DFE_EN_TIMER, 0x04), -+ QMP_PHY_INIT_CFG(QSERDES_RX0_UCDR_SO_SATURATION_AND_ENABLE, 0x7f), -+ QMP_PHY_INIT_CFG(QSERDES_RX0_UCDR_PI_CONTROLS, 0x70), -+ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x73), -+ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), -+ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_10_LOW, 0x00), -+ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_10_HIGH, 0x02), -+ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_10_HIGH2, 0xc8), -+ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_10_HIGH3, 0x09), -+ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_10_HIGH4, 0xb1), -+ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_01_LOW, 0x01), -+ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_01_HIGH, 0x02), -+ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_01_HIGH2, 0xc8), -+ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_01_HIGH3, 0x09), -+ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_01_HIGH4, 0xb1), -+ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_00_LOW, 0xf0), -+ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_00_HIGH, 0x2), -+ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_00_HIGH2, 0x2f), -+ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_00_HIGH3, 0xd3), -+ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_00_HIGH4, 0x40), -+ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_IDAC_TSETTLE_HIGH, 0x00), -+ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_IDAC_TSETTLE_LOW, 0xc0), -+ QMP_PHY_INIT_CFG(QSERDES_RX0_UCDR_FO_GAIN, 0x0c), -+ QMP_PHY_INIT_CFG(QSERDES_RX0_UCDR_SO_GAIN, 0x02), -+}; -+ -+static const struct qmp_phy_init_tbl ipq8074_pcie_gen3_pcs_tbl[] = { -+ QMP_PHY_INIT_CFG(PCS_COM_FLL_CNTRL2, 0x83), -+ QMP_PHY_INIT_CFG(PCS_COM_FLL_CNT_VAL_L, 0x9), -+ QMP_PHY_INIT_CFG(PCS_COM_FLL_CNT_VAL_H_TOL, 0x42), -+ QMP_PHY_INIT_CFG(PCS_COM_FLL_MAN_CODE, 0x40), -+ QMP_PHY_INIT_CFG(PCS_COM_FLL_CNTRL1, 0x01), -+ QMP_PHY_INIT_CFG(PCS_COM_P2U3_WAKEUP_DLY_TIME_AUXCLK_H, 0x0), -+ QMP_PHY_INIT_CFG(PCS_COM_P2U3_WAKEUP_DLY_TIME_AUXCLK_L, 0x1), -+ QMP_PHY_INIT_CFG(PCS_PCIE_OSC_DTCT_ACTIONS, 0x0), -+ QMP_PHY_INIT_CFG(PCS_PCIE_L1P1_WAKEUP_DLY_TIME_AUXCLK_H, 0x00), -+ QMP_PHY_INIT_CFG(PCS_PCIE_L1P1_WAKEUP_DLY_TIME_AUXCLK_L, 0x01), -+ QMP_PHY_INIT_CFG(PCS_PCIE_L1P2_WAKEUP_DLY_TIME_AUXCLK_H, 0x00), -+ QMP_PHY_INIT_CFG(PCS_PCIE_L1P2_WAKEUP_DLY_TIME_AUXCLK_L, 0x01), -+ QMP_PHY_INIT_CFG(PCS_PCIE_EQ_CONFIG1, 0x11), -+ QMP_PHY_INIT_CFG(PCS_PCIE_EQ_CONFIG2, 0xb), -+ QMP_PHY_INIT_CFG(PCS_PCIE_POWER_STATE_CONFIG4, 0x07), -+ QMP_PHY_INIT_CFG(PCS_PCIE_OSC_DTCT_CONFIG2, 0x52), -+ QMP_PHY_INIT_CFG(PCS_PCIE_OSC_DTCT_MODE2_CONFIG2, 0x50), -+ QMP_PHY_INIT_CFG(PCS_PCIE_OSC_DTCT_MODE2_CONFIG4, 0x1a), -+ QMP_PHY_INIT_CFG(PCS_PCIE_OSC_DTCT_MODE2_CONFIG5, 0x6), -+ QMP_PHY_INIT_CFG(PCS_COM_G12S1_TXDEEMPH_M3P5DB, 0x10), -+ QMP_PHY_INIT_CFG(PCS_PCIE_ENDPOINT_REFCLK_DRIVE, 0xc1), -+ QMP_PHY_INIT_CFG(PCS_COM_RX_DCC_CAL_CONFIG, 0x01), -+ QMP_PHY_INIT_CFG(PCS_COM_RX_SIGDET_LVL, 0xaa), -+ QMP_PHY_INIT_CFG(PCS_COM_REFGEN_REQ_CONFIG1, 0x0d), -+}; -+ - static const struct qmp_phy_init_tbl sdm845_qmp_pcie_serdes_tbl[] = { - QMP_PHY_INIT_CFG(QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN, 0x14), - QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x30), -@@ -3168,6 +3295,36 @@ static const struct qmp_phy_cfg ipq8074_ - .pwrdn_delay_max = 1005, /* us */ - }; - -+static const struct qmp_phy_cfg ipq8074_pciephy_gen3_cfg = { -+ .type = PHY_TYPE_PCIE, -+ .nlanes = 1, -+ -+ .serdes_tbl = ipq8074_pcie_gen3_serdes_tbl, -+ .serdes_tbl_num = ARRAY_SIZE(ipq8074_pcie_gen3_serdes_tbl), -+ .tx_tbl = ipq8074_pcie_gen3_tx_tbl, -+ .tx_tbl_num = ARRAY_SIZE(ipq8074_pcie_gen3_tx_tbl), -+ .rx_tbl = ipq8074_pcie_gen3_rx_tbl, -+ .rx_tbl_num = ARRAY_SIZE(ipq8074_pcie_gen3_rx_tbl), -+ .pcs_tbl = ipq8074_pcie_gen3_pcs_tbl, -+ .pcs_tbl_num = ARRAY_SIZE(ipq8074_pcie_gen3_pcs_tbl), -+ .clk_list = ipq8074_pciephy_clk_l, -+ .num_clks = ARRAY_SIZE(ipq8074_pciephy_clk_l), -+ .reset_list = ipq8074_pciephy_reset_l, -+ .num_resets = ARRAY_SIZE(ipq8074_pciephy_reset_l), -+ .vreg_list = NULL, -+ .num_vregs = 0, -+ .regs = ipq_pciephy_gen3_regs_layout, -+ -+ .start_ctrl = SERDES_START | PCS_START, -+ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, -+ -+ .has_pwrdn_delay = true, -+ .pwrdn_delay_min = 995, /* us */ -+ .pwrdn_delay_max = 1005, /* us */ -+ -+ .pipe_clock_rate = 250000000, -+}; -+ - static const struct qmp_phy_cfg ipq6018_pciephy_cfg = { - .type = PHY_TYPE_PCIE, - .nlanes = 1, -@@ -5571,6 +5728,9 @@ static const struct of_device_id qcom_qm - .compatible = "qcom,ipq8074-qmp-pcie-phy", - .data = &ipq8074_pciephy_cfg, - }, { -+ .compatible = "qcom,ipq8074-qmp-gen3-pcie-phy", -+ .data = &ipq8074_pciephy_gen3_cfg, -+ }, { - .compatible = "qcom,ipq6018-qmp-pcie-phy", - .data = &ipq6018_pciephy_cfg, - }, { diff --git a/target/linux/ipq60xx/patches-5.15/0041-v5.16-soc-qcom-socinfo-Add-IPQ8074-family-ID-s.patch b/target/linux/ipq60xx/patches-5.15/0041-v5.16-soc-qcom-socinfo-Add-IPQ8074-family-ID-s.patch deleted file mode 100644 index 085fab079..000000000 --- a/target/linux/ipq60xx/patches-5.15/0041-v5.16-soc-qcom-socinfo-Add-IPQ8074-family-ID-s.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 70835efbc6c9dbc4e652aa60a250ecb1a2160a9b Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Sun, 5 Sep 2021 19:11:31 +0200 -Subject: [PATCH 41/44] soc: qcom: socinfo: Add IPQ8074 family ID-s - -IPQ8074 family SoC ID-s are missing, so lets add them based on -the downstream driver. - -Signed-off-by: Robert Marko -Reviewed-by: Kathiravan T -Signed-off-by: Bjorn Andersson -Link: https://lore.kernel.org/r/20210905171131.660885-1-robimarko@gmail.com ---- - drivers/soc/qcom/socinfo.c | 12 ++++++++++++ - 1 file changed, 12 insertions(+) - ---- a/drivers/soc/qcom/socinfo.c -+++ b/drivers/soc/qcom/socinfo.c -@@ -281,19 +281,31 @@ static const struct soc_id soc_id[] = { - { 319, "APQ8098" }, - { 321, "SDM845" }, - { 322, "MDM9206" }, -+ { 323, "IPQ8074" }, - { 324, "SDA660" }, - { 325, "SDM658" }, - { 326, "SDA658" }, - { 327, "SDA630" }, - { 338, "SDM450" }, - { 341, "SDA845" }, -+ { 342, "IPQ8072" }, -+ { 343, "IPQ8076" }, -+ { 344, "IPQ8078" }, - { 345, "SDM636" }, - { 346, "SDA636" }, - { 349, "SDM632" }, - { 350, "SDA632" }, - { 351, "SDA450" }, - { 356, "SM8250" }, -+ { 375, "IPQ8070" }, -+ { 376, "IPQ8071" }, -+ { 389, "IPQ8072A" }, -+ { 390, "IPQ8074A" }, -+ { 391, "IPQ8076A" }, -+ { 392, "IPQ8078A" }, - { 394, "SM6125" }, -+ { 395, "IPQ8070A" }, -+ { 396, "IPQ8071A" }, - { 402, "IPQ6018" }, - { 403, "IPQ6028" }, - { 421, "IPQ6000" }, diff --git a/target/linux/ipq60xx/patches-5.15/0042-v6.0-PCI-dwc-tegra-move-GEN3_RELATED-DBI-register-to-comm.patch b/target/linux/ipq60xx/patches-5.15/0042-v6.0-PCI-dwc-tegra-move-GEN3_RELATED-DBI-register-to-comm.patch deleted file mode 100644 index ad9b6fc98..000000000 --- a/target/linux/ipq60xx/patches-5.15/0042-v6.0-PCI-dwc-tegra-move-GEN3_RELATED-DBI-register-to-comm.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 66dafdaad281e0a0eb2045ffb1f8dcf72e25989f Mon Sep 17 00:00:00 2001 -From: Baruch Siach -Date: Mon, 7 Feb 2022 16:51:24 +0200 -Subject: [PATCH 42/44] PCI: dwc: tegra: move GEN3_RELATED DBI register to - common header - -These are common dwc macros that will be used for other platforms. - -Reviewed-by: Rob Herring -Signed-off-by: Baruch Siach ---- - drivers/pci/controller/dwc/pcie-designware.h | 6 ++++++ - drivers/pci/controller/dwc/pcie-tegra194.c | 6 ------ - 2 files changed, 6 insertions(+), 6 deletions(-) - ---- a/drivers/pci/controller/dwc/pcie-designware.h -+++ b/drivers/pci/controller/dwc/pcie-designware.h -@@ -74,6 +74,12 @@ - #define PCIE_MSI_INTR0_MASK 0x82C - #define PCIE_MSI_INTR0_STATUS 0x830 - -+#define GEN3_RELATED_OFF 0x890 -+#define GEN3_RELATED_OFF_GEN3_ZRXDC_NONCOMPL BIT(0) -+#define GEN3_RELATED_OFF_GEN3_EQ_DISABLE BIT(16) -+#define GEN3_RELATED_OFF_RATE_SHADOW_SEL_SHIFT 24 -+#define GEN3_RELATED_OFF_RATE_SHADOW_SEL_MASK GENMASK(25, 24) -+ - #define PCIE_PORT_MULTI_LANE_CTRL 0x8C0 - #define PORT_MLTI_UPCFG_SUPPORT BIT(7) - ---- a/drivers/pci/controller/dwc/pcie-tegra194.c -+++ b/drivers/pci/controller/dwc/pcie-tegra194.c -@@ -194,12 +194,6 @@ - #define GEN3_EQ_CONTROL_OFF_PSET_REQ_VEC_MASK GENMASK(23, 8) - #define GEN3_EQ_CONTROL_OFF_FB_MODE_MASK GENMASK(3, 0) - --#define GEN3_RELATED_OFF 0x890 --#define GEN3_RELATED_OFF_GEN3_ZRXDC_NONCOMPL BIT(0) --#define GEN3_RELATED_OFF_GEN3_EQ_DISABLE BIT(16) --#define GEN3_RELATED_OFF_RATE_SHADOW_SEL_SHIFT 24 --#define GEN3_RELATED_OFF_RATE_SHADOW_SEL_MASK GENMASK(25, 24) -- - #define PORT_LOGIC_AMBA_ERROR_RESPONSE_DEFAULT 0x8D0 - #define AMBA_ERROR_RESPONSE_CRS_SHIFT 3 - #define AMBA_ERROR_RESPONSE_CRS_MASK GENMASK(1, 0) diff --git a/target/linux/ipq60xx/patches-5.15/0043-v6.0-PCI-qcom-Define-slot-capabilities-using-PCI_EXP_SLTC.patch b/target/linux/ipq60xx/patches-5.15/0043-v6.0-PCI-qcom-Define-slot-capabilities-using-PCI_EXP_SLTC.patch deleted file mode 100644 index d84839f2b..000000000 --- a/target/linux/ipq60xx/patches-5.15/0043-v6.0-PCI-qcom-Define-slot-capabilities-using-PCI_EXP_SLTC.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 55299da8c17f23249497ee8868a5a268c6e3fbcc Mon Sep 17 00:00:00 2001 -From: Baruch Siach -Date: Mon, 7 Feb 2022 16:51:25 +0200 -Subject: [PATCH 43/44] PCI: qcom: Define slot capabilities using - PCI_EXP_SLTCAP_* - -The PCIE_CAP_LINK1_VAL macro actually defines slot capabilities. Use -PCI_EXP_SLTCAP_* macros to spell its value, and rename it to better -describe its meaning. - -Signed-off-by: Baruch Siach ---- - drivers/pci/controller/dwc/pcie-qcom.c | 15 +++++++++++++-- - 1 file changed, 13 insertions(+), 2 deletions(-) - ---- a/drivers/pci/controller/dwc/pcie-qcom.c -+++ b/drivers/pci/controller/dwc/pcie-qcom.c -@@ -69,7 +69,18 @@ - #define PCIE20_AXI_MSTR_RESP_COMP_CTRL1 0x81c - #define CFG_BRIDGE_SB_INIT BIT(0) - --#define PCIE_CAP_LINK1_VAL 0x2FD7F -+#define PCIE_CAP_SLOT_POWER_LIMIT_VAL 0x7D00 -+#define PCIE_CAP_SLOT_POWER_LIMIT_SCALE 0x8000 -+#define PCIE_CAP_SLOT_VAL (PCI_EXP_SLTCAP_ABP | \ -+ PCI_EXP_SLTCAP_PCP | \ -+ PCI_EXP_SLTCAP_MRLSP | \ -+ PCI_EXP_SLTCAP_AIP | \ -+ PCI_EXP_SLTCAP_PIP | \ -+ PCI_EXP_SLTCAP_HPS | \ -+ PCI_EXP_SLTCAP_HPC | \ -+ PCI_EXP_SLTCAP_EIP | \ -+ PCIE_CAP_SLOT_POWER_LIMIT_VAL | \ -+ PCIE_CAP_SLOT_POWER_LIMIT_SCALE) - - #define PCIE20_PARF_Q2A_FLUSH 0x1AC - -@@ -1125,7 +1136,7 @@ static int qcom_pcie_post_init_2_3_3(str - - writel(PCI_COMMAND_MASTER, pci->dbi_base + PCI_COMMAND); - writel(DBI_RO_WR_EN, pci->dbi_base + PCIE20_MISC_CONTROL_1_REG); -- writel(PCIE_CAP_LINK1_VAL, pci->dbi_base + offset + PCI_EXP_SLTCAP); -+ writel(PCIE_CAP_SLOT_VAL, pci->dbi_base + offset + PCI_EXP_SLTCAP); - - val = readl(pci->dbi_base + offset + PCI_EXP_LNKCAP); - val &= ~PCI_EXP_LNKCAP_ASPMS; diff --git a/target/linux/ipq60xx/patches-5.15/0044-v6.0-PCI-qcom-Add-IPQ60xx-support.patch b/target/linux/ipq60xx/patches-5.15/0044-v6.0-PCI-qcom-Add-IPQ60xx-support.patch deleted file mode 100644 index 93bec2f04..000000000 --- a/target/linux/ipq60xx/patches-5.15/0044-v6.0-PCI-qcom-Add-IPQ60xx-support.patch +++ /dev/null @@ -1,212 +0,0 @@ -From b9d02fcefdf166671356a08dd621429e63541b22 Mon Sep 17 00:00:00 2001 -From: Selvam Sathappan Periakaruppan -Date: Thu, 10 Feb 2022 18:02:47 +0100 -Subject: [PATCH 44/44] PCI: qcom: Add IPQ60xx support - -IPQ60xx series of SoCs have one port of PCIe gen 3. Add support for that -platform. - -The code is based on downstream[1] Codeaurora kernel v5.4 (branch -win.linuxopenwrt.2.0). - -Split out the DBI registers access part from .init into .post_init. DBI -registers are only accessible after phy_power_on(). - -[1] https://source.codeaurora.org/quic/qsdk/oss/kernel/linux-ipq-5.4/ - -Signed-off-by: Selvam Sathappan Periakaruppan -Signed-off-by: Baruch Siach ---- - drivers/pci/controller/dwc/pcie-designware.h | 1 + - drivers/pci/controller/dwc/pcie-qcom.c | 135 +++++++++++++++++++ - 2 files changed, 136 insertions(+) - ---- a/drivers/pci/controller/dwc/pcie-designware.h -+++ b/drivers/pci/controller/dwc/pcie-designware.h -@@ -76,6 +76,7 @@ - - #define GEN3_RELATED_OFF 0x890 - #define GEN3_RELATED_OFF_GEN3_ZRXDC_NONCOMPL BIT(0) -+#define GEN3_RELATED_OFF_RXEQ_RGRDLESS_RXTS BIT(13) - #define GEN3_RELATED_OFF_GEN3_EQ_DISABLE BIT(16) - #define GEN3_RELATED_OFF_RATE_SHADOW_SEL_SHIFT 24 - #define GEN3_RELATED_OFF_RATE_SHADOW_SEL_MASK GENMASK(25, 24) ---- a/drivers/pci/controller/dwc/pcie-qcom.c -+++ b/drivers/pci/controller/dwc/pcie-qcom.c -@@ -52,6 +52,10 @@ - #define PCIE20_PARF_DBI_BASE_ADDR 0x168 - #define PCIE20_PARF_SLV_ADDR_SPACE_SIZE 0x16C - #define PCIE20_PARF_MHI_CLOCK_RESET_CTRL 0x174 -+#define AHB_CLK_EN BIT(0) -+#define MSTR_AXI_CLK_EN BIT(1) -+#define BYPASS BIT(4) -+ - #define PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT 0x178 - #define PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT_V2 0x1A8 - #define PCIE20_PARF_LTSSM 0x1B0 -@@ -179,6 +183,11 @@ struct qcom_pcie_resources_2_7_0 { - struct clk *pipe_clk; - }; - -+struct qcom_pcie_resources_2_9_0 { -+ struct clk_bulk_data clks[5]; -+ struct reset_control *rst; -+}; -+ - union qcom_pcie_resources { - struct qcom_pcie_resources_1_0_0 v1_0_0; - struct qcom_pcie_resources_2_1_0 v2_1_0; -@@ -186,6 +195,7 @@ union qcom_pcie_resources { - struct qcom_pcie_resources_2_3_3 v2_3_3; - struct qcom_pcie_resources_2_4_0 v2_4_0; - struct qcom_pcie_resources_2_7_0 v2_7_0; -+ struct qcom_pcie_resources_2_9_0 v2_9_0; - }; - - struct qcom_pcie; -@@ -1276,6 +1286,121 @@ static void qcom_pcie_post_deinit_2_7_0( - clk_disable_unprepare(res->pipe_clk); - } - -+static int qcom_pcie_get_resources_2_9_0(struct qcom_pcie *pcie) -+{ -+ struct qcom_pcie_resources_2_9_0 *res = &pcie->res.v2_9_0; -+ struct dw_pcie *pci = pcie->pci; -+ struct device *dev = pci->dev; -+ int ret; -+ -+ res->clks[0].id = "iface"; -+ res->clks[1].id = "axi_m"; -+ res->clks[2].id = "axi_s"; -+ res->clks[3].id = "axi_bridge"; -+ res->clks[4].id = "rchng"; -+ -+ ret = devm_clk_bulk_get(dev, ARRAY_SIZE(res->clks), res->clks); -+ if (ret < 0) -+ return ret; -+ -+ res->rst = devm_reset_control_array_get_exclusive(dev); -+ if (IS_ERR(res->rst)) -+ return PTR_ERR(res->rst); -+ -+ return 0; -+} -+ -+static void qcom_pcie_deinit_2_9_0(struct qcom_pcie *pcie) -+{ -+ struct qcom_pcie_resources_2_9_0 *res = &pcie->res.v2_9_0; -+ -+ clk_bulk_disable_unprepare(ARRAY_SIZE(res->clks), res->clks); -+} -+ -+static int qcom_pcie_init_2_9_0(struct qcom_pcie *pcie) -+{ -+ struct qcom_pcie_resources_2_9_0 *res = &pcie->res.v2_9_0; -+ struct device *dev = pcie->pci->dev; -+ int ret; -+ -+ ret = reset_control_assert(res->rst); -+ if (ret) { -+ dev_err(dev, "reset assert failed (%d)\n", ret); -+ return ret; -+ } -+ -+ /* -+ * Delay periods before and after reset deassert are working values -+ * from downstream Codeaurora kernel -+ */ -+ usleep_range(2000, 2500); -+ -+ ret = reset_control_deassert(res->rst); -+ if (ret) { -+ dev_err(dev, "reset deassert failed (%d)\n", ret); -+ return ret; -+ } -+ -+ usleep_range(2000, 2500); -+ -+ ret = clk_bulk_prepare_enable(ARRAY_SIZE(res->clks), res->clks); -+ if (ret) -+ goto err_reset; -+ -+ return 0; -+ -+err_reset: -+ reset_control_assert(res->rst); -+ -+ return ret; -+} -+ -+static int qcom_pcie_post_init_2_9_0(struct qcom_pcie *pcie) -+{ -+ struct dw_pcie *pci = pcie->pci; -+ u16 offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP); -+ u32 val; -+ int i; -+ -+ writel(SLV_ADDR_SPACE_SZ, -+ pcie->parf + PCIE20_v3_PARF_SLV_ADDR_SPACE_SIZE); -+ -+ val = readl(pcie->parf + PCIE20_PARF_PHY_CTRL); -+ val &= ~BIT(0); -+ writel(val, pcie->parf + PCIE20_PARF_PHY_CTRL); -+ -+ writel(0, pcie->parf + PCIE20_PARF_DBI_BASE_ADDR); -+ -+ writel(DEVICE_TYPE_RC, pcie->parf + PCIE20_PARF_DEVICE_TYPE); -+ writel(BYPASS | MSTR_AXI_CLK_EN | AHB_CLK_EN, -+ pcie->parf + PCIE20_PARF_MHI_CLOCK_RESET_CTRL); -+ writel(GEN3_RELATED_OFF_RXEQ_RGRDLESS_RXTS -+ | GEN3_RELATED_OFF_GEN3_ZRXDC_NONCOMPL, -+ pci->dbi_base + GEN3_RELATED_OFF); -+ -+ writel(MST_WAKEUP_EN | SLV_WAKEUP_EN | MSTR_ACLK_CGC_DIS -+ | SLV_ACLK_CGC_DIS | CORE_CLK_CGC_DIS | -+ AUX_PWR_DET | L23_CLK_RMV_DIS | L1_CLK_RMV_DIS, -+ pcie->parf + PCIE20_PARF_SYS_CTRL); -+ -+ writel(0, pcie->parf + PCIE20_PARF_Q2A_FLUSH); -+ -+ dw_pcie_dbi_ro_wr_en(pci); -+ writel(PCIE_CAP_SLOT_VAL, pci->dbi_base + offset + PCI_EXP_SLTCAP); -+ -+ val = readl(pci->dbi_base + offset + PCI_EXP_LNKCAP); -+ val &= ~PCI_EXP_LNKCAP_ASPMS; -+ writel(val, pci->dbi_base + offset + PCI_EXP_LNKCAP); -+ -+ writel(PCI_EXP_DEVCTL2_COMP_TMOUT_DIS, pci->dbi_base + offset + -+ PCI_EXP_DEVCTL2); -+ -+ for (i = 0; i < 256; i++) -+ writel(0x0, pcie->parf + PCIE20_PARF_BDF_TO_SID_TABLE_N -+ + (4 * i)); -+ -+ return 0; -+} - static int qcom_pcie_link_up(struct dw_pcie *pci) - { - u16 offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP); -@@ -1467,6 +1592,15 @@ static const struct qcom_pcie_ops ops_1_ - .config_sid = qcom_pcie_config_sid_sm8250, - }; - -+/* Qcom IP rev.: 2.9.0 Synopsys IP rev.: 5.00a */ -+static const struct qcom_pcie_ops ops_2_9_0 = { -+ .get_resources = qcom_pcie_get_resources_2_9_0, -+ .init = qcom_pcie_init_2_9_0, -+ .post_init = qcom_pcie_post_init_2_9_0, -+ .deinit = qcom_pcie_deinit_2_9_0, -+ .ltssm_enable = qcom_pcie_2_3_2_ltssm_enable, -+}; -+ - static const struct dw_pcie_ops dw_pcie_ops = { - .link_up = qcom_pcie_link_up, - .start_link = qcom_pcie_start_link, -@@ -1565,6 +1699,7 @@ static const struct of_device_id qcom_pc - { .compatible = "qcom,pcie-qcs404", .data = &ops_2_4_0 }, - { .compatible = "qcom,pcie-sdm845", .data = &ops_2_7_0 }, - { .compatible = "qcom,pcie-sm8250", .data = &ops_1_9_0 }, -+ { .compatible = "qcom,pcie-ipq6018", .data = &ops_2_9_0 }, - { } - }; - diff --git a/target/linux/ipq60xx/patches-5.15/0100-arm64-dts-ipq8074-add-reserved-memory-nodes.patch b/target/linux/ipq60xx/patches-5.15/0100-arm64-dts-ipq8074-add-reserved-memory-nodes.patch deleted file mode 100644 index 314db03b2..000000000 --- a/target/linux/ipq60xx/patches-5.15/0100-arm64-dts-ipq8074-add-reserved-memory-nodes.patch +++ /dev/null @@ -1,70 +0,0 @@ -From 2dc8319c43ccc511a38f441ab4f7aa120af9a9fb Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Wed, 22 Dec 2021 12:23:34 +0100 -Subject: [PATCH 100/137] arm64: dts: ipq8074: add reserved memory nodes - -IPQ8074 has multiple reserved memory ranges, if they are not defined -then weird things tend to happen, board hangs and resets when PCI or -WLAN is used etc. - -So, to avoid all of that add the reserved memory nodes from the downstream -5.4 kernel from QCA. -This is their default layout meant for devices with 1GB of RAM, but -devices with lower ammounts can override the Q6 node. - -Signed-off-by: Robert Marko ---- - arch/arm64/boot/dts/qcom/ipq8074.dtsi | 35 +++++++++++++++++++++++++++ - 1 file changed, 35 insertions(+) - ---- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -85,6 +85,26 @@ - #size-cells = <2>; - ranges; - -+ nss@40000000 { -+ no-map; -+ reg = <0x0 0x40000000 0x0 0x01000000>; -+ }; -+ -+ tzapp_region: tzapp@4a400000 { -+ no-map; -+ reg = <0x0 0x4a400000 0x0 0x00200000>; -+ }; -+ -+ uboot@4a600000 { -+ no-map; -+ reg = <0x0 0x4a600000 0x0 0x00400000>; -+ }; -+ -+ sbl@4aa00000 { -+ no-map; -+ reg = <0x0 0x4aa00000 0x0 0x00100000>; -+ }; -+ - smem@4ab00000 { - compatible = "qcom,smem"; - reg = <0x0 0x4ab00000 0x0 0x00100000>; -@@ -97,6 +117,21 @@ - no-map; - reg = <0x0 0x4ac00000 0x0 0x00400000>; - }; -+ -+ q6_region: wcnss@4b000000 { -+ no-map; -+ reg = <0x0 0x4b000000 0x0 0x05f00000>; -+ }; -+ -+ q6_etr_region: q6_etr_dump@50f00000 { -+ no-map; -+ reg = <0x0 0x50f00000 0x0 0x00100000>; -+ }; -+ -+ m3_dump_region: m3_dump@51000000 { -+ no-map; -+ reg = <0x0 0x51000000 0x0 0x100000>; -+ }; - }; - - firmware { diff --git a/target/linux/ipq60xx/patches-5.15/0101-clk-qcom-clk-rcg2-add-rcg2-mux-ops.patch b/target/linux/ipq60xx/patches-5.15/0101-clk-qcom-clk-rcg2-add-rcg2-mux-ops.patch deleted file mode 100644 index 548f1e97d..000000000 --- a/target/linux/ipq60xx/patches-5.15/0101-clk-qcom-clk-rcg2-add-rcg2-mux-ops.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 9d38e110e23ce0b858ccd67a8a819dc187529a33 Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Fri, 8 Jul 2022 23:24:25 +0200 -Subject: [PATCH 101/137] clk: qcom: clk-rcg2: add rcg2 mux ops - -An RCG may act as a mux that switch between 2 parents. -This is the case on IPQ6018 and IPQ8074 where the APCS core clk that feeds -the CPU cluster clock just switches between XO and the PLL that feeds it. - -Add the required ops to add support for this special configuration and use -the generic mux function to determine the rate. - -This way we dont have to keep a essentially dummy frequency table to use -RCG2 as a mux. - -Signed-off-by: Christian Marangi -Signed-off-by: Robert Marko -Reviewed-by: Dmitry Baryshkov ---- - drivers/clk/qcom/clk-rcg.h | 1 + - drivers/clk/qcom/clk-rcg2.c | 7 +++++++ - 2 files changed, 8 insertions(+) - ---- a/drivers/clk/qcom/clk-rcg.h -+++ b/drivers/clk/qcom/clk-rcg.h -@@ -164,6 +164,7 @@ struct clk_rcg2_gfx3d { - - extern const struct clk_ops clk_rcg2_ops; - extern const struct clk_ops clk_rcg2_floor_ops; -+extern const struct clk_ops clk_rcg2_mux_closest_ops; - extern const struct clk_ops clk_edp_pixel_ops; - extern const struct clk_ops clk_byte_ops; - extern const struct clk_ops clk_byte2_ops; ---- a/drivers/clk/qcom/clk-rcg2.c -+++ b/drivers/clk/qcom/clk-rcg2.c -@@ -471,6 +471,13 @@ const struct clk_ops clk_rcg2_floor_ops - }; - EXPORT_SYMBOL_GPL(clk_rcg2_floor_ops); - -+const struct clk_ops clk_rcg2_mux_closest_ops = { -+ .determine_rate = __clk_mux_determine_rate_closest, -+ .get_parent = clk_rcg2_get_parent, -+ .set_parent = clk_rcg2_set_parent, -+}; -+EXPORT_SYMBOL_GPL(clk_rcg2_mux_closest_ops); -+ - struct frac_entry { - int num; - int den; diff --git a/target/linux/ipq60xx/patches-5.15/0102-clk-qcom-apss-ipq6018-fix-apcs_alias0_clk_src.patch b/target/linux/ipq60xx/patches-5.15/0102-clk-qcom-apss-ipq6018-fix-apcs_alias0_clk_src.patch deleted file mode 100644 index 9f05a72f1..000000000 --- a/target/linux/ipq60xx/patches-5.15/0102-clk-qcom-apss-ipq6018-fix-apcs_alias0_clk_src.patch +++ /dev/null @@ -1,61 +0,0 @@ -From d2b31da4eae2175ff86f28f596b54abde08d382f Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Sat, 9 Jul 2022 00:18:45 +0200 -Subject: [PATCH 102/137] clk: qcom: apss-ipq6018: fix apcs_alias0_clk_src - -While working on IPQ8074 APSS driver it was discovered that IPQ6018 and -IPQ8074 use almost the same PLL and APSS clocks, however APSS driver is -currently broken. - -More precisely apcs_alias0_clk_src is broken, it was added as regmap_mux -clock. -However after debugging why it was always stuck at 800Mhz, it was figured -out that its not regmap_mux compatible at all. -It is a simple mux but it uses RCG2 register layout and control bits, so -utilize the new clk_rcg2_mux_closest_ops to correctly drive it while not -having to provide a dummy frequency table. - -While we are here, use ARRAY_SIZE for number of parents. - -Tested on IPQ6018-CP01-C1 reference board and multiple IPQ8074 boards. - -Fixes: 5e77b4ef1b19 ("clk: qcom: Add ipq6018 apss clock controller") -Signed-off-by: Robert Marko -Reviewed-by: Dmitry Baryshkov ---- - drivers/clk/qcom/apss-ipq6018.c | 13 ++++++------- - 1 file changed, 6 insertions(+), 7 deletions(-) - ---- a/drivers/clk/qcom/apss-ipq6018.c -+++ b/drivers/clk/qcom/apss-ipq6018.c -@@ -16,7 +16,7 @@ - #include "clk-regmap.h" - #include "clk-branch.h" - #include "clk-alpha-pll.h" --#include "clk-regmap-mux.h" -+#include "clk-rcg.h" - - enum { - P_XO, -@@ -33,16 +33,15 @@ static const struct parent_map parents_a - { P_APSS_PLL_EARLY, 5 }, - }; - --static struct clk_regmap_mux apcs_alias0_clk_src = { -- .reg = 0x0050, -- .width = 3, -- .shift = 7, -+static struct clk_rcg2 apcs_alias0_clk_src = { -+ .cmd_rcgr = 0x0050, -+ .hid_width = 5, - .parent_map = parents_apcs_alias0_clk_src_map, - .clkr.hw.init = &(struct clk_init_data){ - .name = "apcs_alias0_clk_src", - .parent_data = parents_apcs_alias0_clk_src, -- .num_parents = 2, -- .ops = &clk_regmap_mux_closest_ops, -+ .num_parents = ARRAY_SIZE(parents_apcs_alias0_clk_src), -+ .ops = &clk_rcg2_mux_closest_ops, - .flags = CLK_SET_RATE_PARENT, - }, - }; diff --git a/target/linux/ipq60xx/patches-5.15/0104-clk-qcom-apss-ipq-pll-use-OF-match-data-for-Alpha-PL.patch b/target/linux/ipq60xx/patches-5.15/0104-clk-qcom-apss-ipq-pll-use-OF-match-data-for-Alpha-PL.patch deleted file mode 100644 index 18ba654a0..000000000 --- a/target/linux/ipq60xx/patches-5.15/0104-clk-qcom-apss-ipq-pll-use-OF-match-data-for-Alpha-PL.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 8878f39722eeacbb40babe82ad763d8d20214018 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Sat, 9 Jul 2022 00:32:04 +0200 -Subject: [PATCH 104/137] clk: qcom: apss-ipq-pll: use OF match data for Alpha - PLL config - -Convert the driver to use OF match data for providing the Alpha PLL config -per compatible. -This is required for IPQ8074 support since it uses a different Alpha PLL -config. - -While we are here rename "ipq_pll_config" to "ipq6018_pll_config" to make -it clear that it is for IPQ6018 only. - -Signed-off-by: Robert Marko ---- - drivers/clk/qcom/apss-ipq-pll.c | 12 +++++++++--- - 1 file changed, 9 insertions(+), 3 deletions(-) - ---- a/drivers/clk/qcom/apss-ipq-pll.c -+++ b/drivers/clk/qcom/apss-ipq-pll.c -@@ -2,6 +2,7 @@ - // Copyright (c) 2018, The Linux Foundation. All rights reserved. - #include - #include -+#include - #include - #include - -@@ -36,7 +37,7 @@ static struct clk_alpha_pll ipq_pll = { - }, - }; - --static const struct alpha_pll_config ipq_pll_config = { -+static const struct alpha_pll_config ipq6018_pll_config = { - .l = 0x37, - .config_ctl_val = 0x04141200, - .config_ctl_hi_val = 0x0, -@@ -54,6 +55,7 @@ static const struct regmap_config ipq_pl - - static int apss_ipq_pll_probe(struct platform_device *pdev) - { -+ const struct alpha_pll_config *ipq_pll_config; - struct device *dev = &pdev->dev; - struct regmap *regmap; - void __iomem *base; -@@ -67,7 +69,11 @@ static int apss_ipq_pll_probe(struct pla - if (IS_ERR(regmap)) - return PTR_ERR(regmap); - -- clk_alpha_pll_configure(&ipq_pll, regmap, &ipq_pll_config); -+ ipq_pll_config = of_device_get_match_data(&pdev->dev); -+ if (!ipq_pll_config) -+ return -ENODEV; -+ -+ clk_alpha_pll_configure(&ipq_pll, regmap, ipq_pll_config); - - ret = devm_clk_register_regmap(dev, &ipq_pll.clkr); - if (ret) -@@ -78,7 +84,7 @@ static int apss_ipq_pll_probe(struct pla - } - - static const struct of_device_id apss_ipq_pll_match_table[] = { -- { .compatible = "qcom,ipq6018-a53pll" }, -+ { .compatible = "qcom,ipq6018-a53pll", .data = &ipq6018_pll_config }, - { } - }; - MODULE_DEVICE_TABLE(of, apss_ipq_pll_match_table); diff --git a/target/linux/ipq60xx/patches-5.15/0105-clk-qcom-apss-ipq-pll-update-IPQ6018-Alpha-PLL-confi.patch b/target/linux/ipq60xx/patches-5.15/0105-clk-qcom-apss-ipq-pll-update-IPQ6018-Alpha-PLL-confi.patch deleted file mode 100644 index 6a84c13cc..000000000 --- a/target/linux/ipq60xx/patches-5.15/0105-clk-qcom-apss-ipq-pll-update-IPQ6018-Alpha-PLL-confi.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 426edd7e45e9eaf18c433739ceeb51e6f2f8e190 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Mon, 11 Jul 2022 22:40:52 +0200 -Subject: [PATCH 105/137] clk: qcom: apss-ipq-pll: update IPQ6018 Alpha PLL - config - -Update the IPQ6018 Alpha PLL config to the latest one from the downstream -5.4 kernel[1]. - -This one should match the production SoC-s. - -Tested on IPQ6018 CP01-C1 reference board. - -[1] https://git.codelinaro.org/clo/qsdk/oss/kernel/linux-ipq-5.4/-/blob/NHSS.QSDK.12.1.r4/drivers/clk/qcom/apss-ipq-pll.c#L41 -Signed-off-by: Robert Marko ---- - drivers/clk/qcom/apss-ipq-pll.c | 8 ++++++-- - 1 file changed, 6 insertions(+), 2 deletions(-) - ---- a/drivers/clk/qcom/apss-ipq-pll.c -+++ b/drivers/clk/qcom/apss-ipq-pll.c -@@ -39,10 +39,14 @@ static struct clk_alpha_pll ipq_pll = { - - static const struct alpha_pll_config ipq6018_pll_config = { - .l = 0x37, -- .config_ctl_val = 0x04141200, -- .config_ctl_hi_val = 0x0, -+ .config_ctl_val = 0x240d4828, -+ .config_ctl_hi_val = 0x6, - .early_output_mask = BIT(3), -+ .aux2_output_mask = BIT(2), -+ .aux_output_mask = BIT(1), - .main_output_mask = BIT(0), -+ .test_ctl_val = 0x1c0000C0, -+ .test_ctl_hi_val = 0x4000, - }; - - static const struct regmap_config ipq_pll_regmap_config = { diff --git a/target/linux/ipq60xx/patches-5.15/0106-clk-qcom-apss-ipq-pll-add-support-for-IPQ8074.patch b/target/linux/ipq60xx/patches-5.15/0106-clk-qcom-apss-ipq-pll-add-support-for-IPQ8074.patch deleted file mode 100644 index f59ce60c8..000000000 --- a/target/linux/ipq60xx/patches-5.15/0106-clk-qcom-apss-ipq-pll-add-support-for-IPQ8074.patch +++ /dev/null @@ -1,51 +0,0 @@ -From c633afe32123157370f21aeaf3d705ca584fc754 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Mon, 11 Jul 2022 14:23:08 +0200 -Subject: [PATCH 106/137] clk: qcom: apss-ipq-pll: add support for IPQ8074 - -Add support for IPQ8074 since it uses the same PLL setup, however it uses -slightly different Alpha PLL config. - -Alpha PLL config was obtained by dumping PLL registers from a running -device. - -Signed-off-by: Robert Marko ---- -Changes in v2: -* Drop hardcoded compatible check for IPQ6018 to do the PLL config and -utilize match data provided by previous commit -* Add IPQ8074 Alpha PLL config using match data -* Update commit description to reflect changes ---- - drivers/clk/qcom/apss-ipq-pll.c | 13 +++++++++++++ - 1 file changed, 13 insertions(+) - ---- a/drivers/clk/qcom/apss-ipq-pll.c -+++ b/drivers/clk/qcom/apss-ipq-pll.c -@@ -49,6 +49,18 @@ static const struct alpha_pll_config ipq - .test_ctl_hi_val = 0x4000, - }; - -+static const struct alpha_pll_config ipq8074_pll_config = { -+ .l = 0x48, -+ .config_ctl_val = 0x200d4828, -+ .config_ctl_hi_val = 0x6, -+ .early_output_mask = BIT(3), -+ .aux2_output_mask = BIT(2), -+ .aux_output_mask = BIT(1), -+ .main_output_mask = BIT(0), -+ .test_ctl_val = 0x1c000000, -+ .test_ctl_hi_val = 0x4000, -+}; -+ - static const struct regmap_config ipq_pll_regmap_config = { - .reg_bits = 32, - .reg_stride = 4, -@@ -89,6 +101,7 @@ static int apss_ipq_pll_probe(struct pla - - static const struct of_device_id apss_ipq_pll_match_table[] = { - { .compatible = "qcom,ipq6018-a53pll", .data = &ipq6018_pll_config }, -+ { .compatible = "qcom,ipq8074-a53pll", .data = &ipq8074_pll_config }, - { } - }; - MODULE_DEVICE_TABLE(of, apss_ipq_pll_match_table); diff --git a/target/linux/ipq60xx/patches-5.15/0107-arm64-dts-qcom-ipq8074-correct-APCS-register-space-s.patch b/target/linux/ipq60xx/patches-5.15/0107-arm64-dts-qcom-ipq8074-correct-APCS-register-space-s.patch deleted file mode 100644 index 31a6e1f8b..000000000 --- a/target/linux/ipq60xx/patches-5.15/0107-arm64-dts-qcom-ipq8074-correct-APCS-register-space-s.patch +++ /dev/null @@ -1,31 +0,0 @@ -From f3d524334069e69554eaecd8adf75284dff7c9d9 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Thu, 18 Aug 2022 23:15:43 +0200 -Subject: [PATCH 107/137] arm64: dts: qcom: ipq8074: correct APCS register - space size - -APCS DTS addition that was merged, was not supposed to get merged as it -was part of patch series that was superseded by 2 more patch series -that resolved issues with this one and greatly simplified things. - -Since it already got merged, start by correcting the register space -size as APCS will not be providing regmap for PLL and it will conflict -with the standalone A53 PLL node. - -Fixes: 50ed9fffec3a ("arm64: dts: qcom: ipq8074: add APCS node") -Signed-off-by: Robert Marko ---- - arch/arm64/boot/dts/qcom/ipq8074.dtsi | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -704,7 +704,7 @@ - - apcs_glb: mailbox@b111000 { - compatible = "qcom,ipq8074-apcs-apps-global"; -- reg = <0x0b111000 0x6000>; -+ reg = <0x0b111000 0x1000>; - - #clock-cells = <1>; - #mbox-cells = <1>; diff --git a/target/linux/ipq60xx/patches-5.15/0108-arm64-dts-qcom-ipq8074-add-A53-PLL-node.patch b/target/linux/ipq60xx/patches-5.15/0108-arm64-dts-qcom-ipq8074-add-A53-PLL-node.patch deleted file mode 100644 index 26b9a0df1..000000000 --- a/target/linux/ipq60xx/patches-5.15/0108-arm64-dts-qcom-ipq8074-add-A53-PLL-node.patch +++ /dev/null @@ -1,30 +0,0 @@ -From be028f5f79b8af6ea16ffeea486e216acdf80789 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Thu, 18 Aug 2022 23:21:06 +0200 -Subject: [PATCH 108/137] arm64: dts: qcom: ipq8074: add A53 PLL node - -Add the required node for A53 PLL which will be used to provide the CPU -clock via APCS for APSS scaling. - -Signed-off-by: Robert Marko ---- - arch/arm64/boot/dts/qcom/ipq8074.dtsi | 8 ++++++++ - 1 file changed, 8 insertions(+) - ---- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -710,6 +710,14 @@ - #mbox-cells = <1>; - }; - -+ a53pll: clock@b116000 { -+ compatible = "qcom,ipq8074-a53pll"; -+ reg = <0x0b116000 0x40>; -+ #clock-cells = <0>; -+ clocks = <&xo>; -+ clock-names = "xo"; -+ }; -+ - timer@b120000 { - #address-cells = <1>; - #size-cells = <1>; diff --git a/target/linux/ipq60xx/patches-5.15/0109-mailbox-qcom-apcs-ipc-add-IPQ8074-APSS-clock-support.patch b/target/linux/ipq60xx/patches-5.15/0109-mailbox-qcom-apcs-ipc-add-IPQ8074-APSS-clock-support.patch deleted file mode 100644 index 32a9faafe..000000000 --- a/target/linux/ipq60xx/patches-5.15/0109-mailbox-qcom-apcs-ipc-add-IPQ8074-APSS-clock-support.patch +++ /dev/null @@ -1,50 +0,0 @@ -From ded0538937e9edf8b217d2082fd30af3bf7bd10b Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Tue, 28 Dec 2021 20:59:18 +0100 -Subject: [PATCH 109/137] mailbox: qcom-apcs-ipc: add IPQ8074 APSS clock - support - -IPQ8074 has the APSS clock controller utilizing the same register space as -the APCS, so provide access to the APSS utilizing a child device like -IPQ6018. - -IPQ6018 and IPQ8074 use the same controller and driver, so just utilize -IPQ6018 match data for IPQ8074. - -Signed-off-by: Robert Marko -Reviewed-by: Dmitry Baryshkov ---- -Changes in v7: -* Dont max_register modifications -* Drop custom IPQ8074 match data and use IPQ6018 one as they share the -controller and driver - -Changes in v5: -* Use lower case hex for max_register -* Update the APSS clock name to match the new one without commas ---- - drivers/mailbox/qcom-apcs-ipc-mailbox.c | 6 +----- - 1 file changed, 1 insertion(+), 5 deletions(-) - ---- a/drivers/mailbox/qcom-apcs-ipc-mailbox.c -+++ b/drivers/mailbox/qcom-apcs-ipc-mailbox.c -@@ -33,10 +33,6 @@ static const struct qcom_apcs_ipc_data i - .offset = 8, .clk_name = "qcom,apss-ipq6018-clk" - }; - --static const struct qcom_apcs_ipc_data ipq8074_apcs_data = { -- .offset = 8, .clk_name = NULL --}; -- - static const struct qcom_apcs_ipc_data msm8916_apcs_data = { - .offset = 8, .clk_name = "qcom-apcs-msm8916-clk" - }; -@@ -160,7 +156,7 @@ static int qcom_apcs_ipc_remove(struct p - /* .data is the offset of the ipc register within the global block */ - static const struct of_device_id qcom_apcs_ipc_of_match[] = { - { .compatible = "qcom,ipq6018-apcs-apps-global", .data = &ipq6018_apcs_data }, -- { .compatible = "qcom,ipq8074-apcs-apps-global", .data = &ipq8074_apcs_data }, -+ { .compatible = "qcom,ipq8074-apcs-apps-global", .data = &ipq6018_apcs_data }, - { .compatible = "qcom,msm8916-apcs-kpss-global", .data = &msm8916_apcs_data }, - { .compatible = "qcom,msm8939-apcs-kpss-global", .data = &msm8916_apcs_data }, - { .compatible = "qcom,msm8953-apcs-kpss-global", .data = &msm8994_apcs_data }, diff --git a/target/linux/ipq60xx/patches-5.15/0110-arm64-dts-qcom-ipq8074-add-clocks-to-APCS.patch b/target/linux/ipq60xx/patches-5.15/0110-arm64-dts-qcom-ipq8074-add-clocks-to-APCS.patch deleted file mode 100644 index c90ccdbb0..000000000 --- a/target/linux/ipq60xx/patches-5.15/0110-arm64-dts-qcom-ipq8074-add-clocks-to-APCS.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0a36a586424feabf9ce9436379f9d061b7844155 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Thu, 18 Aug 2022 23:25:00 +0200 -Subject: [PATCH 110/137] arm64: dts: qcom: ipq8074: add clocks to APCS - -APCS now has support for providing the APSS clocks as the child device -for IPQ8074. - -So, add the A53 PLL and XO clocks in order to use APCS as the CPU -clocksource for APSS scaling. - -Signed-off-by: Robert Marko ---- - arch/arm64/boot/dts/qcom/ipq8074.dtsi | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - ---- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -705,8 +705,9 @@ - apcs_glb: mailbox@b111000 { - compatible = "qcom,ipq8074-apcs-apps-global"; - reg = <0x0b111000 0x1000>; -- - #clock-cells = <1>; -+ clocks = <&a53pll>, <&xo>; -+ clock-names = "pll", "xo"; - #mbox-cells = <1>; - }; - diff --git a/target/linux/ipq60xx/patches-5.15/0111-PCI-qcom-add-IPQ8074-Gen3-support.patch b/target/linux/ipq60xx/patches-5.15/0111-PCI-qcom-add-IPQ8074-Gen3-support.patch deleted file mode 100644 index 3a3c5b84a..000000000 --- a/target/linux/ipq60xx/patches-5.15/0111-PCI-qcom-add-IPQ8074-Gen3-support.patch +++ /dev/null @@ -1,45 +0,0 @@ -From f086c5659cd54946b618ae4c695a8c05096f267a Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Mon, 20 Dec 2021 15:01:36 +0100 -Subject: [PATCH 111/137] PCI: qcom: add IPQ8074 Gen3 support - -IPQ8074 has one Gen2 and one Gen3 port, Gen3 port is the same one as -in IPQ6018, so reuse the support but just add the missing clocks. - -Signed-off-by: Robert Marko ---- - drivers/pci/controller/dwc/pcie-qcom.c | 9 ++++++--- - 1 file changed, 6 insertions(+), 3 deletions(-) - ---- a/drivers/pci/controller/dwc/pcie-qcom.c -+++ b/drivers/pci/controller/dwc/pcie-qcom.c -@@ -184,7 +184,7 @@ struct qcom_pcie_resources_2_7_0 { - }; - - struct qcom_pcie_resources_2_9_0 { -- struct clk_bulk_data clks[5]; -+ struct clk_bulk_data clks[7]; - struct reset_control *rst; - }; - -@@ -1296,8 +1296,10 @@ static int qcom_pcie_get_resources_2_9_0 - res->clks[0].id = "iface"; - res->clks[1].id = "axi_m"; - res->clks[2].id = "axi_s"; -- res->clks[3].id = "axi_bridge"; -- res->clks[4].id = "rchng"; -+ res->clks[3].id = "ahb"; -+ res->clks[4].id = "aux"; -+ res->clks[5].id = "axi_bridge"; -+ res->clks[6].id = "rchng"; - - ret = devm_clk_bulk_get(dev, ARRAY_SIZE(res->clks), res->clks); - if (ret < 0) -@@ -1700,6 +1702,7 @@ static const struct of_device_id qcom_pc - { .compatible = "qcom,pcie-sdm845", .data = &ops_2_7_0 }, - { .compatible = "qcom,pcie-sm8250", .data = &ops_1_9_0 }, - { .compatible = "qcom,pcie-ipq6018", .data = &ops_2_9_0 }, -+ { .compatible = "qcom,pcie-ipq8074-gen3", .data = &ops_2_9_0 }, - { } - }; - diff --git a/target/linux/ipq60xx/patches-5.15/0113-remoteproc-qcom-Add-PRNG-proxy-clock.patch b/target/linux/ipq60xx/patches-5.15/0113-remoteproc-qcom-Add-PRNG-proxy-clock.patch deleted file mode 100644 index 01750ecfe..000000000 --- a/target/linux/ipq60xx/patches-5.15/0113-remoteproc-qcom-Add-PRNG-proxy-clock.patch +++ /dev/null @@ -1,155 +0,0 @@ -From 84e13a5267e43bb0a6a1f764211fda7769dc9cbe Mon Sep 17 00:00:00 2001 -From: Gokul Sriram Palanisamy -Date: Sat, 30 Jan 2021 10:50:05 +0530 -Subject: [PATCH 113/137] remoteproc: qcom: Add PRNG proxy clock - -PRNG clock is needed by the secure PIL, support for the same -is added in subsequent patches. - -Signed-off-by: Gokul Sriram Palanisamy -Signed-off-by: Sricharan R -Signed-off-by: Nikhil Prakash V ---- - drivers/remoteproc/qcom_q6v5_wcss.c | 65 +++++++++++++++++++++-------- - 1 file changed, 47 insertions(+), 18 deletions(-) - ---- a/drivers/remoteproc/qcom_q6v5_wcss.c -+++ b/drivers/remoteproc/qcom_q6v5_wcss.c -@@ -91,19 +91,6 @@ enum { - WCSS_QCS404, - }; - --struct wcss_data { -- const char *firmware_name; -- unsigned int crash_reason_smem; -- u32 version; -- bool aon_reset_required; -- bool wcss_q6_reset_required; -- const char *ssr_name; -- const char *sysmon_name; -- int ssctl_id; -- const struct rproc_ops *ops; -- bool requires_force_stop; --}; -- - struct q6v5_wcss { - struct device *dev; - -@@ -128,6 +115,7 @@ struct q6v5_wcss { - struct clk *qdsp6ss_xo_cbcr; - struct clk *qdsp6ss_core_gfmux; - struct clk *lcc_bcr_sleep; -+ struct clk *prng_clk; - struct regulator *cx_supply; - struct qcom_sysmon *sysmon; - -@@ -151,6 +139,21 @@ struct q6v5_wcss { - struct qcom_rproc_ssr ssr_subdev; - }; - -+struct wcss_data { -+ int (*init_clock)(struct q6v5_wcss *wcss); -+ int (*init_regulator)(struct q6v5_wcss *wcss); -+ const char *firmware_name; -+ unsigned int crash_reason_smem; -+ u32 version; -+ bool aon_reset_required; -+ bool wcss_q6_reset_required; -+ const char *ssr_name; -+ const char *sysmon_name; -+ int ssctl_id; -+ const struct rproc_ops *ops; -+ bool requires_force_stop; -+}; -+ - static int q6v5_wcss_reset(struct q6v5_wcss *wcss) - { - int ret; -@@ -240,6 +243,12 @@ static int q6v5_wcss_start(struct rproc - struct q6v5_wcss *wcss = rproc->priv; - int ret; - -+ ret = clk_prepare_enable(wcss->prng_clk); -+ if (ret) { -+ dev_err(wcss->dev, "prng clock enable failed\n"); -+ return ret; -+ } -+ - qcom_q6v5_prepare(&wcss->q6v5); - - /* Release Q6 and WCSS reset */ -@@ -733,6 +742,7 @@ static int q6v5_wcss_stop(struct rproc * - return ret; - } - -+ clk_disable_unprepare(wcss->prng_clk); - qcom_q6v5_unprepare(&wcss->q6v5); - - return 0; -@@ -900,7 +910,21 @@ static int q6v5_alloc_memory_region(stru - return 0; - } - --static int q6v5_wcss_init_clock(struct q6v5_wcss *wcss) -+static int ipq8074_init_clock(struct q6v5_wcss *wcss) -+{ -+ int ret; -+ -+ wcss->prng_clk = devm_clk_get(wcss->dev, "prng"); -+ if (IS_ERR(wcss->prng_clk)) { -+ ret = PTR_ERR(wcss->prng_clk); -+ if (ret != -EPROBE_DEFER) -+ dev_err(wcss->dev, "Failed to get prng clock\n"); -+ return ret; -+ } -+ return 0; -+} -+ -+static int qcs404_init_clock(struct q6v5_wcss *wcss) - { - int ret; - -@@ -990,7 +1014,7 @@ static int q6v5_wcss_init_clock(struct q - return 0; - } - --static int q6v5_wcss_init_regulator(struct q6v5_wcss *wcss) -+static int qcs404_init_regulator(struct q6v5_wcss *wcss) - { - wcss->cx_supply = devm_regulator_get(wcss->dev, "cx"); - if (IS_ERR(wcss->cx_supply)) -@@ -1034,12 +1058,14 @@ static int q6v5_wcss_probe(struct platfo - if (ret) - goto free_rproc; - -- if (wcss->version == WCSS_QCS404) { -- ret = q6v5_wcss_init_clock(wcss); -+ if (desc->init_clock) { -+ ret = desc->init_clock(wcss); - if (ret) - goto free_rproc; -+ } - -- ret = q6v5_wcss_init_regulator(wcss); -+ if (desc->init_regulator) { -+ ret = desc->init_regulator(wcss); - if (ret) - goto free_rproc; - } -@@ -1086,6 +1112,7 @@ static int q6v5_wcss_remove(struct platf - } - - static const struct wcss_data wcss_ipq8074_res_init = { -+ .init_clock = ipq8074_init_clock, - .firmware_name = "IPQ8074/q6_fw.mdt", - .crash_reason_smem = WCSS_CRASH_REASON, - .aon_reset_required = true, -@@ -1095,6 +1122,8 @@ static const struct wcss_data wcss_ipq80 - }; - - static const struct wcss_data wcss_qcs404_res_init = { -+ .init_clock = qcs404_init_clock, -+ .init_regulator = qcs404_init_regulator, - .crash_reason_smem = WCSS_CRASH_REASON, - .firmware_name = "wcnss.mdt", - .version = WCSS_QCS404, diff --git a/target/linux/ipq60xx/patches-5.15/0114-remoteproc-qcom-Add-secure-PIL-support.patch b/target/linux/ipq60xx/patches-5.15/0114-remoteproc-qcom-Add-secure-PIL-support.patch deleted file mode 100644 index 35c105754..000000000 --- a/target/linux/ipq60xx/patches-5.15/0114-remoteproc-qcom-Add-secure-PIL-support.patch +++ /dev/null @@ -1,143 +0,0 @@ -From cb3b9e284104fd7fe4aa92a37df005577aed2c40 Mon Sep 17 00:00:00 2001 -From: Gokul Sriram Palanisamy -Date: Sat, 30 Jan 2021 10:50:06 +0530 -Subject: [PATCH 114/137] remoteproc: qcom: Add secure PIL support - -IPQ8074 uses secure PIL. Hence, adding the support for the same. - -Signed-off-by: Gokul Sriram Palanisamy -Signed-off-by: Sricharan R -Signed-off-by: Nikhil Prakash V ---- - drivers/remoteproc/qcom_q6v5_wcss.c | 43 +++++++++++++++++++++++++++-- - 1 file changed, 40 insertions(+), 3 deletions(-) - ---- a/drivers/remoteproc/qcom_q6v5_wcss.c -+++ b/drivers/remoteproc/qcom_q6v5_wcss.c -@@ -18,6 +18,7 @@ - #include - #include - #include -+#include - #include "qcom_common.h" - #include "qcom_pil_info.h" - #include "qcom_q6v5.h" -@@ -86,6 +87,9 @@ - #define TCSR_WCSS_CLK_ENABLE 0x14 - - #define MAX_HALT_REG 3 -+ -+#define WCNSS_PAS_ID 6 -+ - enum { - WCSS_IPQ8074, - WCSS_QCS404, -@@ -134,6 +138,7 @@ struct q6v5_wcss { - unsigned int crash_reason_smem; - u32 version; - bool requires_force_stop; -+ bool need_mem_protection; - - struct qcom_rproc_glink glink_subdev; - struct qcom_rproc_ssr ssr_subdev; -@@ -152,6 +157,7 @@ struct wcss_data { - int ssctl_id; - const struct rproc_ops *ops; - bool requires_force_stop; -+ bool need_mem_protection; - }; - - static int q6v5_wcss_reset(struct q6v5_wcss *wcss) -@@ -251,6 +257,15 @@ static int q6v5_wcss_start(struct rproc - - qcom_q6v5_prepare(&wcss->q6v5); - -+ if (wcss->need_mem_protection) { -+ ret = qcom_scm_pas_auth_and_reset(WCNSS_PAS_ID); -+ if (ret) { -+ dev_err(wcss->dev, "wcss_reset failed\n"); -+ return ret; -+ } -+ goto wait_for_reset; -+ } -+ - /* Release Q6 and WCSS reset */ - ret = reset_control_deassert(wcss->wcss_reset); - if (ret) { -@@ -285,6 +300,7 @@ static int q6v5_wcss_start(struct rproc - if (ret) - goto wcss_q6_reset; - -+wait_for_reset: - ret = qcom_q6v5_wait_for_start(&wcss->q6v5, 5 * HZ); - if (ret == -ETIMEDOUT) - dev_err(wcss->dev, "start timed out\n"); -@@ -718,6 +734,15 @@ static int q6v5_wcss_stop(struct rproc * - struct q6v5_wcss *wcss = rproc->priv; - int ret; - -+ if (wcss->need_mem_protection) { -+ ret = qcom_scm_pas_shutdown(WCNSS_PAS_ID); -+ if (ret) { -+ dev_err(wcss->dev, "not able to shutdown\n"); -+ return ret; -+ } -+ goto pas_done; -+ } -+ - /* WCSS powerdown */ - if (wcss->requires_force_stop) { - ret = qcom_q6v5_request_stop(&wcss->q6v5, NULL); -@@ -742,6 +767,7 @@ static int q6v5_wcss_stop(struct rproc * - return ret; - } - -+pas_done: - clk_disable_unprepare(wcss->prng_clk); - qcom_q6v5_unprepare(&wcss->q6v5); - -@@ -765,9 +791,15 @@ static int q6v5_wcss_load(struct rproc * - struct q6v5_wcss *wcss = rproc->priv; - int ret; - -- ret = qcom_mdt_load_no_init(wcss->dev, fw, rproc->firmware, -- 0, wcss->mem_region, wcss->mem_phys, -- wcss->mem_size, &wcss->mem_reloc); -+ if (wcss->need_mem_protection) -+ ret = qcom_mdt_load(wcss->dev, fw, rproc->firmware, -+ WCNSS_PAS_ID, wcss->mem_region, -+ wcss->mem_phys, wcss->mem_size, -+ &wcss->mem_reloc); -+ else -+ ret = qcom_mdt_load_no_init(wcss->dev, fw, rproc->firmware, -+ 0, wcss->mem_region, wcss->mem_phys, -+ wcss->mem_size, &wcss->mem_reloc); - if (ret) - return ret; - -@@ -1036,6 +1068,9 @@ static int q6v5_wcss_probe(struct platfo - if (!desc) - return -EINVAL; - -+ if (desc->need_mem_protection && !qcom_scm_is_available()) -+ return -EPROBE_DEFER; -+ - rproc = rproc_alloc(&pdev->dev, pdev->name, desc->ops, - desc->firmware_name, sizeof(*wcss)); - if (!rproc) { -@@ -1049,6 +1084,7 @@ static int q6v5_wcss_probe(struct platfo - - wcss->version = desc->version; - wcss->requires_force_stop = desc->requires_force_stop; -+ wcss->need_mem_protection = desc->need_mem_protection; - - ret = q6v5_wcss_init_mmio(wcss, pdev); - if (ret) -@@ -1119,6 +1155,7 @@ static const struct wcss_data wcss_ipq80 - .wcss_q6_reset_required = true, - .ops = &q6v5_wcss_ipq8074_ops, - .requires_force_stop = true, -+ .need_mem_protection = true, - }; - - static const struct wcss_data wcss_qcs404_res_init = { diff --git a/target/linux/ipq60xx/patches-5.15/0115-remoteproc-qcom-Add-support-for-split-q6-m3-wlan-fir.patch b/target/linux/ipq60xx/patches-5.15/0115-remoteproc-qcom-Add-support-for-split-q6-m3-wlan-fir.patch deleted file mode 100644 index 04f93045c..000000000 --- a/target/linux/ipq60xx/patches-5.15/0115-remoteproc-qcom-Add-support-for-split-q6-m3-wlan-fir.patch +++ /dev/null @@ -1,104 +0,0 @@ -From bcb2c37f265924ac43642f1f97c964dd546b3cb5 Mon Sep 17 00:00:00 2001 -From: Gokul Sriram Palanisamy -Date: Sat, 30 Jan 2021 10:50:07 +0530 -Subject: [PATCH 115/137] remoteproc: qcom: Add support for split q6 + m3 wlan - firmware - -IPQ8074 supports split firmware for q6 and m3 as well. -So add support for loading the m3 firmware before q6. -Now the drivers works fine for both split and unified -firmwares. - -Signed-off-by: Gokul Sriram Palanisamy -Signed-off-by: Sricharan R -Signed-off-by: Nikhil Prakash V ---- - drivers/remoteproc/qcom_q6v5_wcss.c | 33 +++++++++++++++++++++++++---- - 1 file changed, 29 insertions(+), 4 deletions(-) - ---- a/drivers/remoteproc/qcom_q6v5_wcss.c -+++ b/drivers/remoteproc/qcom_q6v5_wcss.c -@@ -139,6 +139,7 @@ struct q6v5_wcss { - u32 version; - bool requires_force_stop; - bool need_mem_protection; -+ const char *m3_firmware_name; - - struct qcom_rproc_glink glink_subdev; - struct qcom_rproc_ssr ssr_subdev; -@@ -147,7 +148,8 @@ struct q6v5_wcss { - struct wcss_data { - int (*init_clock)(struct q6v5_wcss *wcss); - int (*init_regulator)(struct q6v5_wcss *wcss); -- const char *firmware_name; -+ const char *q6_firmware_name; -+ const char *m3_firmware_name; - unsigned int crash_reason_smem; - u32 version; - bool aon_reset_required; -@@ -789,8 +791,29 @@ static void *q6v5_wcss_da_to_va(struct r - static int q6v5_wcss_load(struct rproc *rproc, const struct firmware *fw) - { - struct q6v5_wcss *wcss = rproc->priv; -+ const struct firmware *m3_fw; - int ret; - -+ if (wcss->m3_firmware_name) { -+ ret = request_firmware(&m3_fw, wcss->m3_firmware_name, -+ wcss->dev); -+ if (ret) -+ goto skip_m3; -+ -+ ret = qcom_mdt_load_no_init(wcss->dev, m3_fw, -+ wcss->m3_firmware_name, 0, -+ wcss->mem_region, wcss->mem_phys, -+ wcss->mem_size, &wcss->mem_reloc); -+ -+ release_firmware(m3_fw); -+ -+ if (ret) { -+ dev_err(wcss->dev, "can't load m3_fw.bXX\n"); -+ return ret; -+ } -+ } -+ -+skip_m3: - if (wcss->need_mem_protection) - ret = qcom_mdt_load(wcss->dev, fw, rproc->firmware, - WCNSS_PAS_ID, wcss->mem_region, -@@ -1072,7 +1095,7 @@ static int q6v5_wcss_probe(struct platfo - return -EPROBE_DEFER; - - rproc = rproc_alloc(&pdev->dev, pdev->name, desc->ops, -- desc->firmware_name, sizeof(*wcss)); -+ desc->q6_firmware_name, sizeof(*wcss)); - if (!rproc) { - dev_err(&pdev->dev, "failed to allocate rproc\n"); - return -ENOMEM; -@@ -1085,6 +1108,7 @@ static int q6v5_wcss_probe(struct platfo - wcss->version = desc->version; - wcss->requires_force_stop = desc->requires_force_stop; - wcss->need_mem_protection = desc->need_mem_protection; -+ wcss->m3_firmware_name = desc->m3_firmware_name; - - ret = q6v5_wcss_init_mmio(wcss, pdev); - if (ret) -@@ -1149,7 +1173,8 @@ static int q6v5_wcss_remove(struct platf - - static const struct wcss_data wcss_ipq8074_res_init = { - .init_clock = ipq8074_init_clock, -- .firmware_name = "IPQ8074/q6_fw.mdt", -+ .q6_firmware_name = "IPQ8074/q6_fw.mdt", -+ .m3_firmware_name = "IPQ8074/m3_fw.mdt", - .crash_reason_smem = WCSS_CRASH_REASON, - .aon_reset_required = true, - .wcss_q6_reset_required = true, -@@ -1162,7 +1187,7 @@ static const struct wcss_data wcss_qcs40 - .init_clock = qcs404_init_clock, - .init_regulator = qcs404_init_regulator, - .crash_reason_smem = WCSS_CRASH_REASON, -- .firmware_name = "wcnss.mdt", -+ .q6_firmware_name = "wcnss.mdt", - .version = WCSS_QCS404, - .aon_reset_required = false, - .wcss_q6_reset_required = false, diff --git a/target/linux/ipq60xx/patches-5.15/0116-remoteproc-qcom-Add-ssr-subdevice-identifier.patch b/target/linux/ipq60xx/patches-5.15/0116-remoteproc-qcom-Add-ssr-subdevice-identifier.patch deleted file mode 100644 index ff166087e..000000000 --- a/target/linux/ipq60xx/patches-5.15/0116-remoteproc-qcom-Add-ssr-subdevice-identifier.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 5b717749ce49853f495ebac227c72013622b0810 Mon Sep 17 00:00:00 2001 -From: Gokul Sriram Palanisamy -Date: Sat, 30 Jan 2021 10:50:08 +0530 -Subject: [PATCH 116/137] remoteproc: qcom: Add ssr subdevice identifier - -Add name for ssr subdevice on IPQ8074 SoC. - -Signed-off-by: Gokul Sriram Palanisamy -Signed-off-by: Sricharan R -Signed-off-by: Nikhil Prakash V ---- - drivers/remoteproc/qcom_q6v5_wcss.c | 1 + - 1 file changed, 1 insertion(+) - ---- a/drivers/remoteproc/qcom_q6v5_wcss.c -+++ b/drivers/remoteproc/qcom_q6v5_wcss.c -@@ -1178,6 +1178,7 @@ static const struct wcss_data wcss_ipq80 - .crash_reason_smem = WCSS_CRASH_REASON, - .aon_reset_required = true, - .wcss_q6_reset_required = true, -+ .ssr_name = "q6wcss", - .ops = &q6v5_wcss_ipq8074_ops, - .requires_force_stop = true, - .need_mem_protection = true, diff --git a/target/linux/ipq60xx/patches-5.15/0117-remoteproc-qcom-Update-regmap-offsets-for-halt-regis.patch b/target/linux/ipq60xx/patches-5.15/0117-remoteproc-qcom-Update-regmap-offsets-for-halt-regis.patch deleted file mode 100644 index 4cbbb825a..000000000 --- a/target/linux/ipq60xx/patches-5.15/0117-remoteproc-qcom-Update-regmap-offsets-for-halt-regis.patch +++ /dev/null @@ -1,80 +0,0 @@ -From 3bc5b97ecbb003e413ae76b332b0ccdba05ef6bc Mon Sep 17 00:00:00 2001 -From: Gokul Sriram Palanisamy -Date: Sat, 30 Jan 2021 10:50:09 +0530 -Subject: [PATCH 117/137] remoteproc: qcom: Update regmap offsets for halt - register - -Fixed issue in reading halt-regs parameter from device-tree. - -Signed-off-by: Gokul Sriram Palanisamy -Signed-off-by: Sricharan R ---- - drivers/remoteproc/qcom_q6v5_wcss.c | 22 ++++++++++++++-------- - 1 file changed, 14 insertions(+), 8 deletions(-) - ---- a/drivers/remoteproc/qcom_q6v5_wcss.c -+++ b/drivers/remoteproc/qcom_q6v5_wcss.c -@@ -86,7 +86,7 @@ - #define TCSR_WCSS_CLK_MASK 0x1F - #define TCSR_WCSS_CLK_ENABLE 0x14 - --#define MAX_HALT_REG 3 -+#define MAX_HALT_REG 4 - - #define WCNSS_PAS_ID 6 - -@@ -154,6 +154,7 @@ struct wcss_data { - u32 version; - bool aon_reset_required; - bool wcss_q6_reset_required; -+ bool bcr_reset_required; - const char *ssr_name; - const char *sysmon_name; - int ssctl_id; -@@ -875,10 +876,13 @@ static int q6v5_wcss_init_reset(struct q - } - } - -- wcss->wcss_q6_bcr_reset = devm_reset_control_get_exclusive(dev, "wcss_q6_bcr_reset"); -- if (IS_ERR(wcss->wcss_q6_bcr_reset)) { -- dev_err(wcss->dev, "unable to acquire wcss_q6_bcr_reset\n"); -- return PTR_ERR(wcss->wcss_q6_bcr_reset); -+ if (desc->bcr_reset_required) { -+ wcss->wcss_q6_bcr_reset = devm_reset_control_get_exclusive(dev, -+ "wcss_q6_bcr_reset"); -+ if (IS_ERR(wcss->wcss_q6_bcr_reset)) { -+ dev_err(wcss->dev, "unable to acquire wcss_q6_bcr_reset\n"); -+ return PTR_ERR(wcss->wcss_q6_bcr_reset); -+ } - } - - return 0; -@@ -929,9 +933,9 @@ static int q6v5_wcss_init_mmio(struct q6 - return -EINVAL; - } - -- wcss->halt_q6 = halt_reg[0]; -- wcss->halt_wcss = halt_reg[1]; -- wcss->halt_nc = halt_reg[2]; -+ wcss->halt_q6 = halt_reg[1]; -+ wcss->halt_wcss = halt_reg[2]; -+ wcss->halt_nc = halt_reg[3]; - - return 0; - } -@@ -1178,6 +1182,7 @@ static const struct wcss_data wcss_ipq80 - .crash_reason_smem = WCSS_CRASH_REASON, - .aon_reset_required = true, - .wcss_q6_reset_required = true, -+ .bcr_reset_required = false, - .ssr_name = "q6wcss", - .ops = &q6v5_wcss_ipq8074_ops, - .requires_force_stop = true, -@@ -1192,6 +1197,7 @@ static const struct wcss_data wcss_qcs40 - .version = WCSS_QCS404, - .aon_reset_required = false, - .wcss_q6_reset_required = false, -+ .bcr_reset_required = true, - .ssr_name = "mpss", - .sysmon_name = "wcnss", - .ssctl_id = 0x12, diff --git a/target/linux/ipq60xx/patches-5.15/0118-drivers-thermal-tsens-Add-support-for-combined-inter.patch b/target/linux/ipq60xx/patches-5.15/0118-drivers-thermal-tsens-Add-support-for-combined-inter.patch deleted file mode 100644 index 76704b40b..000000000 --- a/target/linux/ipq60xx/patches-5.15/0118-drivers-thermal-tsens-Add-support-for-combined-inter.patch +++ /dev/null @@ -1,138 +0,0 @@ -From 24a47e4619d90266188d26be04c0c29854294f06 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Thu, 28 Apr 2022 14:58:16 +0200 -Subject: [PATCH 118/137] drivers: thermal: tsens: Add support for combined - interrupt - -Despite using tsens v2.3 IP, IPQ8074 and IPQ6018 only have one IRQ for -signaling both up/low and critical trips. - -Signed-off-by: Robert Marko ---- -Changes in v7: -* Rebase to apply on next-20220818 - -Changes in v6: -* Check critical IRQ handler return, simplify up/low return ---- - drivers/thermal/qcom/tsens-8960.c | 1 + - drivers/thermal/qcom/tsens-v0_1.c | 1 + - drivers/thermal/qcom/tsens-v1.c | 1 + - drivers/thermal/qcom/tsens-v2.c | 1 + - drivers/thermal/qcom/tsens.c | 38 ++++++++++++++++++++++++++----- - drivers/thermal/qcom/tsens.h | 2 ++ - 6 files changed, 38 insertions(+), 6 deletions(-) - ---- a/drivers/thermal/qcom/tsens-8960.c -+++ b/drivers/thermal/qcom/tsens-8960.c -@@ -269,6 +269,7 @@ static const struct tsens_ops ops_8960 = - static struct tsens_features tsens_8960_feat = { - .ver_major = VER_0, - .crit_int = 0, -+ .combo_int = 0, - .adc = 1, - .srot_split = 0, - .max_sensors = 11, ---- a/drivers/thermal/qcom/tsens-v0_1.c -+++ b/drivers/thermal/qcom/tsens-v0_1.c -@@ -549,6 +549,7 @@ static int __init init_8939(struct tsens - static struct tsens_features tsens_v0_1_feat = { - .ver_major = VER_0_1, - .crit_int = 0, -+ .combo_int = 0, - .adc = 1, - .srot_split = 1, - .max_sensors = 11, ---- a/drivers/thermal/qcom/tsens-v1.c -+++ b/drivers/thermal/qcom/tsens-v1.c -@@ -273,6 +273,7 @@ static int calibrate_8976(struct tsens_p - static struct tsens_features tsens_v1_feat = { - .ver_major = VER_1_X, - .crit_int = 0, -+ .combo_int = 0, - .adc = 1, - .srot_split = 1, - .max_sensors = 11, ---- a/drivers/thermal/qcom/tsens-v2.c -+++ b/drivers/thermal/qcom/tsens-v2.c -@@ -31,6 +31,7 @@ - static struct tsens_features tsens_v2_feat = { - .ver_major = VER_2_X, - .crit_int = 1, -+ .combo_int = 0, - .adc = 0, - .srot_split = 1, - .max_sensors = 16, ---- a/drivers/thermal/qcom/tsens.c -+++ b/drivers/thermal/qcom/tsens.c -@@ -531,6 +531,27 @@ static irqreturn_t tsens_irq_thread(int - return IRQ_HANDLED; - } - -+/** -+ * tsens_combined_irq_thread - Threaded interrupt handler for combined interrupts -+ * @irq: irq number -+ * @data: tsens controller private data -+ * -+ * Handle the combined interrupt as if it were 2 separate interrupts, so call the -+ * critical handler first and then the up/low one. -+ * -+ * Return: IRQ_HANDLED -+ */ -+static irqreturn_t tsens_combined_irq_thread(int irq, void *data) -+{ -+ irqreturn_t ret; -+ -+ ret = tsens_critical_irq_thread(irq, data); -+ if (ret != IRQ_HANDLED) -+ return ret; -+ -+ return tsens_irq_thread(irq, data); -+} -+ - static int tsens_set_trips(void *_sensor, int low, int high) - { - struct tsens_sensor *s = _sensor; -@@ -1081,13 +1102,18 @@ static int tsens_register(struct tsens_p - tsens_mC_to_hw(priv->sensor, 0)); - } - -- ret = tsens_register_irq(priv, "uplow", tsens_irq_thread); -- if (ret < 0) -- return ret; -+ if (priv->feat->combo_int) { -+ ret = tsens_register_irq(priv, "combined", -+ tsens_combined_irq_thread); -+ } else { -+ ret = tsens_register_irq(priv, "uplow", tsens_irq_thread); -+ if (ret < 0) -+ return ret; - -- if (priv->feat->crit_int) -- ret = tsens_register_irq(priv, "critical", -- tsens_critical_irq_thread); -+ if (priv->feat->crit_int) -+ ret = tsens_register_irq(priv, "critical", -+ tsens_critical_irq_thread); -+ } - - return ret; - } ---- a/drivers/thermal/qcom/tsens.h -+++ b/drivers/thermal/qcom/tsens.h -@@ -495,6 +495,7 @@ enum regfield_ids { - * struct tsens_features - Features supported by the IP - * @ver_major: Major number of IP version - * @crit_int: does the IP support critical interrupts? -+ * @combo_int: does the IP use one IRQ for up, low and critical thresholds? - * @adc: do the sensors only output adc code (instead of temperature)? - * @srot_split: does the IP neatly splits the register space into SROT and TM, - * with SROT only being available to secure boot firmware? -@@ -504,6 +505,7 @@ enum regfield_ids { - struct tsens_features { - unsigned int ver_major; - unsigned int crit_int:1; -+ unsigned int combo_int:1; - unsigned int adc:1; - unsigned int srot_split:1; - unsigned int has_watchdog:1; diff --git a/target/linux/ipq60xx/patches-5.15/0119-drivers-thermal-tsens-allow-configuring-min-and-max-.patch b/target/linux/ipq60xx/patches-5.15/0119-drivers-thermal-tsens-allow-configuring-min-and-max-.patch deleted file mode 100644 index 4866b9e92..000000000 --- a/target/linux/ipq60xx/patches-5.15/0119-drivers-thermal-tsens-allow-configuring-min-and-max-.patch +++ /dev/null @@ -1,100 +0,0 @@ -From f035a370b770831f1c4a5d5b5b4387391ee3f71a Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Thu, 28 Apr 2022 19:06:29 +0200 -Subject: [PATCH 119/137] drivers: thermal: tsens: allow configuring min and - max trips - -IPQ8074 and IPQ6018 dont support negative trip temperatures and support -up to 204 degrees C as the max trip temperature. - -So, instead of always setting the -40 as min and 120 degrees C as max -allow it to be configured as part of the features. - -Signed-off-by: Robert Marko -Reviewed-by: Bjorn Andersson ---- - drivers/thermal/qcom/tsens-8960.c | 2 ++ - drivers/thermal/qcom/tsens-v0_1.c | 2 ++ - drivers/thermal/qcom/tsens-v1.c | 2 ++ - drivers/thermal/qcom/tsens-v2.c | 2 ++ - drivers/thermal/qcom/tsens.c | 4 ++-- - drivers/thermal/qcom/tsens.h | 4 ++++ - 6 files changed, 14 insertions(+), 2 deletions(-) - ---- a/drivers/thermal/qcom/tsens-8960.c -+++ b/drivers/thermal/qcom/tsens-8960.c -@@ -273,6 +273,8 @@ static struct tsens_features tsens_8960_ - .adc = 1, - .srot_split = 0, - .max_sensors = 11, -+ .trip_min_temp = -40000, -+ .trip_max_temp = 120000, - }; - - struct tsens_plat_data data_8960 = { ---- a/drivers/thermal/qcom/tsens-v0_1.c -+++ b/drivers/thermal/qcom/tsens-v0_1.c -@@ -553,6 +553,8 @@ static struct tsens_features tsens_v0_1_ - .adc = 1, - .srot_split = 1, - .max_sensors = 11, -+ .trip_min_temp = -40000, -+ .trip_max_temp = 120000, - }; - - static const struct reg_field tsens_v0_1_regfields[MAX_REGFIELDS] = { ---- a/drivers/thermal/qcom/tsens-v1.c -+++ b/drivers/thermal/qcom/tsens-v1.c -@@ -277,6 +277,8 @@ static struct tsens_features tsens_v1_fe - .adc = 1, - .srot_split = 1, - .max_sensors = 11, -+ .trip_min_temp = -40000, -+ .trip_max_temp = 120000, - }; - - static const struct reg_field tsens_v1_regfields[MAX_REGFIELDS] = { ---- a/drivers/thermal/qcom/tsens-v2.c -+++ b/drivers/thermal/qcom/tsens-v2.c -@@ -35,6 +35,8 @@ static struct tsens_features tsens_v2_fe - .adc = 0, - .srot_split = 1, - .max_sensors = 16, -+ .trip_min_temp = -40000, -+ .trip_max_temp = 120000, - }; - - static const struct reg_field tsens_v2_regfields[MAX_REGFIELDS] = { ---- a/drivers/thermal/qcom/tsens.c -+++ b/drivers/thermal/qcom/tsens.c -@@ -572,8 +572,8 @@ static int tsens_set_trips(void *_sensor - dev_dbg(dev, "[%u] %s: proposed thresholds: (%d:%d)\n", - hw_id, __func__, low, high); - -- cl_high = clamp_val(high, -40000, 120000); -- cl_low = clamp_val(low, -40000, 120000); -+ cl_high = clamp_val(high, priv->feat->trip_min_temp, priv->feat->trip_max_temp); -+ cl_low = clamp_val(low, priv->feat->trip_min_temp, priv->feat->trip_max_temp); - - high_val = tsens_mC_to_hw(s, cl_high); - low_val = tsens_mC_to_hw(s, cl_low); ---- a/drivers/thermal/qcom/tsens.h -+++ b/drivers/thermal/qcom/tsens.h -@@ -501,6 +501,8 @@ enum regfield_ids { - * with SROT only being available to secure boot firmware? - * @has_watchdog: does this IP support watchdog functionality? - * @max_sensors: maximum sensors supported by this version of the IP -+ * @trip_min_temp: minimum trip temperature supported by this version of the IP -+ * @trip_max_temp: maximum trip temperature supported by this version of the IP - */ - struct tsens_features { - unsigned int ver_major; -@@ -510,6 +512,8 @@ struct tsens_features { - unsigned int srot_split:1; - unsigned int has_watchdog:1; - unsigned int max_sensors; -+ int trip_min_temp; -+ int trip_max_temp; - }; - - /** diff --git a/target/linux/ipq60xx/patches-5.15/0120-drivers-thermal-tsens-add-IPQ8074-support.patch b/target/linux/ipq60xx/patches-5.15/0120-drivers-thermal-tsens-add-IPQ8074-support.patch deleted file mode 100644 index 8f65dfaf0..000000000 --- a/target/linux/ipq60xx/patches-5.15/0120-drivers-thermal-tsens-add-IPQ8074-support.patch +++ /dev/null @@ -1,72 +0,0 @@ -From ffc91d0fc802e58f44c7f888f44643847b6dfa3a Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Thu, 28 Apr 2022 20:26:13 +0200 -Subject: [PATCH 120/137] drivers: thermal: tsens: add IPQ8074 support - -Qualcomm IPQ8074 uses tsens v2.3 IP, however unlike other tsens v2 IP -it only has one IRQ, that is used for up/low as well as critical. -It also does not support negative trip temperatures. - -Signed-off-by: Robert Marko -Reviewed-by: Bjorn Andersson ---- - drivers/thermal/qcom/tsens-v2.c | 17 +++++++++++++++++ - drivers/thermal/qcom/tsens.c | 3 +++ - drivers/thermal/qcom/tsens.h | 2 +- - 3 files changed, 21 insertions(+), 1 deletion(-) - ---- a/drivers/thermal/qcom/tsens-v2.c -+++ b/drivers/thermal/qcom/tsens-v2.c -@@ -39,6 +39,17 @@ static struct tsens_features tsens_v2_fe - .trip_max_temp = 120000, - }; - -+static struct tsens_features ipq8074_feat = { -+ .ver_major = VER_2_X, -+ .crit_int = 1, -+ .combo_int = 1, -+ .adc = 0, -+ .srot_split = 1, -+ .max_sensors = 16, -+ .trip_min_temp = 0, -+ .trip_max_temp = 204000, -+}; -+ - static const struct reg_field tsens_v2_regfields[MAX_REGFIELDS] = { - /* ----- SROT ------ */ - /* VERSION */ -@@ -104,6 +115,12 @@ struct tsens_plat_data data_tsens_v2 = { - .fields = tsens_v2_regfields, - }; - -+struct tsens_plat_data data_ipq8074 = { -+ .ops = &ops_generic_v2, -+ .feat = &ipq8074_feat, -+ .fields = tsens_v2_regfields, -+}; -+ - /* Kept around for backward compatibility with old msm8996.dtsi */ - struct tsens_plat_data data_8996 = { - .num_sensors = 13, ---- a/drivers/thermal/qcom/tsens.c -+++ b/drivers/thermal/qcom/tsens.c -@@ -991,6 +991,9 @@ static const struct of_device_id tsens_t - .compatible = "qcom,ipq8064-tsens", - .data = &data_8960, - }, { -+ .compatible = "qcom,ipq8074-tsens", -+ .data = &data_ipq8074, -+ }, { - .compatible = "qcom,mdm9607-tsens", - .data = &data_9607, - }, { ---- a/drivers/thermal/qcom/tsens.h -+++ b/drivers/thermal/qcom/tsens.h -@@ -599,6 +599,6 @@ extern struct tsens_plat_data data_8916, - extern struct tsens_plat_data data_tsens_v1, data_8976, data_8956; - - /* TSENS v2 targets */ --extern struct tsens_plat_data data_8996, data_tsens_v2; -+extern struct tsens_plat_data data_8996, data_ipq8074, data_tsens_v2; - - #endif /* __QCOM_TSENS_H__ */ diff --git a/target/linux/ipq60xx/patches-5.15/0121-arm64-dts-ipq8074-add-thermal-nodes.patch b/target/linux/ipq60xx/patches-5.15/0121-arm64-dts-ipq8074-add-thermal-nodes.patch deleted file mode 100644 index b2e94d2b4..000000000 --- a/target/linux/ipq60xx/patches-5.15/0121-arm64-dts-ipq8074-add-thermal-nodes.patch +++ /dev/null @@ -1,131 +0,0 @@ -From 1cdc1eaed3ea5b2cab82dee4c72c3cea23356ca6 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Fri, 24 Dec 2021 20:33:59 +0100 -Subject: [PATCH 121/137] arm64: dts: ipq8074: add thermal nodes - -IPQ8074 has a tsens v2.3.0 peripheral which monitors -temperatures around the various subsystems on the -die. - -So lets add the tsens and thermal zone nodes, passive -CPU cooling will come in later patches after CPU frequency -scaling is supported. - -Signed-off-by: Robert Marko ---- -Changes in v5: -* Rebase to apply on next-20220708 ---- - arch/arm64/boot/dts/qcom/ipq8074.dtsi | 96 +++++++++++++++++++++++++++ - 1 file changed, 96 insertions(+) - ---- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -309,6 +309,16 @@ - status = "disabled"; - }; - -+ tsens: thermal-sensor@4a9000 { -+ compatible = "qcom,ipq8074-tsens"; -+ reg = <0x4a9000 0x1000>, /* TM */ -+ <0x4a8000 0x1000>; /* SROT */ -+ interrupts = ; -+ interrupt-names = "combined"; -+ #qcom,sensors = <16>; -+ #thermal-sensor-cells = <1>; -+ }; -+ - cryptobam: dma-controller@704000 { - compatible = "qcom,bam-v1.7.0"; - reg = <0x00704000 0x20000>; -@@ -910,4 +920,90 @@ - , - ; - }; -+ -+ thermal-zones { -+ nss-top-thermal { -+ polling-delay-passive = <250>; -+ polling-delay = <1000>; -+ -+ thermal-sensors = <&tsens 4>; -+ }; -+ -+ nss0-thermal { -+ polling-delay-passive = <250>; -+ polling-delay = <1000>; -+ -+ thermal-sensors = <&tsens 5>; -+ }; -+ -+ nss1-thermal { -+ polling-delay-passive = <250>; -+ polling-delay = <1000>; -+ -+ thermal-sensors = <&tsens 6>; -+ }; -+ -+ wcss-phya0-thermal { -+ polling-delay-passive = <250>; -+ polling-delay = <1000>; -+ -+ thermal-sensors = <&tsens 7>; -+ }; -+ -+ wcss-phya1-thermal { -+ polling-delay-passive = <250>; -+ polling-delay = <1000>; -+ -+ thermal-sensors = <&tsens 8>; -+ }; -+ -+ cpu0_thermal: cpu0-thermal { -+ polling-delay-passive = <250>; -+ polling-delay = <1000>; -+ -+ thermal-sensors = <&tsens 9>; -+ }; -+ -+ cpu1_thermal: cpu1-thermal { -+ polling-delay-passive = <250>; -+ polling-delay = <1000>; -+ -+ thermal-sensors = <&tsens 10>; -+ }; -+ -+ cpu2_thermal: cpu2-thermal { -+ polling-delay-passive = <250>; -+ polling-delay = <1000>; -+ -+ thermal-sensors = <&tsens 11>; -+ }; -+ -+ cpu3_thermal: cpu3-thermal { -+ polling-delay-passive = <250>; -+ polling-delay = <1000>; -+ -+ thermal-sensors = <&tsens 12>; -+ }; -+ -+ cluster_thermal: cluster-thermal { -+ polling-delay-passive = <250>; -+ polling-delay = <1000>; -+ -+ thermal-sensors = <&tsens 13>; -+ }; -+ -+ wcss-phyb0-thermal { -+ polling-delay-passive = <250>; -+ polling-delay = <1000>; -+ -+ thermal-sensors = <&tsens 14>; -+ }; -+ -+ wcss-phyb1-thermal { -+ polling-delay-passive = <250>; -+ polling-delay = <1000>; -+ -+ thermal-sensors = <&tsens 15>; -+ }; -+ }; - }; diff --git a/target/linux/ipq60xx/patches-5.15/0122-mfd-qcom-spmi-pmic-add-support-for-PMP8074.patch b/target/linux/ipq60xx/patches-5.15/0122-mfd-qcom-spmi-pmic-add-support-for-PMP8074.patch deleted file mode 100644 index 07a31af89..000000000 --- a/target/linux/ipq60xx/patches-5.15/0122-mfd-qcom-spmi-pmic-add-support-for-PMP8074.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 0d176e7d075fb7deeb1b137fec56304a402f2f25 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Thu, 19 May 2022 14:51:53 +0200 -Subject: [PATCH 122/137] mfd: qcom-spmi-pmic: add support for PMP8074 - -Add support for PMP8074 PMIC which is a companion PMIC for the Qualcomm -IPQ8074 SoC-s. - -It shares the same subtype identifier as PM8901. - -Signed-off-by: Robert Marko ---- - drivers/mfd/qcom-spmi-pmic.c | 1 + - 1 file changed, 1 insertion(+) - ---- a/drivers/mfd/qcom-spmi-pmic.c -+++ b/drivers/mfd/qcom-spmi-pmic.c -@@ -76,6 +76,7 @@ static const struct of_device_id pmic_sp - { .compatible = "qcom,pmi8994", .data = (void *)PMI8994_SUBTYPE }, - { .compatible = "qcom,pmi8998", .data = (void *)PMI8998_SUBTYPE }, - { .compatible = "qcom,pmk8002", .data = (void *)PMK8002_SUBTYPE }, -+ { .compatible = "qcom,pmp8074", .data = (void *)PM8901_SUBTYPE }, - { .compatible = "qcom,smb2351", .data = (void *)SMB2351_SUBTYPE }, - { .compatible = "qcom,spmi-pmic", .data = (void *)COMMON_SUBTYPE }, - { } diff --git a/target/linux/ipq60xx/patches-5.15/0123-arm64-dts-qcom-add-PMP8074-DTSI.patch b/target/linux/ipq60xx/patches-5.15/0123-arm64-dts-qcom-add-PMP8074-DTSI.patch deleted file mode 100644 index 8c2c68616..000000000 --- a/target/linux/ipq60xx/patches-5.15/0123-arm64-dts-qcom-add-PMP8074-DTSI.patch +++ /dev/null @@ -1,158 +0,0 @@ -From 2abf33c722b4ade9438dc91a652f294ada68a50e Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Wed, 18 May 2022 16:36:42 +0200 -Subject: [PATCH 123/137] arm64: dts: qcom: add PMP8074 DTSI - -PMP8074 is a companion PMIC to the Qualcomm IPQ8074 series that is -controlled via SPMI. - -Add DTSI for it providing GPIO, regulator, RTC and VADC support. - -RTC is disabled by default as there is no built-in battery so it will -loose time unless board vendor added a battery, so make it optional. - -Signed-off-by: Robert Marko ---- -Changes in v7: -* Dual license with BSD-3-Clause -* Use "-" instead of underscores in node names - -Changes in v6: -* Add RTC and GPIO nodes - -Changes in v5: -* Remove #address-cells and #size-cells as they are not required for -regulator subnodes ---- - arch/arm64/boot/dts/qcom/pmp8074.dtsi | 125 ++++++++++++++++++++++++++ - 1 file changed, 125 insertions(+) - create mode 100644 arch/arm64/boot/dts/qcom/pmp8074.dtsi - ---- /dev/null -+++ b/arch/arm64/boot/dts/qcom/pmp8074.dtsi -@@ -0,0 +1,125 @@ -+// SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause -+ -+#include -+#include -+ -+&spmi_bus { -+ pmic@0 { -+ compatible = "qcom,pmp8074", "qcom,spmi-pmic"; -+ reg = <0x0 SPMI_USID>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ pmp8074_adc: adc@3100 { -+ compatible = "qcom,spmi-adc-rev2"; -+ reg = <0x3100>; -+ interrupts = <0x0 0x31 0x0 IRQ_TYPE_EDGE_RISING>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ #io-channel-cells = <1>; -+ -+ ref-gnd@0 { -+ reg = ; -+ qcom,pre-scaling = <1 1>; -+ }; -+ -+ vref-1p25@1 { -+ reg = ; -+ qcom,pre-scaling = <1 1>; -+ }; -+ -+ vref-vadc@2 { -+ reg = ; -+ qcom,pre-scaling = <1 1>; -+ }; -+ -+ pmic_die: die-temp@6 { -+ reg = ; -+ qcom,pre-scaling = <1 1>; -+ }; -+ -+ xo_therm: xo-temp@76 { -+ reg = ; -+ qcom,ratiometric; -+ qcom,hw-settle-time = <200>; -+ qcom,pre-scaling = <1 1>; -+ }; -+ -+ pa_therm1: thermistor1@77 { -+ reg = ; -+ qcom,ratiometric; -+ qcom,hw-settle-time = <200>; -+ qcom,pre-scaling = <1 1>; -+ }; -+ -+ pa_therm2: thermistor2@78 { -+ reg = ; -+ qcom,ratiometric; -+ qcom,hw-settle-time = <200>; -+ qcom,pre-scaling = <1 1>; -+ }; -+ -+ pa_therm3: thermistor3@79 { -+ reg = ; -+ qcom,ratiometric; -+ qcom,hw-settle-time = <200>; -+ qcom,pre-scaling = <1 1>; -+ }; -+ -+ vph-pwr@131 { -+ reg = ; -+ qcom,pre-scaling = <1 3>; -+ }; -+ }; -+ -+ pmp8074_rtc: rtc@6000 { -+ compatible = "qcom,pm8941-rtc"; -+ reg = <0x6000>; -+ reg-names = "rtc", "alarm"; -+ interrupts = <0x0 0x61 0x1 IRQ_TYPE_NONE>; -+ allow-set-time; -+ status = "disabled"; -+ }; -+ -+ pmp8074_gpios: gpio@c000 { -+ compatible = "qcom,pmp8074-gpio", "qcom,spmi-gpio"; -+ reg = <0xc000>; -+ gpio-controller; -+ #gpio-cells = <2>; -+ gpio-ranges = <&pmp8074_gpios 0 0 12>; -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ }; -+ }; -+ -+ pmic@1 { -+ compatible = "qcom,pmp8074", "qcom,spmi-pmic"; -+ reg = <0x1 SPMI_USID>; -+ -+ regulators { -+ compatible = "qcom,pmp8074-regulators"; -+ -+ s3: s3 { -+ regulator-name = "vdd_s3"; -+ regulator-min-microvolt = <592000>; -+ regulator-max-microvolt = <1064000>; -+ regulator-always-on; -+ regulator-boot-on; -+ }; -+ -+ s4: s4 { -+ regulator-name = "vdd_s4"; -+ regulator-min-microvolt = <712000>; -+ regulator-max-microvolt = <992000>; -+ regulator-always-on; -+ regulator-boot-on; -+ }; -+ -+ l11: l11 { -+ regulator-name = "l11"; -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <3300000>; -+ }; -+ }; -+ }; -+}; diff --git a/target/linux/ipq60xx/patches-5.15/0124-arm64-dts-qcom-ipq8074-hk01-add-VQMMC-supply.patch b/target/linux/ipq60xx/patches-5.15/0124-arm64-dts-qcom-ipq8074-hk01-add-VQMMC-supply.patch deleted file mode 100644 index 0d1aea992..000000000 --- a/target/linux/ipq60xx/patches-5.15/0124-arm64-dts-qcom-ipq8074-hk01-add-VQMMC-supply.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 89f8d101005ee40b3a6c689ba1765403d3617672 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Thu, 19 May 2022 13:34:03 +0200 -Subject: [PATCH 124/137] arm64: dts: qcom: ipq8074-hk01: add VQMMC supply - -Since now we have control over the PMP8074 PMIC providing various system -voltages including L11 which provides the SDIO/eMMC I/O voltage set it as -the SDHCI VQMMC supply. - -This allows SDHCI controller to switch to 1.8V I/O mode and support high -speed modes like HS200 and HS400. - -Signed-off-by: Robert Marko ---- - arch/arm64/boot/dts/qcom/ipq8074-hk01.dts | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/arch/arm64/boot/dts/qcom/ipq8074-hk01.dts -+++ b/arch/arm64/boot/dts/qcom/ipq8074-hk01.dts -@@ -3,6 +3,7 @@ - /* Copyright (c) 2017, The Linux Foundation. All rights reserved. - */ - #include "ipq8074.dtsi" -+#include "pmp8074.dtsi" - - / { - model = "Qualcomm Technologies, Inc. IPQ8074-HK01"; -@@ -82,6 +83,7 @@ - - &sdhc_1 { - status = "okay"; -+ vqmmc-supply = <&l11>; - }; - - &qusb_phy_0 { diff --git a/target/linux/ipq60xx/patches-5.15/0125-arm64-dts-ipq8074-add-CPU-clock.patch b/target/linux/ipq60xx/patches-5.15/0125-arm64-dts-ipq8074-add-CPU-clock.patch deleted file mode 100644 index 29d0b3890..000000000 --- a/target/linux/ipq60xx/patches-5.15/0125-arm64-dts-ipq8074-add-CPU-clock.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 7b7941649605363d0eebc9fdfb84a13a95522cfb Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Fri, 31 Dec 2021 17:56:14 +0100 -Subject: [PATCH 125/137] arm64: dts: ipq8074: add CPU clock - -Now that CPU clock is exposed and can be controlled, add the necessary -properties to the CPU nodes. - -Signed-off-by: Robert Marko ---- - arch/arm64/boot/dts/qcom/ipq8074.dtsi | 9 +++++++++ - 1 file changed, 9 insertions(+) - ---- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -5,6 +5,7 @@ - - #include - #include -+#include - - / { - #address-cells = <2>; -@@ -38,6 +39,8 @@ - reg = <0x0>; - next-level-cache = <&L2_0>; - enable-method = "psci"; -+ clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>; -+ clock-names = "cpu"; - }; - - CPU1: cpu@1 { -@@ -46,6 +49,8 @@ - enable-method = "psci"; - reg = <0x1>; - next-level-cache = <&L2_0>; -+ clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>; -+ clock-names = "cpu"; - }; - - CPU2: cpu@2 { -@@ -54,6 +59,8 @@ - enable-method = "psci"; - reg = <0x2>; - next-level-cache = <&L2_0>; -+ clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>; -+ clock-names = "cpu"; - }; - - CPU3: cpu@3 { -@@ -62,6 +69,8 @@ - enable-method = "psci"; - reg = <0x3>; - next-level-cache = <&L2_0>; -+ clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>; -+ clock-names = "cpu"; - }; - - L2_0: l2-cache { diff --git a/target/linux/ipq60xx/patches-5.15/0126-arm64-dts-ipq8074-add-label-to-cpus.patch b/target/linux/ipq60xx/patches-5.15/0126-arm64-dts-ipq8074-add-label-to-cpus.patch deleted file mode 100644 index 45a560ee0..000000000 --- a/target/linux/ipq60xx/patches-5.15/0126-arm64-dts-ipq8074-add-label-to-cpus.patch +++ /dev/null @@ -1,25 +0,0 @@ -From ff74c990c4b671f17d0dfc2c93bae9e23b017472 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Fri, 31 Dec 2021 18:42:53 +0100 -Subject: [PATCH 126/137] arm64: dts: ipq8074: add label to cpus - -Add label to cpus node as that makes it easy to add OPP table in SoC model -specific DTSI as IPQ8074 family has differing clocks and voltages based on -the specific model. - -Signed-off-by: Robert Marko ---- - arch/arm64/boot/dts/qcom/ipq8074.dtsi | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -29,7 +29,7 @@ - }; - }; - -- cpus { -+ cpus: cpus { - #address-cells = <0x1>; - #size-cells = <0x0>; - diff --git a/target/linux/ipq60xx/patches-5.15/0127-arm64-dts-ipq8074-add-cooling-cells-to-CPU-nodes.patch b/target/linux/ipq60xx/patches-5.15/0127-arm64-dts-ipq8074-add-cooling-cells-to-CPU-nodes.patch deleted file mode 100644 index b49e1b8df..000000000 --- a/target/linux/ipq60xx/patches-5.15/0127-arm64-dts-ipq8074-add-cooling-cells-to-CPU-nodes.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 8ddd2743d7bd30165b0c5e1abb6990da15c181d4 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Fri, 31 Dec 2021 20:38:06 +0100 -Subject: [PATCH 127/137] arm64: dts: ipq8074: add cooling cells to CPU nodes - -Since there is CPU Freq support as well as thermal sensor support -now for the IPQ8074, add cooling cells to CPU nodes so that they can -be used as cooling devices using CPU Freq. - -Signed-off-by: Robert Marko ---- - arch/arm64/boot/dts/qcom/ipq8074.dtsi | 4 ++++ - 1 file changed, 4 insertions(+) - ---- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -41,6 +41,7 @@ - enable-method = "psci"; - clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>; - clock-names = "cpu"; -+ #cooling-cells = <2>; - }; - - CPU1: cpu@1 { -@@ -51,6 +52,7 @@ - next-level-cache = <&L2_0>; - clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>; - clock-names = "cpu"; -+ #cooling-cells = <2>; - }; - - CPU2: cpu@2 { -@@ -61,6 +63,7 @@ - next-level-cache = <&L2_0>; - clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>; - clock-names = "cpu"; -+ #cooling-cells = <2>; - }; - - CPU3: cpu@3 { -@@ -71,6 +74,7 @@ - next-level-cache = <&L2_0>; - clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>; - clock-names = "cpu"; -+ #cooling-cells = <2>; - }; - - L2_0: l2-cache { diff --git a/target/linux/ipq60xx/patches-5.15/0128-dt-bindings-clock-qcom-Add-reset-for-WCSSAON.patch b/target/linux/ipq60xx/patches-5.15/0128-dt-bindings-clock-qcom-Add-reset-for-WCSSAON.patch deleted file mode 100644 index b91b7565d..000000000 --- a/target/linux/ipq60xx/patches-5.15/0128-dt-bindings-clock-qcom-Add-reset-for-WCSSAON.patch +++ /dev/null @@ -1,26 +0,0 @@ -From aa0c4a764d290cceba0a27fd5d81b30b54c5c81f Mon Sep 17 00:00:00 2001 -From: Gokul Sriram Palanisamy -Date: Sat, 30 Jan 2021 10:50:10 +0530 -Subject: [PATCH 128/137] dt-bindings: clock: qcom: Add reset for WCSSAON - -Add binding for WCSSAON reset required for Q6v5 reset on IPQ8074 SoC. - -Signed-off-by: Gokul Sriram Palanisamy -Signed-off-by: Sricharan R -Signed-off-by: Nikhil Prakash V -Acked-by: Rob Herring -Acked-by: Stephen Boyd ---- - include/dt-bindings/clock/qcom,gcc-ipq8074.h | 1 + - 1 file changed, 1 insertion(+) - ---- a/include/dt-bindings/clock/qcom,gcc-ipq8074.h -+++ b/include/dt-bindings/clock/qcom,gcc-ipq8074.h -@@ -367,6 +367,7 @@ - #define GCC_PCIE1_AHB_ARES 129 - #define GCC_PCIE1_AXI_MASTER_STICKY_ARES 130 - #define GCC_PCIE0_AXI_SLAVE_STICKY_ARES 131 -+#define GCC_WCSSAON_RESET 132 - - #define USB0_GDSC 0 - #define USB1_GDSC 1 diff --git a/target/linux/ipq60xx/patches-5.15/0129-clk-qcom-Add-WCSSAON-reset.patch b/target/linux/ipq60xx/patches-5.15/0129-clk-qcom-Add-WCSSAON-reset.patch deleted file mode 100644 index 45ebea230..000000000 --- a/target/linux/ipq60xx/patches-5.15/0129-clk-qcom-Add-WCSSAON-reset.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 1377fc72a67c8684237fa9b1f246257fd073b2b1 Mon Sep 17 00:00:00 2001 -From: Gokul Sriram Palanisamy -Date: Sat, 30 Jan 2021 10:50:11 +0530 -Subject: [PATCH 129/137] clk: qcom: Add WCSSAON reset - -Add WCSSAON reset required for Q6v5 on IPQ8074 SoC. - -Signed-off-by: Gokul Sriram Palanisamy -Signed-off-by: Sricharan R -Signed-off-by: Nikhil Prakash V -Acked-by: Stephen Boyd ---- - drivers/clk/qcom/gcc-ipq8074.c | 1 + - 1 file changed, 1 insertion(+) - ---- a/drivers/clk/qcom/gcc-ipq8074.c -+++ b/drivers/clk/qcom/gcc-ipq8074.c -@@ -4820,6 +4820,7 @@ static const struct qcom_reset_map gcc_i - [GCC_PCIE1_AXI_SLAVE_ARES] = { 0x76040, 4 }, - [GCC_PCIE1_AHB_ARES] = { 0x76040, 5 }, - [GCC_PCIE1_AXI_MASTER_STICKY_ARES] = { 0x76040, 6 }, -+ [GCC_WCSSAON_RESET] = { 0x59010, 0 }, - }; - - static struct gdsc *gcc_ipq8074_gdscs[] = { diff --git a/target/linux/ipq60xx/patches-5.15/0130-remoteproc-wcss-disable-auto-boot-for-IPQ8074.patch b/target/linux/ipq60xx/patches-5.15/0130-remoteproc-wcss-disable-auto-boot-for-IPQ8074.patch deleted file mode 100644 index 773b53090..000000000 --- a/target/linux/ipq60xx/patches-5.15/0130-remoteproc-wcss-disable-auto-boot-for-IPQ8074.patch +++ /dev/null @@ -1,47 +0,0 @@ -From d9965ec6f02f71609d837d33d4bae20fb7dec1fd Mon Sep 17 00:00:00 2001 -From: Sivaprakash Murugesan -Date: Fri, 17 Apr 2020 16:37:10 +0530 -Subject: [PATCH 130/137] remoteproc: wcss: disable auto boot for IPQ8074 - -auto boot is disabled for IPQ8074 the wifi driver brings up the wcss. - -Signed-off-by: Sivaprakash Murugesan -Change-Id: Ia82edb7ee52f2bd010c099f151179d69a953ac88 ---- - drivers/remoteproc/qcom_q6v5_wcss.c | 4 ++++ - 1 file changed, 4 insertions(+) - ---- a/drivers/remoteproc/qcom_q6v5_wcss.c -+++ b/drivers/remoteproc/qcom_q6v5_wcss.c -@@ -161,6 +161,7 @@ struct wcss_data { - const struct rproc_ops *ops; - bool requires_force_stop; - bool need_mem_protection; -+ bool need_auto_boot; - }; - - static int q6v5_wcss_reset(struct q6v5_wcss *wcss) -@@ -1151,6 +1152,7 @@ static int q6v5_wcss_probe(struct platfo - desc->sysmon_name, - desc->ssctl_id); - -+ rproc->auto_boot = desc->need_auto_boot; - ret = rproc_add(rproc); - if (ret) - goto free_rproc; -@@ -1187,6 +1189,7 @@ static const struct wcss_data wcss_ipq80 - .ops = &q6v5_wcss_ipq8074_ops, - .requires_force_stop = true, - .need_mem_protection = true, -+ .need_auto_boot = false, - }; - - static const struct wcss_data wcss_qcs404_res_init = { -@@ -1203,6 +1206,7 @@ static const struct wcss_data wcss_qcs40 - .ssctl_id = 0x12, - .ops = &q6v5_wcss_qcs404_ops, - .requires_force_stop = false, -+ .need_auto_boot = true, - }; - - static const struct of_device_id q6v5_wcss_of_match[] = { diff --git a/target/linux/ipq60xx/patches-5.15/0131-arm64-dts-qcom-Enable-Q6v5-WCSS-for-ipq8074-SoC.patch b/target/linux/ipq60xx/patches-5.15/0131-arm64-dts-qcom-Enable-Q6v5-WCSS-for-ipq8074-SoC.patch deleted file mode 100644 index 54d202200..000000000 --- a/target/linux/ipq60xx/patches-5.15/0131-arm64-dts-qcom-Enable-Q6v5-WCSS-for-ipq8074-SoC.patch +++ /dev/null @@ -1,120 +0,0 @@ -From 45dfcd1ecf0910e4e45fec5f26f2fc80a47732f9 Mon Sep 17 00:00:00 2001 -From: Gokul Sriram Palanisamy -Date: Sat, 30 Jan 2021 10:50:13 +0530 -Subject: [PATCH 131/137] arm64: dts: qcom: Enable Q6v5 WCSS for ipq8074 SoC - -Enable remoteproc WCSS PIL driver with glink and ssr subdevices. -Also enables smp2p and mailboxes required for IPC. - -Signed-off-by: Gokul Sriram Palanisamy -Signed-off-by: Sricharan R -Signed-off-by: Nikhil Prakash V -Signed-off-by: Robert Marko ---- - arch/arm64/boot/dts/qcom/ipq8074.dtsi | 81 +++++++++++++++++++++++++++ - 1 file changed, 81 insertions(+) - ---- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -153,6 +153,32 @@ - }; - }; - -+ wcss: smp2p-wcss { -+ compatible = "qcom,smp2p"; -+ qcom,smem = <435>, <428>; -+ -+ interrupt-parent = <&intc>; -+ interrupts = <0 322 1>; -+ -+ mboxes = <&apcs_glb 9>; -+ -+ qcom,local-pid = <0>; -+ qcom,remote-pid = <1>; -+ -+ wcss_smp2p_out: master-kernel { -+ qcom,entry-name = "master-kernel"; -+ qcom,smp2p-feature-ssr-ack; -+ #qcom,smem-state-cells = <1>; -+ }; -+ -+ wcss_smp2p_in: slave-kernel { -+ qcom,entry-name = "slave-kernel"; -+ -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ }; -+ }; -+ - soc: soc { - #address-cells = <0x1>; - #size-cells = <0x1>; -@@ -420,6 +446,11 @@ - #hwlock-cells = <1>; - }; - -+ tcsr_q6: syscon@1945000 { -+ compatible = "syscon"; -+ reg = <0x01945000 0xe000>; -+ }; -+ - spmi_bus: spmi@200f000 { - compatible = "qcom,spmi-pmic-arb"; - reg = <0x0200f000 0x001000>, -@@ -924,6 +955,56 @@ - "axi_s_sticky"; - status = "disabled"; - }; -+ -+ q6v5_wcss: q6v5_wcss@cd00000 { -+ compatible = "qcom,ipq8074-wcss-pil"; -+ reg = <0x0cd00000 0x4040>, -+ <0x004ab000 0x20>; -+ reg-names = "qdsp6", -+ "rmb"; -+ qca,auto-restart; -+ qca,extended-intc; -+ interrupts-extended = <&intc 0 325 1>, -+ <&wcss_smp2p_in 0 0>, -+ <&wcss_smp2p_in 1 0>, -+ <&wcss_smp2p_in 2 0>, -+ <&wcss_smp2p_in 3 0>; -+ interrupt-names = "wdog", -+ "fatal", -+ "ready", -+ "handover", -+ "stop-ack"; -+ -+ resets = <&gcc GCC_WCSSAON_RESET>, -+ <&gcc GCC_WCSS_BCR>, -+ <&gcc GCC_WCSS_Q6_BCR>; -+ -+ reset-names = "wcss_aon_reset", -+ "wcss_reset", -+ "wcss_q6_reset"; -+ -+ clocks = <&gcc GCC_PRNG_AHB_CLK>; -+ clock-names = "prng"; -+ -+ qcom,halt-regs = <&tcsr_q6 0xa000 0xd000 0x0>; -+ -+ qcom,smem-states = <&wcss_smp2p_out 0>, -+ <&wcss_smp2p_out 1>; -+ qcom,smem-state-names = "shutdown", -+ "stop"; -+ -+ memory-region = <&q6_region>; -+ -+ glink-edge { -+ interrupts = ; -+ qcom,remote-pid = <1>; -+ mboxes = <&apcs_glb 8>; -+ -+ rpm_requests { -+ qcom,glink-channels = "IPCRTR"; -+ }; -+ }; -+ }; - }; - - timer { diff --git a/target/linux/ipq60xx/patches-5.15/0132-arm64-dts-ipq8074-Add-WLAN-node.patch b/target/linux/ipq60xx/patches-5.15/0132-arm64-dts-ipq8074-Add-WLAN-node.patch deleted file mode 100644 index 1548f1157..000000000 --- a/target/linux/ipq60xx/patches-5.15/0132-arm64-dts-ipq8074-Add-WLAN-node.patch +++ /dev/null @@ -1,135 +0,0 @@ -From d8e8adbf99ed4a3b50f87a665661a8cad84918ff Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Tue, 21 Dec 2021 14:49:36 +0100 -Subject: [PATCH 132/137] arm64: dts: ipq8074: Add WLAN node - -IPQ8074 has a AHB based Q6v5 802.11ax radios that are supported -by the ath11k. - -Add the required DT node to enable the built-in radios. - -Signed-off-by: Robert Marko ---- - arch/arm64/boot/dts/qcom/ipq8074.dtsi | 111 ++++++++++++++++++++++++++ - 1 file changed, 111 insertions(+) - ---- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -1005,6 +1005,117 @@ - }; - }; - }; -+ -+ wifi: wifi@c0000000 { -+ compatible = "qcom,ipq8074-wifi"; -+ reg = <0xc000000 0x2000000>; -+ -+ interrupts = , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ ; -+ -+ interrupt-names = "misc-pulse1", -+ "misc-latch", -+ "sw-exception", -+ "ce0", -+ "ce1", -+ "ce2", -+ "ce3", -+ "ce4", -+ "ce5", -+ "ce6", -+ "ce7", -+ "ce8", -+ "ce9", -+ "ce10", -+ "ce11", -+ "host2wbm-desc-feed", -+ "host2reo-re-injection", -+ "host2reo-command", -+ "host2rxdma-monitor-ring3", -+ "host2rxdma-monitor-ring2", -+ "host2rxdma-monitor-ring1", -+ "reo2ost-exception", -+ "wbm2host-rx-release", -+ "reo2host-status", -+ "reo2host-destination-ring4", -+ "reo2host-destination-ring3", -+ "reo2host-destination-ring2", -+ "reo2host-destination-ring1", -+ "rxdma2host-monitor-destination-mac3", -+ "rxdma2host-monitor-destination-mac2", -+ "rxdma2host-monitor-destination-mac1", -+ "ppdu-end-interrupts-mac3", -+ "ppdu-end-interrupts-mac2", -+ "ppdu-end-interrupts-mac1", -+ "rxdma2host-monitor-status-ring-mac3", -+ "rxdma2host-monitor-status-ring-mac2", -+ "rxdma2host-monitor-status-ring-mac1", -+ "host2rxdma-host-buf-ring-mac3", -+ "host2rxdma-host-buf-ring-mac2", -+ "host2rxdma-host-buf-ring-mac1", -+ "rxdma2host-destination-ring-mac3", -+ "rxdma2host-destination-ring-mac2", -+ "rxdma2host-destination-ring-mac1", -+ "host2tcl-input-ring4", -+ "host2tcl-input-ring3", -+ "host2tcl-input-ring2", -+ "host2tcl-input-ring1", -+ "wbm2host-tx-completions-ring3", -+ "wbm2host-tx-completions-ring2", -+ "wbm2host-tx-completions-ring1", -+ "tcl2host-status-ring"; -+ qcom,rproc = <&q6v5_wcss>; -+ status = "disabled"; -+ }; - }; - - timer { diff --git a/target/linux/ipq60xx/patches-5.15/0134-clk-qcom-ipq8074-add-missing-networking-resets.patch b/target/linux/ipq60xx/patches-5.15/0134-clk-qcom-ipq8074-add-missing-networking-resets.patch deleted file mode 100644 index d5313f146..000000000 --- a/target/linux/ipq60xx/patches-5.15/0134-clk-qcom-ipq8074-add-missing-networking-resets.patch +++ /dev/null @@ -1,63 +0,0 @@ -From ad08de7cb6308521b4a80c427a7cbec84742a729 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Sat, 1 Jan 2022 18:15:03 +0100 -Subject: [PATCH 134/137] clk: qcom: ipq8074: add missing networking resets - -Downstream QCA 5.4 kernel defines networking resets which are not present -in the mainline kernel but are required for the networking drivers. - -So, port the downstream resets and avoid using magic values for mask, -construct mask for resets which require multiple bits to be set/cleared. - -Signed-off-by: Robert Marko ---- - drivers/clk/qcom/gcc-ipq8074.c | 14 ++++++++++++++ - include/dt-bindings/clock/qcom,gcc-ipq8074.h | 14 ++++++++++++++ - 2 files changed, 28 insertions(+) - ---- a/drivers/clk/qcom/gcc-ipq8074.c -+++ b/drivers/clk/qcom/gcc-ipq8074.c -@@ -4821,6 +4821,20 @@ static const struct qcom_reset_map gcc_i - [GCC_PCIE1_AHB_ARES] = { 0x76040, 5 }, - [GCC_PCIE1_AXI_MASTER_STICKY_ARES] = { 0x76040, 6 }, - [GCC_WCSSAON_RESET] = { 0x59010, 0 }, -+ [GCC_PPE_FULL_RESET] = { 0x68014, 0, GENMASK(19, 16) }, -+ [GCC_UNIPHY0_SOFT_RESET] = { 0x56004, 0, GENMASK(13, 4) | BIT(1) }, -+ [GCC_UNIPHY0_XPCS_RESET] = { 0x56004, 2 }, -+ [GCC_UNIPHY1_SOFT_RESET] = { 0x56104, 0, GENMASK(5, 4) | BIT(1) }, -+ [GCC_UNIPHY1_XPCS_RESET] = { 0x56104, 2 }, -+ [GCC_UNIPHY2_SOFT_RESET] = { 0x56204, 0, GENMASK(5, 4) | BIT(1) }, -+ [GCC_UNIPHY2_XPCS_RESET] = { 0x56204, 2 }, -+ [GCC_EDMA_HW_RESET] = { 0x68014, 0, GENMASK(21, 20) }, -+ [GCC_NSSPORT1_RESET] = { 0x68014, 0, BIT(24) | GENMASK(1, 0) }, -+ [GCC_NSSPORT2_RESET] = { 0x68014, 0, BIT(25) | GENMASK(3, 2) }, -+ [GCC_NSSPORT3_RESET] = { 0x68014, 0, BIT(26) | GENMASK(5, 4) }, -+ [GCC_NSSPORT4_RESET] = { 0x68014, 0, BIT(27) | GENMASK(9, 8) }, -+ [GCC_NSSPORT5_RESET] = { 0x68014, 0, BIT(28) | GENMASK(11, 10) }, -+ [GCC_NSSPORT6_RESET] = { 0x68014, 0, BIT(29) | GENMASK(13, 12) }, - }; - - static struct gdsc *gcc_ipq8074_gdscs[] = { ---- a/include/dt-bindings/clock/qcom,gcc-ipq8074.h -+++ b/include/dt-bindings/clock/qcom,gcc-ipq8074.h -@@ -368,6 +368,20 @@ - #define GCC_PCIE1_AXI_MASTER_STICKY_ARES 130 - #define GCC_PCIE0_AXI_SLAVE_STICKY_ARES 131 - #define GCC_WCSSAON_RESET 132 -+#define GCC_PPE_FULL_RESET 133 -+#define GCC_UNIPHY0_SOFT_RESET 134 -+#define GCC_UNIPHY0_XPCS_RESET 135 -+#define GCC_UNIPHY1_SOFT_RESET 136 -+#define GCC_UNIPHY1_XPCS_RESET 137 -+#define GCC_UNIPHY2_SOFT_RESET 138 -+#define GCC_UNIPHY2_XPCS_RESET 139 -+#define GCC_EDMA_HW_RESET 140 -+#define GCC_NSSPORT1_RESET 141 -+#define GCC_NSSPORT2_RESET 142 -+#define GCC_NSSPORT3_RESET 143 -+#define GCC_NSSPORT4_RESET 144 -+#define GCC_NSSPORT5_RESET 145 -+#define GCC_NSSPORT6_RESET 146 - - #define USB0_GDSC 0 - #define USB1_GDSC 1 diff --git a/target/linux/ipq60xx/patches-5.15/0135-arm64-dts-ipq8074-add-label-to-clocks.patch b/target/linux/ipq60xx/patches-5.15/0135-arm64-dts-ipq8074-add-label-to-clocks.patch deleted file mode 100644 index deafccbeb..000000000 --- a/target/linux/ipq60xx/patches-5.15/0135-arm64-dts-ipq8074-add-label-to-clocks.patch +++ /dev/null @@ -1,24 +0,0 @@ -From c7b874696964bab2de6b08a44168c42a556a077c Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Wed, 9 Feb 2022 23:13:26 +0100 -Subject: [PATCH 135/137] arm64: dts: ipq8074: add label to clocks - -Add label to clocks node as that makes it easy to add the NSS fixed -clocks that are required in their DTSI. - -Signed-off-by: Robert Marko ---- - arch/arm64/boot/dts/qcom/ipq8074.dtsi | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -15,7 +15,7 @@ - compatible = "qcom,ipq8074"; - interrupt-parent = <&intc>; - -- clocks { -+ clocks: clocks { - sleep_clk: sleep_clk { - compatible = "fixed-clock"; - clock-frequency = <32768>; diff --git a/target/linux/ipq60xx/patches-5.15/0136-power-Add-Qualcomm-APM.patch b/target/linux/ipq60xx/patches-5.15/0136-power-Add-Qualcomm-APM.patch deleted file mode 100644 index e73afce71..000000000 --- a/target/linux/ipq60xx/patches-5.15/0136-power-Add-Qualcomm-APM.patch +++ /dev/null @@ -1,1047 +0,0 @@ -From 715f1016a6083b2a7509cb08a4f5ea0bc9661020 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Mon, 11 Apr 2022 14:38:08 +0200 -Subject: [PATCH 136/137] power: Add Qualcomm APM - -Allow building Qualcomm APM. - -Signed-off-by: Robert Marko ---- - drivers/power/Kconfig | 1 + - drivers/power/Makefile | 1 + - drivers/power/qcom/Kconfig | 7 + - drivers/power/qcom/Makefile | 1 + - drivers/power/qcom/apm.c | 944 +++++++++++++++++++++++++++++++++ - include/linux/power/qcom/apm.h | 48 ++ - 6 files changed, 1002 insertions(+) - create mode 100644 drivers/power/qcom/Kconfig - create mode 100644 drivers/power/qcom/Makefile - create mode 100644 drivers/power/qcom/apm.c - create mode 100644 include/linux/power/qcom/apm.h - ---- 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/supply/Kconfig" -+source "drivers/power/qcom/Kconfig" ---- 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_SUPPLY) += supply/ -+obj-$(CONFIG_QCOM_APM) += qcom/ ---- /dev/null -+++ b/drivers/power/qcom/Kconfig -@@ -0,0 +1,7 @@ -+config QCOM_APM -+ bool "Qualcomm Technologies Inc platform specific APM driver" -+ help -+ Platform specific driver to manage the power source of -+ memory arrays. Interfaces with regulator drivers to ensure -+ SRAM Vmin requirements are met across different performance -+ levels. ---- /dev/null -+++ b/drivers/power/qcom/Makefile -@@ -0,0 +1 @@ -+obj-$(CONFIG_QCOM_APM) += apm.o ---- /dev/null -+++ b/drivers/power/qcom/apm.c -@@ -0,0 +1,944 @@ -+/* -+ * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 and -+ * only 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. -+ */ -+ -+#define pr_fmt(fmt) "%s: " fmt, __func__ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* -+ * VDD_APCC -+ * ============================================================= -+ * | VDD_MX | | -+ * | ==========================|============= | -+ * ___|___ ___|___ ___|___ ___|___ ___|___ ___|___ -+ * | | | | | | | | | | | | -+ * | APCC | | MX HS | | MX HS | | APCC | | MX HS | | APCC | -+ * | HS | | | | | | HS | | | | HS | -+ * |_______| |_______| |_______| |_______| |_______| |_______| -+ * |_________| |_________| |__________| -+ * | | | -+ * ______|_____ ______|_____ _______|_____ -+ * | | | | | | -+ * | | | | | | -+ * | CPU MEM | | L2 MEM | | L3 MEM | -+ * | Arrays | | Arrays | | Arrays | -+ * | | | | | | -+ * |____________| |____________| |_____________| -+ * -+ */ -+ -+/* Register value definitions */ -+#define APCS_GFMUXA_SEL_VAL 0x13 -+#define APCS_GFMUXA_DESEL_VAL 0x03 -+#define MSM_APM_MX_MODE_VAL 0x00 -+#define MSM_APM_APCC_MODE_VAL 0x10 -+#define MSM_APM_MX_DONE_VAL 0x00 -+#define MSM_APM_APCC_DONE_VAL 0x03 -+#define MSM_APM_OVERRIDE_SEL_VAL 0xb0 -+#define MSM_APM_SEC_CLK_SEL_VAL 0x30 -+#define SPM_EVENT_SET_VAL 0x01 -+#define SPM_EVENT_CLEAR_VAL 0x00 -+ -+/* Register bit mask definitions */ -+#define MSM_APM_CTL_STS_MASK 0x0f -+ -+/* Register offset definitions */ -+#define APCC_APM_MODE 0x00000098 -+#define APCC_APM_CTL_STS 0x000000a8 -+#define APCS_SPARE 0x00000068 -+#define APCS_VERSION 0x00000fd0 -+ -+#define HMSS_VERSION_1P2 0x10020000 -+ -+#define MSM_APM_SWITCH_TIMEOUT_US 10 -+#define SPM_WAKEUP_DELAY_US 2 -+#define SPM_EVENT_NUM 6 -+ -+#define MSM_APM_DRIVER_NAME "qcom,msm-apm" -+ -+enum { -+ MSM8996_ID, -+ MSM8953_ID, -+ IPQ807x_ID, -+}; -+ -+struct msm_apm_ctrl_dev { -+ struct list_head list; -+ struct device *dev; -+ enum msm_apm_supply supply; -+ spinlock_t lock; -+ void __iomem *reg_base; -+ void __iomem *apcs_csr_base; -+ void __iomem **apcs_spm_events_addr; -+ void __iomem *apc0_pll_ctl_addr; -+ void __iomem *apc1_pll_ctl_addr; -+ u32 version; -+ struct dentry *debugfs; -+ u32 msm_id; -+}; -+ -+#if defined(CONFIG_DEBUG_FS) -+static struct dentry *apm_debugfs_base; -+#endif -+ -+static DEFINE_MUTEX(apm_ctrl_list_mutex); -+static LIST_HEAD(apm_ctrl_list); -+ -+/* -+ * Get the resources associated with the APM controller from device tree -+ * and remap all I/O addresses that are relevant to this HW revision. -+ */ -+static int msm_apm_ctrl_devm_ioremap(struct platform_device *pdev, -+ struct msm_apm_ctrl_dev *ctrl) -+{ -+ struct device *dev = &pdev->dev; -+ struct resource *res; -+ static const char *res_name[SPM_EVENT_NUM] = { -+ "apc0-l2-spm", -+ "apc1-l2-spm", -+ "apc0-cpu0-spm", -+ "apc0-cpu1-spm", -+ "apc1-cpu0-spm", -+ "apc1-cpu1-spm" -+ }; -+ int i, ret = 0; -+ -+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pm-apcc-glb"); -+ if (!res) { -+ dev_err(dev, "Missing PM APCC Global register physical address"); -+ return -EINVAL; -+ } -+ ctrl->reg_base = devm_ioremap(dev, res->start, resource_size(res)); -+ if (!ctrl->reg_base) { -+ dev_err(dev, "Failed to map PM APCC Global registers\n"); -+ return -ENOMEM; -+ } -+ -+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "apcs-csr"); -+ if (!res) { -+ dev_err(dev, "Missing APCS CSR physical base address"); -+ return -EINVAL; -+ } -+ ctrl->apcs_csr_base = devm_ioremap(dev, res->start, resource_size(res)); -+ if (!ctrl->apcs_csr_base) { -+ dev_err(dev, "Failed to map APCS CSR registers\n"); -+ return -ENOMEM; -+ } -+ -+ ctrl->version = readl_relaxed(ctrl->apcs_csr_base + APCS_VERSION); -+ -+ if (ctrl->version >= HMSS_VERSION_1P2) -+ return ret; -+ -+ ctrl->apcs_spm_events_addr = devm_kzalloc(&pdev->dev, -+ SPM_EVENT_NUM -+ * sizeof(void __iomem *), -+ GFP_KERNEL); -+ if (!ctrl->apcs_spm_events_addr) { -+ dev_err(dev, "Failed to allocate memory for APCS SPM event registers\n"); -+ return -ENOMEM; -+ } -+ -+ for (i = 0; i < SPM_EVENT_NUM; i++) { -+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, -+ res_name[i]); -+ if (!res) { -+ dev_err(dev, "Missing address for %s\n", res_name[i]); -+ ret = -EINVAL; -+ goto free_events; -+ } -+ -+ ctrl->apcs_spm_events_addr[i] = devm_ioremap(dev, res->start, -+ resource_size(res)); -+ if (!ctrl->apcs_spm_events_addr[i]) { -+ dev_err(dev, "Failed to map %s\n", res_name[i]); -+ ret = -ENOMEM; -+ goto free_events; -+ } -+ -+ dev_dbg(dev, "%s event phys: %pa virt:0x%p\n", res_name[i], -+ &res->start, ctrl->apcs_spm_events_addr[i]); -+ } -+ -+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, -+ "apc0-pll-ctl"); -+ if (!res) { -+ dev_err(dev, "Missing APC0 PLL CTL physical address\n"); -+ ret = -EINVAL; -+ goto free_events; -+ } -+ -+ ctrl->apc0_pll_ctl_addr = devm_ioremap(dev, -+ res->start, -+ resource_size(res)); -+ if (!ctrl->apc0_pll_ctl_addr) { -+ dev_err(dev, "Failed to map APC0 PLL CTL register\n"); -+ ret = -ENOMEM; -+ goto free_events; -+ } -+ -+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, -+ "apc1-pll-ctl"); -+ if (!res) { -+ dev_err(dev, "Missing APC1 PLL CTL physical address\n"); -+ ret = -EINVAL; -+ goto free_events; -+ } -+ -+ ctrl->apc1_pll_ctl_addr = devm_ioremap(dev, -+ res->start, -+ resource_size(res)); -+ if (!ctrl->apc1_pll_ctl_addr) { -+ dev_err(dev, "Failed to map APC1 PLL CTL register\n"); -+ ret = -ENOMEM; -+ goto free_events; -+ } -+ -+ return ret; -+ -+free_events: -+ devm_kfree(dev, ctrl->apcs_spm_events_addr); -+ return ret; -+} -+ -+/* 8953 register offset definition */ -+#define MSM8953_APM_DLY_CNTR 0x2ac -+ -+/* Register field shift definitions */ -+#define APM_CTL_SEL_SWITCH_DLY_SHIFT 0 -+#define APM_CTL_RESUME_CLK_DLY_SHIFT 8 -+#define APM_CTL_HALT_CLK_DLY_SHIFT 16 -+#define APM_CTL_POST_HALT_DLY_SHIFT 24 -+ -+/* Register field mask definitions */ -+#define APM_CTL_SEL_SWITCH_DLY_MASK GENMASK(7, 0) -+#define APM_CTL_RESUME_CLK_DLY_MASK GENMASK(15, 8) -+#define APM_CTL_HALT_CLK_DLY_MASK GENMASK(23, 16) -+#define APM_CTL_POST_HALT_DLY_MASK GENMASK(31, 24) -+ -+/* -+ * Get the resources associated with the msm8953 APM controller from -+ * device tree, remap all I/O addresses, and program the initial -+ * register configuration required for the 8953 APM controller device. -+ */ -+static int msm8953_apm_ctrl_init(struct platform_device *pdev, -+ struct msm_apm_ctrl_dev *ctrl) -+{ -+ struct device *dev = &pdev->dev; -+ struct resource *res; -+ u32 delay_counter, val = 0, regval = 0; -+ int rc = 0; -+ -+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pm-apcc-glb"); -+ if (!res) { -+ dev_err(dev, "Missing PM APCC Global register physical address\n"); -+ return -ENODEV; -+ } -+ ctrl->reg_base = devm_ioremap(dev, res->start, resource_size(res)); -+ if (!ctrl->reg_base) { -+ dev_err(dev, "Failed to map PM APCC Global registers\n"); -+ return -ENOMEM; -+ } -+ -+ /* -+ * Initial APM register configuration required before starting -+ * APM HW controller. -+ */ -+ regval = readl_relaxed(ctrl->reg_base + MSM8953_APM_DLY_CNTR); -+ val = regval; -+ -+ if (of_find_property(dev->of_node, "qcom,apm-post-halt-delay", NULL)) { -+ rc = of_property_read_u32(dev->of_node, -+ "qcom,apm-post-halt-delay", &delay_counter); -+ if (rc < 0) { -+ dev_err(dev, "apm-post-halt-delay read failed, rc = %d", -+ rc); -+ return rc; -+ } -+ -+ val &= ~APM_CTL_POST_HALT_DLY_MASK; -+ val |= (delay_counter << APM_CTL_POST_HALT_DLY_SHIFT) -+ & APM_CTL_POST_HALT_DLY_MASK; -+ } -+ -+ if (of_find_property(dev->of_node, "qcom,apm-halt-clk-delay", NULL)) { -+ rc = of_property_read_u32(dev->of_node, -+ "qcom,apm-halt-clk-delay", &delay_counter); -+ if (rc < 0) { -+ dev_err(dev, "apm-halt-clk-delay read failed, rc = %d", -+ rc); -+ return rc; -+ } -+ -+ val &= ~APM_CTL_HALT_CLK_DLY_MASK; -+ val |= (delay_counter << APM_CTL_HALT_CLK_DLY_SHIFT) -+ & APM_CTL_HALT_CLK_DLY_MASK; -+ } -+ -+ if (of_find_property(dev->of_node, "qcom,apm-resume-clk-delay", NULL)) { -+ rc = of_property_read_u32(dev->of_node, -+ "qcom,apm-resume-clk-delay", &delay_counter); -+ if (rc < 0) { -+ dev_err(dev, "apm-resume-clk-delay read failed, rc = %d", -+ rc); -+ return rc; -+ } -+ -+ val &= ~APM_CTL_RESUME_CLK_DLY_MASK; -+ val |= (delay_counter << APM_CTL_RESUME_CLK_DLY_SHIFT) -+ & APM_CTL_RESUME_CLK_DLY_MASK; -+ } -+ -+ if (of_find_property(dev->of_node, "qcom,apm-sel-switch-delay", NULL)) { -+ rc = of_property_read_u32(dev->of_node, -+ "qcom,apm-sel-switch-delay", &delay_counter); -+ if (rc < 0) { -+ dev_err(dev, "apm-sel-switch-delay read failed, rc = %d", -+ rc); -+ return rc; -+ } -+ -+ val &= ~APM_CTL_SEL_SWITCH_DLY_MASK; -+ val |= (delay_counter << APM_CTL_SEL_SWITCH_DLY_SHIFT) -+ & APM_CTL_SEL_SWITCH_DLY_MASK; -+ } -+ -+ if (val != regval) { -+ writel_relaxed(val, ctrl->reg_base + MSM8953_APM_DLY_CNTR); -+ /* make sure write completes before return */ -+ mb(); -+ } -+ -+ return rc; -+} -+ -+static int msm8996_apm_switch_to_mx(struct msm_apm_ctrl_dev *ctrl_dev) -+{ -+ int i, timeout = MSM_APM_SWITCH_TIMEOUT_US; -+ u32 regval; -+ int ret = 0; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&ctrl_dev->lock, flags); -+ -+ /* Perform revision-specific programming steps */ -+ if (ctrl_dev->version < HMSS_VERSION_1P2) { -+ /* Clear SPM events */ -+ for (i = 0; i < SPM_EVENT_NUM; i++) -+ writel_relaxed(SPM_EVENT_CLEAR_VAL, -+ ctrl_dev->apcs_spm_events_addr[i]); -+ -+ udelay(SPM_WAKEUP_DELAY_US); -+ -+ /* Switch APC/CBF to GPLL0 clock */ -+ writel_relaxed(APCS_GFMUXA_SEL_VAL, -+ ctrl_dev->apcs_csr_base + APCS_SPARE); -+ ndelay(200); -+ writel_relaxed(MSM_APM_OVERRIDE_SEL_VAL, -+ ctrl_dev->apc0_pll_ctl_addr); -+ ndelay(200); -+ writel_relaxed(MSM_APM_OVERRIDE_SEL_VAL, -+ ctrl_dev->apc1_pll_ctl_addr); -+ -+ /* Ensure writes complete before proceeding */ -+ mb(); -+ } -+ -+ /* Switch arrays to MX supply and wait for its completion */ -+ writel_relaxed(MSM_APM_MX_MODE_VAL, ctrl_dev->reg_base + -+ APCC_APM_MODE); -+ -+ /* Ensure write above completes before delaying */ -+ mb(); -+ -+ while (timeout > 0) { -+ regval = readl_relaxed(ctrl_dev->reg_base + APCC_APM_CTL_STS); -+ if ((regval & MSM_APM_CTL_STS_MASK) == -+ MSM_APM_MX_DONE_VAL) -+ break; -+ -+ udelay(1); -+ timeout--; -+ } -+ -+ if (timeout == 0) { -+ ret = -ETIMEDOUT; -+ dev_err(ctrl_dev->dev, "APCC to MX APM switch timed out. APCC_APM_CTL_STS=0x%x\n", -+ regval); -+ } -+ -+ /* Perform revision-specific programming steps */ -+ if (ctrl_dev->version < HMSS_VERSION_1P2) { -+ /* Switch APC/CBF clocks to original source */ -+ writel_relaxed(APCS_GFMUXA_DESEL_VAL, -+ ctrl_dev->apcs_csr_base + APCS_SPARE); -+ ndelay(200); -+ writel_relaxed(MSM_APM_SEC_CLK_SEL_VAL, -+ ctrl_dev->apc0_pll_ctl_addr); -+ ndelay(200); -+ writel_relaxed(MSM_APM_SEC_CLK_SEL_VAL, -+ ctrl_dev->apc1_pll_ctl_addr); -+ -+ /* Complete clock source switch before SPM event sequence */ -+ mb(); -+ -+ /* Set SPM events */ -+ for (i = 0; i < SPM_EVENT_NUM; i++) -+ writel_relaxed(SPM_EVENT_SET_VAL, -+ ctrl_dev->apcs_spm_events_addr[i]); -+ } -+ -+ if (!ret) { -+ ctrl_dev->supply = MSM_APM_SUPPLY_MX; -+ dev_dbg(ctrl_dev->dev, "APM supply switched to MX\n"); -+ } -+ -+ spin_unlock_irqrestore(&ctrl_dev->lock, flags); -+ -+ return ret; -+} -+ -+static int msm8996_apm_switch_to_apcc(struct msm_apm_ctrl_dev *ctrl_dev) -+{ -+ int i, timeout = MSM_APM_SWITCH_TIMEOUT_US; -+ u32 regval; -+ int ret = 0; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&ctrl_dev->lock, flags); -+ -+ /* Perform revision-specific programming steps */ -+ if (ctrl_dev->version < HMSS_VERSION_1P2) { -+ /* Clear SPM events */ -+ for (i = 0; i < SPM_EVENT_NUM; i++) -+ writel_relaxed(SPM_EVENT_CLEAR_VAL, -+ ctrl_dev->apcs_spm_events_addr[i]); -+ -+ udelay(SPM_WAKEUP_DELAY_US); -+ -+ /* Switch APC/CBF to GPLL0 clock */ -+ writel_relaxed(APCS_GFMUXA_SEL_VAL, -+ ctrl_dev->apcs_csr_base + APCS_SPARE); -+ ndelay(200); -+ writel_relaxed(MSM_APM_OVERRIDE_SEL_VAL, -+ ctrl_dev->apc0_pll_ctl_addr); -+ ndelay(200); -+ writel_relaxed(MSM_APM_OVERRIDE_SEL_VAL, -+ ctrl_dev->apc1_pll_ctl_addr); -+ -+ /* Ensure previous writes complete before proceeding */ -+ mb(); -+ } -+ -+ /* Switch arrays to APCC supply and wait for its completion */ -+ writel_relaxed(MSM_APM_APCC_MODE_VAL, ctrl_dev->reg_base + -+ APCC_APM_MODE); -+ -+ /* Ensure write above completes before delaying */ -+ mb(); -+ -+ while (timeout > 0) { -+ regval = readl_relaxed(ctrl_dev->reg_base + APCC_APM_CTL_STS); -+ if ((regval & MSM_APM_CTL_STS_MASK) == -+ MSM_APM_APCC_DONE_VAL) -+ break; -+ -+ udelay(1); -+ timeout--; -+ } -+ -+ if (timeout == 0) { -+ ret = -ETIMEDOUT; -+ dev_err(ctrl_dev->dev, "MX to APCC APM switch timed out. APCC_APM_CTL_STS=0x%x\n", -+ regval); -+ } -+ -+ /* Perform revision-specific programming steps */ -+ if (ctrl_dev->version < HMSS_VERSION_1P2) { -+ /* Set SPM events */ -+ for (i = 0; i < SPM_EVENT_NUM; i++) -+ writel_relaxed(SPM_EVENT_SET_VAL, -+ ctrl_dev->apcs_spm_events_addr[i]); -+ -+ /* Complete SPM event sequence before clock source switch */ -+ mb(); -+ -+ /* Switch APC/CBF clocks to original source */ -+ writel_relaxed(APCS_GFMUXA_DESEL_VAL, -+ ctrl_dev->apcs_csr_base + APCS_SPARE); -+ ndelay(200); -+ writel_relaxed(MSM_APM_SEC_CLK_SEL_VAL, -+ ctrl_dev->apc0_pll_ctl_addr); -+ ndelay(200); -+ writel_relaxed(MSM_APM_SEC_CLK_SEL_VAL, -+ ctrl_dev->apc1_pll_ctl_addr); -+ } -+ -+ if (!ret) { -+ ctrl_dev->supply = MSM_APM_SUPPLY_APCC; -+ dev_dbg(ctrl_dev->dev, "APM supply switched to APCC\n"); -+ } -+ -+ spin_unlock_irqrestore(&ctrl_dev->lock, flags); -+ -+ return ret; -+} -+ -+/* 8953 register value definitions */ -+#define MSM8953_APM_MX_MODE_VAL 0x00 -+#define MSM8953_APM_APCC_MODE_VAL 0x02 -+#define MSM8953_APM_MX_DONE_VAL 0x00 -+#define MSM8953_APM_APCC_DONE_VAL 0x03 -+ -+/* 8953 register offset definitions */ -+#define MSM8953_APCC_APM_MODE 0x000002a8 -+#define MSM8953_APCC_APM_CTL_STS 0x000002b0 -+ -+/* 8953 constants */ -+#define MSM8953_APM_SWITCH_TIMEOUT_US 500 -+ -+/* Register bit mask definitions */ -+#define MSM8953_APM_CTL_STS_MASK 0x1f -+ -+static int msm8953_apm_switch_to_mx(struct msm_apm_ctrl_dev *ctrl_dev) -+{ -+ int timeout = MSM8953_APM_SWITCH_TIMEOUT_US; -+ u32 regval; -+ int ret = 0; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&ctrl_dev->lock, flags); -+ -+ /* Switch arrays to MX supply and wait for its completion */ -+ writel_relaxed(MSM8953_APM_MX_MODE_VAL, ctrl_dev->reg_base + -+ MSM8953_APCC_APM_MODE); -+ -+ /* Ensure write above completes before delaying */ -+ mb(); -+ -+ while (timeout > 0) { -+ regval = readl_relaxed(ctrl_dev->reg_base + -+ MSM8953_APCC_APM_CTL_STS); -+ if ((regval & MSM8953_APM_CTL_STS_MASK) == -+ MSM8953_APM_MX_DONE_VAL) -+ break; -+ -+ udelay(1); -+ timeout--; -+ } -+ -+ if (timeout == 0) { -+ ret = -ETIMEDOUT; -+ dev_err(ctrl_dev->dev, "APCC to MX APM switch timed out. APCC_APM_CTL_STS=0x%x\n", -+ regval); -+ } else { -+ ctrl_dev->supply = MSM_APM_SUPPLY_MX; -+ dev_dbg(ctrl_dev->dev, "APM supply switched to MX\n"); -+ } -+ -+ spin_unlock_irqrestore(&ctrl_dev->lock, flags); -+ -+ return ret; -+} -+ -+static int msm8953_apm_switch_to_apcc(struct msm_apm_ctrl_dev *ctrl_dev) -+{ -+ int timeout = MSM8953_APM_SWITCH_TIMEOUT_US; -+ u32 regval; -+ int ret = 0; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&ctrl_dev->lock, flags); -+ -+ /* Switch arrays to APCC supply and wait for its completion */ -+ writel_relaxed(MSM8953_APM_APCC_MODE_VAL, ctrl_dev->reg_base + -+ MSM8953_APCC_APM_MODE); -+ -+ /* Ensure write above completes before delaying */ -+ mb(); -+ -+ while (timeout > 0) { -+ regval = readl_relaxed(ctrl_dev->reg_base + -+ MSM8953_APCC_APM_CTL_STS); -+ if ((regval & MSM8953_APM_CTL_STS_MASK) == -+ MSM8953_APM_APCC_DONE_VAL) -+ break; -+ -+ udelay(1); -+ timeout--; -+ } -+ -+ if (timeout == 0) { -+ ret = -ETIMEDOUT; -+ dev_err(ctrl_dev->dev, "MX to APCC APM switch timed out. APCC_APM_CTL_STS=0x%x\n", -+ regval); -+ } else { -+ ctrl_dev->supply = MSM_APM_SUPPLY_APCC; -+ dev_dbg(ctrl_dev->dev, "APM supply switched to APCC\n"); -+ } -+ -+ spin_unlock_irqrestore(&ctrl_dev->lock, flags); -+ -+ return ret; -+} -+ -+static int msm_apm_switch_to_mx(struct msm_apm_ctrl_dev *ctrl_dev) -+{ -+ int ret = 0; -+ -+ switch (ctrl_dev->msm_id) { -+ case MSM8996_ID: -+ ret = msm8996_apm_switch_to_mx(ctrl_dev); -+ break; -+ case MSM8953_ID: -+ case IPQ807x_ID: -+ ret = msm8953_apm_switch_to_mx(ctrl_dev); -+ break; -+ } -+ -+ return ret; -+} -+ -+static int msm_apm_switch_to_apcc(struct msm_apm_ctrl_dev *ctrl_dev) -+{ -+ int ret = 0; -+ -+ switch (ctrl_dev->msm_id) { -+ case MSM8996_ID: -+ ret = msm8996_apm_switch_to_apcc(ctrl_dev); -+ break; -+ case MSM8953_ID: -+ case IPQ807x_ID: -+ ret = msm8953_apm_switch_to_apcc(ctrl_dev); -+ break; -+ } -+ -+ return ret; -+} -+ -+/** -+ * msm_apm_get_supply() - Returns the supply that is currently -+ * powering the memory arrays -+ * @ctrl_dev: Pointer to an MSM APM controller device -+ * -+ * Returns the supply currently selected by the APM. -+ */ -+int msm_apm_get_supply(struct msm_apm_ctrl_dev *ctrl_dev) -+{ -+ return ctrl_dev->supply; -+} -+EXPORT_SYMBOL(msm_apm_get_supply); -+ -+/** -+ * msm_apm_set_supply() - Perform the necessary steps to switch the voltage -+ * source of the memory arrays to a given supply -+ * @ctrl_dev: Pointer to an MSM APM controller device -+ * @supply: Power rail to use as supply for the memory -+ * arrays -+ * -+ * Returns 0 on success, -ETIMEDOUT on APM switch timeout, or -EPERM if -+ * the supply is not supported. -+ */ -+int msm_apm_set_supply(struct msm_apm_ctrl_dev *ctrl_dev, -+ enum msm_apm_supply supply) -+{ -+ int ret; -+ -+ switch (supply) { -+ case MSM_APM_SUPPLY_APCC: -+ ret = msm_apm_switch_to_apcc(ctrl_dev); -+ break; -+ case MSM_APM_SUPPLY_MX: -+ ret = msm_apm_switch_to_mx(ctrl_dev); -+ break; -+ default: -+ ret = -EPERM; -+ break; -+ } -+ -+ return ret; -+} -+EXPORT_SYMBOL(msm_apm_set_supply); -+ -+/** -+ * msm_apm_ctrl_dev_get() - get a handle to the MSM APM controller linked to -+ * the device in device tree -+ * @dev: Pointer to the device -+ * -+ * The device must specify "qcom,apm-ctrl" property in its device tree -+ * node which points to an MSM APM controller device node. -+ * -+ * Returns an MSM APM controller handle if successful or ERR_PTR on any error. -+ * If the APM controller device hasn't probed yet, ERR_PTR(-EPROBE_DEFER) is -+ * returned. -+ */ -+struct msm_apm_ctrl_dev *msm_apm_ctrl_dev_get(struct device *dev) -+{ -+ struct msm_apm_ctrl_dev *ctrl_dev = NULL; -+ struct msm_apm_ctrl_dev *dev_found = ERR_PTR(-EPROBE_DEFER); -+ struct device_node *ctrl_node; -+ -+ if (!dev || !dev->of_node) { -+ pr_err("Invalid device node\n"); -+ return ERR_PTR(-EINVAL); -+ } -+ -+ ctrl_node = of_parse_phandle(dev->of_node, "qcom,apm-ctrl", 0); -+ if (!ctrl_node) { -+ pr_err("Could not find qcom,apm-ctrl property in %s\n", -+ dev->of_node->full_name); -+ return ERR_PTR(-ENXIO); -+ } -+ -+ mutex_lock(&apm_ctrl_list_mutex); -+ list_for_each_entry(ctrl_dev, &apm_ctrl_list, list) { -+ if (ctrl_dev->dev && ctrl_dev->dev->of_node == ctrl_node) { -+ dev_found = ctrl_dev; -+ break; -+ } -+ } -+ mutex_unlock(&apm_ctrl_list_mutex); -+ -+ of_node_put(ctrl_node); -+ return dev_found; -+} -+EXPORT_SYMBOL(msm_apm_ctrl_dev_get); -+ -+#if defined(CONFIG_DEBUG_FS) -+ -+static int apm_supply_dbg_open(struct inode *inode, struct file *filep) -+{ -+ filep->private_data = inode->i_private; -+ -+ return 0; -+} -+ -+static ssize_t apm_supply_dbg_read(struct file *filep, char __user *ubuf, -+ size_t count, loff_t *ppos) -+{ -+ struct msm_apm_ctrl_dev *ctrl_dev = filep->private_data; -+ char buf[10]; -+ int len; -+ -+ if (!ctrl_dev) { -+ pr_err("invalid apm ctrl handle\n"); -+ return -ENODEV; -+ } -+ -+ if (ctrl_dev->supply == MSM_APM_SUPPLY_APCC) -+ len = snprintf(buf, sizeof(buf), "APCC\n"); -+ else if (ctrl_dev->supply == MSM_APM_SUPPLY_MX) -+ len = snprintf(buf, sizeof(buf), "MX\n"); -+ else -+ len = snprintf(buf, sizeof(buf), "ERR\n"); -+ -+ return simple_read_from_buffer(ubuf, count, ppos, buf, len); -+} -+ -+static const struct file_operations apm_supply_fops = { -+ .open = apm_supply_dbg_open, -+ .read = apm_supply_dbg_read, -+}; -+ -+static void apm_debugfs_base_init(void) -+{ -+ apm_debugfs_base = debugfs_create_dir("msm-apm", NULL); -+ -+ if (IS_ERR_OR_NULL(apm_debugfs_base)) -+ pr_err("msm-apm debugfs base directory creation failed\n"); -+} -+ -+static void apm_debugfs_init(struct msm_apm_ctrl_dev *ctrl_dev) -+{ -+ struct dentry *temp; -+ -+ if (IS_ERR_OR_NULL(apm_debugfs_base)) { -+ pr_err("Base directory missing, cannot create apm debugfs nodes\n"); -+ return; -+ } -+ -+ ctrl_dev->debugfs = debugfs_create_dir(dev_name(ctrl_dev->dev), -+ apm_debugfs_base); -+ if (IS_ERR_OR_NULL(ctrl_dev->debugfs)) { -+ pr_err("%s debugfs directory creation failed\n", -+ dev_name(ctrl_dev->dev)); -+ return; -+ } -+ -+ temp = debugfs_create_file("supply", S_IRUGO, ctrl_dev->debugfs, -+ ctrl_dev, &apm_supply_fops); -+ if (IS_ERR_OR_NULL(temp)) { -+ pr_err("supply mode creation failed\n"); -+ return; -+ } -+} -+ -+static void apm_debugfs_deinit(struct msm_apm_ctrl_dev *ctrl_dev) -+{ -+ if (!IS_ERR_OR_NULL(ctrl_dev->debugfs)) -+ debugfs_remove_recursive(ctrl_dev->debugfs); -+} -+ -+static void apm_debugfs_base_remove(void) -+{ -+ debugfs_remove_recursive(apm_debugfs_base); -+} -+#else -+ -+static void apm_debugfs_base_init(void) -+{} -+ -+static void apm_debugfs_init(struct msm_apm_ctrl_dev *ctrl_dev) -+{} -+ -+static void apm_debugfs_deinit(struct msm_apm_ctrl_dev *ctrl_dev) -+{} -+ -+static void apm_debugfs_base_remove(void) -+{} -+ -+#endif -+ -+static struct of_device_id msm_apm_match_table[] = { -+ { -+ .compatible = "qcom,msm-apm", -+ .data = (void *)(uintptr_t)MSM8996_ID, -+ }, -+ { -+ .compatible = "qcom,msm8953-apm", -+ .data = (void *)(uintptr_t)MSM8953_ID, -+ }, -+ { -+ .compatible = "qcom,ipq807x-apm", -+ .data = (void *)(uintptr_t)IPQ807x_ID, -+ }, -+ {} -+}; -+ -+static int msm_apm_probe(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ struct msm_apm_ctrl_dev *ctrl; -+ const struct of_device_id *match; -+ int ret = 0; -+ -+ dev_dbg(dev, "probing MSM Array Power Mux driver\n"); -+ -+ if (!dev->of_node) { -+ dev_err(dev, "Device tree node is missing\n"); -+ return -ENODEV; -+ } -+ -+ match = of_match_device(msm_apm_match_table, dev); -+ if (!match) -+ return -ENODEV; -+ -+ ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL); -+ if (!ctrl) { -+ dev_err(dev, "MSM APM controller memory allocation failed\n"); -+ return -ENOMEM; -+ } -+ -+ INIT_LIST_HEAD(&ctrl->list); -+ spin_lock_init(&ctrl->lock); -+ ctrl->dev = dev; -+ ctrl->msm_id = (uintptr_t)match->data; -+ platform_set_drvdata(pdev, ctrl); -+ -+ switch (ctrl->msm_id) { -+ case MSM8996_ID: -+ ret = msm_apm_ctrl_devm_ioremap(pdev, ctrl); -+ if (ret) { -+ dev_err(dev, "Failed to add APM controller device\n"); -+ return ret; -+ } -+ break; -+ case MSM8953_ID: -+ case IPQ807x_ID: -+ ret = msm8953_apm_ctrl_init(pdev, ctrl); -+ if (ret) { -+ dev_err(dev, "Failed to initialize APM controller device: ret=%d\n", -+ ret); -+ return ret; -+ } -+ break; -+ default: -+ dev_err(dev, "unable to add APM controller device for msm_id:%d\n", -+ ctrl->msm_id); -+ return -ENODEV; -+ } -+ -+ apm_debugfs_init(ctrl); -+ mutex_lock(&apm_ctrl_list_mutex); -+ list_add_tail(&ctrl->list, &apm_ctrl_list); -+ mutex_unlock(&apm_ctrl_list_mutex); -+ -+ dev_dbg(dev, "MSM Array Power Mux driver probe successful"); -+ -+ return ret; -+} -+ -+static int msm_apm_remove(struct platform_device *pdev) -+{ -+ struct msm_apm_ctrl_dev *ctrl_dev; -+ -+ ctrl_dev = platform_get_drvdata(pdev); -+ if (ctrl_dev) { -+ mutex_lock(&apm_ctrl_list_mutex); -+ list_del(&ctrl_dev->list); -+ mutex_unlock(&apm_ctrl_list_mutex); -+ apm_debugfs_deinit(ctrl_dev); -+ } -+ -+ return 0; -+} -+ -+static struct platform_driver msm_apm_driver = { -+ .driver = { -+ .name = MSM_APM_DRIVER_NAME, -+ .of_match_table = msm_apm_match_table, -+ .owner = THIS_MODULE, -+ }, -+ .probe = msm_apm_probe, -+ .remove = msm_apm_remove, -+}; -+ -+static int __init msm_apm_init(void) -+{ -+ apm_debugfs_base_init(); -+ return platform_driver_register(&msm_apm_driver); -+} -+ -+static void __exit msm_apm_exit(void) -+{ -+ platform_driver_unregister(&msm_apm_driver); -+ apm_debugfs_base_remove(); -+} -+ -+arch_initcall(msm_apm_init); -+module_exit(msm_apm_exit); -+ -+MODULE_DESCRIPTION("MSM Array Power Mux driver"); -+MODULE_LICENSE("GPL v2"); ---- /dev/null -+++ b/include/linux/power/qcom/apm.h -@@ -0,0 +1,48 @@ -+/* -+ * Copyright (c) 2015, The Linux Foundation. All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 and -+ * only version 2 as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ */ -+ -+#ifndef __LINUX_POWER_QCOM_APM_H__ -+#define __LINUX_POWER_QCOM_APM_H__ -+ -+#include -+#include -+ -+/** -+ * enum msm_apm_supply - supported power rails to supply memory arrays -+ * %MSM_APM_SUPPLY_APCC: to enable selection of VDD_APCC rail as supply -+ * %MSM_APM_SUPPLY_MX: to enable selection of VDD_MX rail as supply -+ */ -+enum msm_apm_supply { -+ MSM_APM_SUPPLY_APCC, -+ MSM_APM_SUPPLY_MX, -+}; -+ -+/* Handle used to identify an APM controller device */ -+struct msm_apm_ctrl_dev; -+ -+#ifdef CONFIG_QCOM_APM -+struct msm_apm_ctrl_dev *msm_apm_ctrl_dev_get(struct device *dev); -+int msm_apm_set_supply(struct msm_apm_ctrl_dev *ctrl_dev, -+ enum msm_apm_supply supply); -+int msm_apm_get_supply(struct msm_apm_ctrl_dev *ctrl_dev); -+ -+#else -+static inline struct msm_apm_ctrl_dev *msm_apm_ctrl_dev_get(struct device *dev) -+{ return ERR_PTR(-EPERM); } -+static inline int msm_apm_set_supply(struct msm_apm_ctrl_dev *ctrl_dev, -+ enum msm_apm_supply supply) -+{ return -EPERM; } -+static inline int msm_apm_get_supply(struct msm_apm_ctrl_dev *ctrl_dev) -+{ return -EPERM; } -+#endif -+#endif diff --git a/target/linux/ipq60xx/patches-5.15/0137-regulator-add-Qualcomm-CPR-regulators.patch b/target/linux/ipq60xx/patches-5.15/0137-regulator-add-Qualcomm-CPR-regulators.patch deleted file mode 100644 index 2f997e23a..000000000 --- a/target/linux/ipq60xx/patches-5.15/0137-regulator-add-Qualcomm-CPR-regulators.patch +++ /dev/null @@ -1,12146 +0,0 @@ -From 15db7a6341e0d01c12cd9a76c1d9f51a6bca56cf Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Mon, 11 Apr 2022 14:35:36 +0200 -Subject: [PATCH 137/137] regulator: add Qualcomm CPR regulators - -Allow building Qualcomm CPR regulators. - -Signed-off-by: Robert Marko ---- - drivers/regulator/Kconfig | 33 + - drivers/regulator/Makefile | 3 + - drivers/regulator/cpr3-npu-regulator.c | 695 +++ - drivers/regulator/cpr3-regulator.c | 5112 +++++++++++++++++++++++ - drivers/regulator/cpr3-regulator.h | 1211 ++++++ - drivers/regulator/cpr3-util.c | 2750 ++++++++++++ - drivers/regulator/cpr4-apss-regulator.c | 1819 ++++++++ - include/soc/qcom/socinfo.h | 463 ++ - 8 files changed, 12086 insertions(+) - create mode 100644 drivers/regulator/cpr3-npu-regulator.c - create mode 100644 drivers/regulator/cpr3-regulator.c - create mode 100644 drivers/regulator/cpr3-regulator.h - create mode 100644 drivers/regulator/cpr3-util.c - create mode 100644 drivers/regulator/cpr4-apss-regulator.c - create mode 100644 include/soc/qcom/socinfo.h - ---- a/drivers/regulator/Kconfig -+++ b/drivers/regulator/Kconfig -@@ -1423,5 +1423,38 @@ config REGULATOR_QCOM_LABIBB - boost regulator and IBB can be used as a negative boost regulator - for LCD display panel. - -+config REGULATOR_CPR3 -+ bool "QCOM CPR3 regulator core support" -+ help -+ This driver supports Core Power Reduction (CPR) version 3 controllers -+ which are used by some Qualcomm Technologies, Inc. SoCs to -+ manage important voltage regulators. CPR3 controllers are capable of -+ monitoring several ring oscillator sensing loops simultaneously. The -+ CPR3 controller informs software when the silicon conditions require -+ the supply voltage to be increased or decreased. On certain supply -+ rails, the CPR3 controller is able to propagate the voltage increase -+ or decrease requests all the way to the PMIC without software -+ involvement. -+ -+config REGULATOR_CPR3_NPU -+ bool "QCOM CPR3 regulator for NPU" -+ depends on OF && REGULATOR_CPR3 -+ help -+ This driver supports Qualcomm Technologies, Inc. NPU CPR3 -+ regulator Which will always operate in open loop. -+ -+config REGULATOR_CPR4_APSS -+ bool "QCOM CPR4 regulator for APSS" -+ depends on OF && REGULATOR_CPR3 -+ help -+ This driver supports Qualcomm Technologies, Inc. APSS application -+ processor specific features including memory array power mux (APM) -+ switching, one CPR4 thread which monitor the two APSS clusters that -+ are both powered by a shared supply, hardware closed-loop auto -+ voltage stepping, voltage adjustments based on online core count, -+ voltage adjustments based on temperature readings, and voltage -+ adjustments for performance boost mode. This driver reads both initial -+ voltage and CPR target quotient values out of hardware fuses. -+ - endif - ---- a/drivers/regulator/Makefile -+++ b/drivers/regulator/Makefile -@@ -105,6 +105,9 @@ obj-$(CONFIG_REGULATOR_QCOM_RPMH) += qco - obj-$(CONFIG_REGULATOR_QCOM_SMD_RPM) += qcom_smd-regulator.o - obj-$(CONFIG_REGULATOR_QCOM_SPMI) += qcom_spmi-regulator.o - obj-$(CONFIG_REGULATOR_QCOM_USB_VBUS) += qcom_usb_vbus-regulator.o -+obj-$(CONFIG_REGULATOR_CPR3) += cpr3-regulator.o cpr3-util.o -+obj-$(CONFIG_REGULATOR_CPR3_NPU) += cpr3-npu-regulator.o -+obj-$(CONFIG_REGULATOR_CPR4_APSS) += cpr4-apss-regulator.o - obj-$(CONFIG_REGULATOR_PALMAS) += palmas-regulator.o - obj-$(CONFIG_REGULATOR_PCA9450) += pca9450-regulator.o - obj-$(CONFIG_REGULATOR_PF8X00) += pf8x00-regulator.o ---- /dev/null -+++ b/drivers/regulator/cpr3-npu-regulator.c -@@ -0,0 +1,695 @@ -+/* -+ * Copyright (c) 2017, The Linux Foundation. All rights reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "cpr3-regulator.h" -+ -+#define IPQ807x_NPU_FUSE_CORNERS 2 -+#define IPQ817x_NPU_FUSE_CORNERS 1 -+#define IPQ807x_NPU_FUSE_STEP_VOLT 8000 -+#define IPQ807x_NPU_VOLTAGE_FUSE_SIZE 6 -+#define IPQ807x_NPU_CPR_CLOCK_RATE 19200000 -+ -+#define IPQ807x_NPU_CPR_TCSR_START 6 -+#define IPQ807x_NPU_CPR_TCSR_END 7 -+ -+#define NPU_TSENS 5 -+ -+u32 g_valid_npu_fuse_count = IPQ807x_NPU_FUSE_CORNERS; -+/** -+ * struct cpr3_ipq807x_npu_fuses - NPU specific fuse data for IPQ807x -+ * @init_voltage: Initial (i.e. open-loop) voltage fuse parameter value -+ * for each fuse corner (raw, not converted to a voltage) -+ * This struct holds the values for all of the fuses read from memory. -+ */ -+struct cpr3_ipq807x_npu_fuses { -+ u64 init_voltage[IPQ807x_NPU_FUSE_CORNERS]; -+}; -+ -+/* -+ * Constants which define the name of each fuse corner. -+ */ -+enum cpr3_ipq807x_npu_fuse_corner { -+ CPR3_IPQ807x_NPU_FUSE_CORNER_NOM = 0, -+ CPR3_IPQ807x_NPU_FUSE_CORNER_TURBO = 1, -+}; -+ -+static const char * const cpr3_ipq807x_npu_fuse_corner_name[] = { -+ [CPR3_IPQ807x_NPU_FUSE_CORNER_NOM] = "NOM", -+ [CPR3_IPQ807x_NPU_FUSE_CORNER_TURBO] = "TURBO", -+}; -+ -+/* -+ * IPQ807x NPU fuse parameter locations: -+ * -+ * Structs are organized with the following dimensions: -+ * Outer: 0 to 1 for fuse corners from lowest to highest corner -+ * Inner: large enough to hold the longest set of parameter segments which -+ * fully defines a fuse parameter, +1 (for NULL termination). -+ * Each segment corresponds to a contiguous group of bits from a -+ * single fuse row. These segments are concatentated together in -+ * order to form the full fuse parameter value. The segments for -+ * a given parameter may correspond to different fuse rows. -+ */ -+static struct cpr3_fuse_param -+ipq807x_npu_init_voltage_param[IPQ807x_NPU_FUSE_CORNERS][2] = { -+ {{73, 22, 27}, {} }, -+ {{73, 16, 21}, {} }, -+}; -+ -+/* -+ * Open loop voltage fuse reference voltages in microvolts for IPQ807x -+ */ -+static int -+ipq807x_npu_fuse_ref_volt [IPQ807x_NPU_FUSE_CORNERS] = { -+ 912000, -+ 992000, -+}; -+ -+/* -+ * IPQ9574 (Few parameters are changed, remaining are same as IPQ807x) -+ */ -+#define IPQ9574_NPU_FUSE_CORNERS 2 -+#define IPQ9574_NPU_FUSE_STEP_VOLT 10000 -+#define IPQ9574_NPU_CPR_CLOCK_RATE 24000000 -+ -+/* -+ * fues parameters for IPQ9574 -+ */ -+static struct cpr3_fuse_param -+ipq9574_npu_init_voltage_param[IPQ9574_NPU_FUSE_CORNERS][2] = { -+ {{105, 12, 17}, {} }, -+ {{105, 6, 11}, {} }, -+}; -+ -+/* -+ * Open loop voltage fuse reference voltages in microvolts for IPQ9574 -+ */ -+static int -+ipq9574_npu_fuse_ref_volt [IPQ9574_NPU_FUSE_CORNERS] = { -+ 862500, -+ 987500, -+}; -+ -+struct cpr3_controller *g_ctrl; -+ -+void cpr3_npu_temp_notify(int sensor, int temp, int low_notif) -+{ -+ u32 prev_sensor_state; -+ -+ if (sensor != NPU_TSENS) -+ return; -+ -+ prev_sensor_state = g_ctrl->cur_sensor_state; -+ if (low_notif) -+ g_ctrl->cur_sensor_state |= BIT(sensor); -+ else -+ g_ctrl->cur_sensor_state &= ~BIT(sensor); -+ -+ if (!prev_sensor_state && g_ctrl->cur_sensor_state) -+ cpr3_handle_temp_open_loop_adjustment(g_ctrl, true); -+ else if (prev_sensor_state && !g_ctrl->cur_sensor_state) -+ cpr3_handle_temp_open_loop_adjustment(g_ctrl, false); -+} -+ -+/** -+ * cpr3_ipq807x_npu_read_fuse_data() - load NPU specific fuse parameter values -+ * @vreg: Pointer to the CPR3 regulator -+ * -+ * This function allocates a cpr3_ipq807x_npu_fuses struct, fills it with -+ * values read out of hardware fuses, and finally copies common fuse values -+ * into the CPR3 regulator struct. -+ * -+ * Return: 0 on success, errno on failure -+ */ -+static int cpr3_ipq807x_npu_read_fuse_data(struct cpr3_regulator *vreg) -+{ -+ void __iomem *base = vreg->thread->ctrl->fuse_base; -+ struct cpr3_ipq807x_npu_fuses *fuse; -+ int i, rc; -+ -+ fuse = devm_kzalloc(vreg->thread->ctrl->dev, sizeof(*fuse), GFP_KERNEL); -+ if (!fuse) -+ return -ENOMEM; -+ -+ for (i = 0; i < g_valid_npu_fuse_count; i++) { -+ rc = cpr3_read_fuse_param(base, -+ vreg->cpr3_regulator_data->init_voltage_param[i], -+ &fuse->init_voltage[i]); -+ if (rc) { -+ cpr3_err(vreg, "Unable to read fuse-corner %d initial voltage fuse, rc=%d\n", -+ i, rc); -+ return rc; -+ } -+ } -+ -+ vreg->fuse_corner_count = g_valid_npu_fuse_count; -+ vreg->platform_fuses = fuse; -+ -+ return 0; -+} -+ -+/** -+ * cpr3_npu_parse_corner_data() - parse NPU corner data from device tree -+ * properties of the CPR3 regulator's device node -+ * @vreg: Pointer to the CPR3 regulator -+ * -+ * Return: 0 on success, errno on failure -+ */ -+static int cpr3_npu_parse_corner_data(struct cpr3_regulator *vreg) -+{ -+ int rc; -+ -+ rc = cpr3_parse_common_corner_data(vreg); -+ if (rc) { -+ cpr3_err(vreg, "error reading corner data, rc=%d\n", rc); -+ return rc; -+ } -+ -+ return rc; -+} -+ -+/** -+ * cpr3_ipq807x_npu_calculate_open_loop_voltages() - calculate the open-loop -+ * voltage for each corner of a CPR3 regulator -+ * @vreg: Pointer to the CPR3 regulator -+ * @temp_correction: Temperature based correction -+ * -+ * If open-loop voltage interpolation is allowed in device tree, then -+ * this function calculates the open-loop voltage for a given corner using -+ * linear interpolation. This interpolation is performed using the processor -+ * frequencies of the lower and higher Fmax corners along with their fused -+ * open-loop voltages. -+ * -+ * If open-loop voltage interpolation is not allowed, then this function uses -+ * the Fmax fused open-loop voltage for all of the corners associated with a -+ * given fuse corner. -+ * -+ * Return: 0 on success, errno on failure -+ */ -+static int cpr3_ipq807x_npu_calculate_open_loop_voltages( -+ struct cpr3_regulator *vreg, bool temp_correction) -+{ -+ struct cpr3_ipq807x_npu_fuses *fuse = vreg->platform_fuses; -+ struct cpr3_controller *ctrl = vreg->thread->ctrl; -+ int i, j, rc = 0; -+ u64 freq_low, volt_low, freq_high, volt_high; -+ int *fuse_volt; -+ int *fmax_corner; -+ -+ fuse_volt = kcalloc(vreg->fuse_corner_count, sizeof(*fuse_volt), -+ GFP_KERNEL); -+ fmax_corner = kcalloc(vreg->fuse_corner_count, sizeof(*fmax_corner), -+ GFP_KERNEL); -+ if (!fuse_volt || !fmax_corner) { -+ rc = -ENOMEM; -+ goto done; -+ } -+ -+ for (i = 0; i < vreg->fuse_corner_count; i++) { -+ if (ctrl->cpr_global_setting == CPR_DISABLED) -+ fuse_volt[i] = vreg->cpr3_regulator_data->fuse_ref_volt[i]; -+ else -+ fuse_volt[i] = cpr3_convert_open_loop_voltage_fuse( -+ vreg->cpr3_regulator_data->fuse_ref_volt[i], -+ vreg->cpr3_regulator_data->fuse_step_volt, -+ fuse->init_voltage[i], -+ IPQ807x_NPU_VOLTAGE_FUSE_SIZE); -+ -+ /* Log fused open-loop voltage values for debugging purposes. */ -+ cpr3_info(vreg, "fused %8s: open-loop=%7d uV\n", -+ cpr3_ipq807x_npu_fuse_corner_name[i], -+ fuse_volt[i]); -+ } -+ -+ rc = cpr3_determine_part_type(vreg, -+ fuse_volt[CPR3_IPQ807x_NPU_FUSE_CORNER_TURBO]); -+ if (rc) { -+ cpr3_err(vreg, -+ "fused part type detection failed failed, rc=%d\n", rc); -+ goto done; -+ } -+ -+ rc = cpr3_adjust_fused_open_loop_voltages(vreg, fuse_volt); -+ if (rc) { -+ cpr3_err(vreg, -+ "fused open-loop voltage adjustment failed, rc=%d\n", -+ rc); -+ goto done; -+ } -+ if (temp_correction) { -+ rc = cpr3_determine_temp_base_open_loop_correction(vreg, -+ fuse_volt); -+ if (rc) { -+ cpr3_err(vreg, -+ "temp open-loop voltage adj. failed, rc=%d\n", -+ rc); -+ goto done; -+ } -+ } -+ -+ for (i = 1; i < vreg->fuse_corner_count; i++) { -+ if (fuse_volt[i] < fuse_volt[i - 1]) { -+ cpr3_info(vreg, -+ "fuse corner %d voltage=%d uV < fuse corner %d \ -+ voltage=%d uV; overriding: fuse corner %d \ -+ voltage=%d\n", -+ i, fuse_volt[i], i - 1, fuse_volt[i - 1], -+ i, fuse_volt[i - 1]); -+ fuse_volt[i] = fuse_volt[i - 1]; -+ } -+ } -+ -+ /* Determine highest corner mapped to each fuse corner */ -+ j = vreg->fuse_corner_count - 1; -+ for (i = vreg->corner_count - 1; i >= 0; i--) { -+ if (vreg->corner[i].cpr_fuse_corner == j) { -+ fmax_corner[j] = i; -+ j--; -+ } -+ } -+ -+ if (j >= 0) { -+ cpr3_err(vreg, "invalid fuse corner mapping\n"); -+ rc = -EINVAL; -+ goto done; -+ } -+ -+ /* -+ * Interpolation is not possible for corners mapped to the lowest fuse -+ * corner so use the fuse corner value directly. -+ */ -+ for (i = 0; i <= fmax_corner[0]; i++) -+ vreg->corner[i].open_loop_volt = fuse_volt[0]; -+ -+ /* Interpolate voltages for the higher fuse corners. */ -+ for (i = 1; i < vreg->fuse_corner_count; i++) { -+ freq_low = vreg->corner[fmax_corner[i - 1]].proc_freq; -+ volt_low = fuse_volt[i - 1]; -+ freq_high = vreg->corner[fmax_corner[i]].proc_freq; -+ volt_high = fuse_volt[i]; -+ -+ for (j = fmax_corner[i - 1] + 1; j <= fmax_corner[i]; j++) -+ vreg->corner[j].open_loop_volt = cpr3_interpolate( -+ freq_low, volt_low, freq_high, volt_high, -+ vreg->corner[j].proc_freq); -+ } -+ -+done: -+ if (rc == 0) { -+ cpr3_debug(vreg, "unadjusted per-corner open-loop voltages:\n"); -+ for (i = 0; i < vreg->corner_count; i++) -+ cpr3_debug(vreg, "open-loop[%2d] = %d uV\n", i, -+ vreg->corner[i].open_loop_volt); -+ -+ rc = cpr3_adjust_open_loop_voltages(vreg); -+ if (rc) -+ cpr3_err(vreg, -+ "open-loop voltage adjustment failed, rc=%d\n", -+ rc); -+ } -+ -+ kfree(fuse_volt); -+ kfree(fmax_corner); -+ return rc; -+} -+ -+/** -+ * cpr3_npu_print_settings() - print out NPU CPR configuration settings into -+ * the kernel log for debugging purposes -+ * @vreg: Pointer to the CPR3 regulator -+ */ -+static void cpr3_npu_print_settings(struct cpr3_regulator *vreg) -+{ -+ struct cpr3_corner *corner; -+ int i; -+ -+ cpr3_debug(vreg, -+ "Corner: Frequency (Hz), Fuse Corner, Floor (uV), \ -+ Open-Loop (uV), Ceiling (uV)\n"); -+ for (i = 0; i < vreg->corner_count; i++) { -+ corner = &vreg->corner[i]; -+ cpr3_debug(vreg, "%3d: %10u, %2d, %7d, %7d, %7d\n", -+ i, corner->proc_freq, corner->cpr_fuse_corner, -+ corner->floor_volt, corner->open_loop_volt, -+ corner->ceiling_volt); -+ } -+ -+ if (vreg->thread->ctrl->apm) -+ cpr3_debug(vreg, "APM threshold = %d uV, APM adjust = %d uV\n", -+ vreg->thread->ctrl->apm_threshold_volt, -+ vreg->thread->ctrl->apm_adj_volt); -+} -+ -+/** -+ * cpr3_ipq807x_npu_calc_temp_based_ol_voltages() - Calculate the open loop -+ * voltages based on temperature based correction margins -+ * @vreg: Pointer to the CPR3 regulator -+ */ -+ -+static int -+cpr3_ipq807x_npu_calc_temp_based_ol_voltages(struct cpr3_regulator *vreg, -+ bool temp_correction) -+{ -+ int rc, i; -+ -+ rc = cpr3_ipq807x_npu_calculate_open_loop_voltages(vreg, -+ temp_correction); -+ if (rc) { -+ cpr3_err(vreg, -+ "unable to calculate open-loop voltages, rc=%d\n", rc); -+ return rc; -+ } -+ -+ rc = cpr3_limit_open_loop_voltages(vreg); -+ if (rc) { -+ cpr3_err(vreg, "unable to limit open-loop voltages, rc=%d\n", -+ rc); -+ return rc; -+ } -+ -+ cpr3_open_loop_voltage_as_ceiling(vreg); -+ -+ rc = cpr3_limit_floor_voltages(vreg); -+ if (rc) { -+ cpr3_err(vreg, "unable to limit floor voltages, rc=%d\n", rc); -+ return rc; -+ } -+ -+ for (i = 0; i < vreg->corner_count; i++) { -+ if (temp_correction) -+ vreg->corner[i].cold_temp_open_loop_volt = -+ vreg->corner[i].open_loop_volt; -+ else -+ vreg->corner[i].normal_temp_open_loop_volt = -+ vreg->corner[i].open_loop_volt; -+ } -+ -+ cpr3_npu_print_settings(vreg); -+ -+ return rc; -+} -+ -+/** -+ * cpr3_npu_init_thread() - perform steps necessary to initialize the -+ * configuration data for a CPR3 thread -+ * @thread: Pointer to the CPR3 thread -+ * -+ * Return: 0 on success, errno on failure -+ */ -+static int cpr3_npu_init_thread(struct cpr3_thread *thread) -+{ -+ int rc; -+ -+ rc = cpr3_parse_common_thread_data(thread); -+ if (rc) { -+ cpr3_err(thread->ctrl, -+ "thread %u CPR thread data from DT- failed, rc=%d\n", -+ thread->thread_id, rc); -+ return rc; -+ } -+ -+ return 0; -+} -+ -+/** -+ * cpr3_npu_init_regulator() - perform all steps necessary to initialize the -+ * configuration data for a CPR3 regulator -+ * @vreg: Pointer to the CPR3 regulator -+ * -+ * Return: 0 on success, errno on failure -+ */ -+static int cpr3_npu_init_regulator(struct cpr3_regulator *vreg) -+{ -+ struct cpr3_ipq807x_npu_fuses *fuse; -+ int rc, cold_temp = 0; -+ bool can_adj_cold_temp = cpr3_can_adjust_cold_temp(vreg); -+ -+ rc = cpr3_ipq807x_npu_read_fuse_data(vreg); -+ if (rc) { -+ cpr3_err(vreg, "unable to read CPR fuse data, rc=%d\n", rc); -+ return rc; -+ } -+ -+ fuse = vreg->platform_fuses; -+ -+ rc = cpr3_npu_parse_corner_data(vreg); -+ if (rc) { -+ cpr3_err(vreg, -+ "Cannot read CPR corner data from DT, rc=%d\n", rc); -+ return rc; -+ } -+ -+ rc = cpr3_mem_acc_init(vreg); -+ if (rc) { -+ if (rc != -EPROBE_DEFER) -+ cpr3_err(vreg, -+ "Cannot initialize mem-acc regulator settings, rc=%d\n", -+ rc); -+ return rc; -+ } -+ -+ if (can_adj_cold_temp) { -+ rc = cpr3_ipq807x_npu_calc_temp_based_ol_voltages(vreg, true); -+ if (rc) { -+ cpr3_err(vreg, -+ "unable to calculate open-loop voltages, rc=%d\n", rc); -+ return rc; -+ } -+ } -+ -+ rc = cpr3_ipq807x_npu_calc_temp_based_ol_voltages(vreg, false); -+ if (rc) { -+ cpr3_err(vreg, -+ "unable to calculate open-loop voltages, rc=%d\n", rc); -+ return rc; -+ } -+ -+ if (can_adj_cold_temp) { -+ cpr3_info(vreg, -+ "Normal and Cold condition init done. Default to normal.\n"); -+ -+ rc = cpr3_get_cold_temp_threshold(vreg, &cold_temp); -+ if (rc) { -+ cpr3_err(vreg, -+ "Get cold temperature threshold failed, rc=%d\n", rc); -+ return rc; -+ } -+ register_low_temp_notif(NPU_TSENS, cold_temp, -+ cpr3_npu_temp_notify); -+ } -+ -+ return rc; -+} -+ -+/** -+ * cpr3_npu_init_controller() - perform NPU CPR3 controller specific -+ * initializations -+ * @ctrl: Pointer to the CPR3 controller -+ * -+ * Return: 0 on success, errno on failure -+ */ -+static int cpr3_npu_init_controller(struct cpr3_controller *ctrl) -+{ -+ int rc; -+ -+ rc = cpr3_parse_open_loop_common_ctrl_data(ctrl); -+ if (rc) { -+ if (rc != -EPROBE_DEFER) -+ cpr3_err(ctrl, "unable to parse common controller data, rc=%d\n", -+ rc); -+ return rc; -+ } -+ -+ ctrl->ctrl_type = CPR_CTRL_TYPE_CPR3; -+ ctrl->supports_hw_closed_loop = false; -+ -+ return 0; -+} -+ -+static const struct cpr3_reg_data ipq807x_cpr_npu = { -+ .cpr_valid_fuse_count = IPQ807x_NPU_FUSE_CORNERS, -+ .init_voltage_param = ipq807x_npu_init_voltage_param, -+ .fuse_ref_volt = ipq807x_npu_fuse_ref_volt, -+ .fuse_step_volt = IPQ807x_NPU_FUSE_STEP_VOLT, -+ .cpr_clk_rate = IPQ807x_NPU_CPR_CLOCK_RATE, -+}; -+ -+static const struct cpr3_reg_data ipq817x_cpr_npu = { -+ .cpr_valid_fuse_count = IPQ817x_NPU_FUSE_CORNERS, -+ .init_voltage_param = ipq807x_npu_init_voltage_param, -+ .fuse_ref_volt = ipq807x_npu_fuse_ref_volt, -+ .fuse_step_volt = IPQ807x_NPU_FUSE_STEP_VOLT, -+ .cpr_clk_rate = IPQ807x_NPU_CPR_CLOCK_RATE, -+}; -+ -+static const struct cpr3_reg_data ipq9574_cpr_npu = { -+ .cpr_valid_fuse_count = IPQ9574_NPU_FUSE_CORNERS, -+ .init_voltage_param = ipq9574_npu_init_voltage_param, -+ .fuse_ref_volt = ipq9574_npu_fuse_ref_volt, -+ .fuse_step_volt = IPQ9574_NPU_FUSE_STEP_VOLT, -+ .cpr_clk_rate = IPQ9574_NPU_CPR_CLOCK_RATE, -+}; -+ -+static struct of_device_id cpr3_regulator_match_table[] = { -+ { -+ .compatible = "qcom,cpr3-ipq807x-npu-regulator", -+ .data = &ipq807x_cpr_npu -+ }, -+ { -+ .compatible = "qcom,cpr3-ipq817x-npu-regulator", -+ .data = &ipq817x_cpr_npu -+ }, -+ { -+ .compatible = "qcom,cpr3-ipq9574-npu-regulator", -+ .data = &ipq9574_cpr_npu -+ }, -+ {} -+}; -+ -+static int cpr3_npu_regulator_probe(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ struct cpr3_controller *ctrl; -+ int i, rc; -+ const struct of_device_id *match; -+ struct cpr3_reg_data *cpr_data; -+ -+ if (!dev->of_node) { -+ dev_err(dev, "Device tree node is missing\n"); -+ return -EINVAL; -+ } -+ -+ ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL); -+ if (!ctrl) -+ return -ENOMEM; -+ g_ctrl = ctrl; -+ -+ match = of_match_device(cpr3_regulator_match_table, &pdev->dev); -+ if (!match) -+ return -ENODEV; -+ -+ cpr_data = (struct cpr3_reg_data *)match->data; -+ g_valid_npu_fuse_count = cpr_data->cpr_valid_fuse_count; -+ dev_info(dev, "NPU CPR valid fuse count: %d\n", g_valid_npu_fuse_count); -+ ctrl->cpr_clock_rate = cpr_data->cpr_clk_rate; -+ -+ ctrl->dev = dev; -+ /* Set to false later if anything precludes CPR operation. */ -+ ctrl->cpr_allowed_hw = true; -+ -+ rc = of_property_read_string(dev->of_node, "qcom,cpr-ctrl-name", -+ &ctrl->name); -+ if (rc) { -+ cpr3_err(ctrl, "unable to read qcom,cpr-ctrl-name, rc=%d\n", -+ rc); -+ return rc; -+ } -+ -+ rc = cpr3_map_fuse_base(ctrl, pdev); -+ if (rc) { -+ cpr3_err(ctrl, "could not map fuse base address\n"); -+ return rc; -+ } -+ -+ rc = cpr3_read_tcsr_setting(ctrl, pdev, IPQ807x_NPU_CPR_TCSR_START, -+ IPQ807x_NPU_CPR_TCSR_END); -+ if (rc) { -+ cpr3_err(ctrl, "could not read CPR tcsr rsetting\n"); -+ return rc; -+ } -+ -+ rc = cpr3_allocate_threads(ctrl, 0, 0); -+ if (rc) { -+ cpr3_err(ctrl, "failed to allocate CPR thread array, rc=%d\n", -+ rc); -+ return rc; -+ } -+ -+ if (ctrl->thread_count != 1) { -+ cpr3_err(ctrl, "expected 1 thread but found %d\n", -+ ctrl->thread_count); -+ return -EINVAL; -+ } -+ -+ rc = cpr3_npu_init_controller(ctrl); -+ if (rc) { -+ if (rc != -EPROBE_DEFER) -+ cpr3_err(ctrl, "failed to initialize CPR controller parameters, rc=%d\n", -+ rc); -+ return rc; -+ } -+ -+ rc = cpr3_npu_init_thread(&ctrl->thread[0]); -+ if (rc) { -+ cpr3_err(ctrl, "thread initialization failed, rc=%d\n", rc); -+ return rc; -+ } -+ -+ for (i = 0; i < ctrl->thread[0].vreg_count; i++) { -+ ctrl->thread[0].vreg[i].cpr3_regulator_data = cpr_data; -+ rc = cpr3_npu_init_regulator(&ctrl->thread[0].vreg[i]); -+ if (rc) { -+ cpr3_err(&ctrl->thread[0].vreg[i], "regulator initialization failed, rc=%d\n", -+ rc); -+ return rc; -+ } -+ } -+ -+ platform_set_drvdata(pdev, ctrl); -+ -+ return cpr3_open_loop_regulator_register(pdev, ctrl); -+} -+ -+static int cpr3_npu_regulator_remove(struct platform_device *pdev) -+{ -+ struct cpr3_controller *ctrl = platform_get_drvdata(pdev); -+ -+ return cpr3_open_loop_regulator_unregister(ctrl); -+} -+ -+static struct platform_driver cpr3_npu_regulator_driver = { -+ .driver = { -+ .name = "qcom,cpr3-npu-regulator", -+ .of_match_table = cpr3_regulator_match_table, -+ .owner = THIS_MODULE, -+ }, -+ .probe = cpr3_npu_regulator_probe, -+ .remove = cpr3_npu_regulator_remove, -+}; -+ -+static int cpr3_regulator_init(void) -+{ -+ return platform_driver_register(&cpr3_npu_regulator_driver); -+} -+arch_initcall(cpr3_regulator_init); -+ -+static void cpr3_regulator_exit(void) -+{ -+ platform_driver_unregister(&cpr3_npu_regulator_driver); -+} -+module_exit(cpr3_regulator_exit); -+ -+MODULE_DESCRIPTION("QCOM CPR3 NPU regulator driver"); -+MODULE_LICENSE("Dual BSD/GPLv2"); -+MODULE_ALIAS("platform:npu-ipq807x"); ---- /dev/null -+++ b/drivers/regulator/cpr3-regulator.c -@@ -0,0 +1,5112 @@ -+/* -+ * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 and -+ * only 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. -+ */ -+ -+#define pr_fmt(fmt) "%s: " fmt, __func__ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "cpr3-regulator.h" -+ -+#define CPR3_REGULATOR_CORNER_INVALID (-1) -+#define CPR3_RO_MASK GENMASK(CPR3_RO_COUNT - 1, 0) -+ -+/* CPR3 registers */ -+#define CPR3_REG_CPR_CTL 0x4 -+#define CPR3_CPR_CTL_LOOP_EN_MASK BIT(0) -+#define CPR3_CPR_CTL_LOOP_ENABLE BIT(0) -+#define CPR3_CPR_CTL_LOOP_DISABLE 0 -+#define CPR3_CPR_CTL_IDLE_CLOCKS_MASK GENMASK(5, 1) -+#define CPR3_CPR_CTL_IDLE_CLOCKS_SHIFT 1 -+#define CPR3_CPR_CTL_COUNT_MODE_MASK GENMASK(7, 6) -+#define CPR3_CPR_CTL_COUNT_MODE_SHIFT 6 -+#define CPR3_CPR_CTL_COUNT_MODE_ALL_AT_ONCE_MIN 0 -+#define CPR3_CPR_CTL_COUNT_MODE_ALL_AT_ONCE_MAX 1 -+#define CPR3_CPR_CTL_COUNT_MODE_STAGGERED 2 -+#define CPR3_CPR_CTL_COUNT_MODE_ALL_AT_ONCE_AGE 3 -+#define CPR3_CPR_CTL_COUNT_REPEAT_MASK GENMASK(31, 9) -+#define CPR3_CPR_CTL_COUNT_REPEAT_SHIFT 9 -+ -+#define CPR3_REG_CPR_STATUS 0x8 -+#define CPR3_CPR_STATUS_BUSY_MASK BIT(0) -+#define CPR3_CPR_STATUS_AGING_MEASUREMENT_MASK BIT(1) -+ -+/* -+ * This register is not present on controllers that support HW closed-loop -+ * except CPR4 APSS controller. -+ */ -+#define CPR3_REG_CPR_TIMER_AUTO_CONT 0xC -+ -+#define CPR3_REG_CPR_STEP_QUOT 0x14 -+#define CPR3_CPR_STEP_QUOT_MIN_MASK GENMASK(5, 0) -+#define CPR3_CPR_STEP_QUOT_MIN_SHIFT 0 -+#define CPR3_CPR_STEP_QUOT_MAX_MASK GENMASK(11, 6) -+#define CPR3_CPR_STEP_QUOT_MAX_SHIFT 6 -+ -+#define CPR3_REG_GCNT(ro) (0xA0 + 0x4 * (ro)) -+ -+#define CPR3_REG_SENSOR_BYPASS_WRITE(sensor) (0xE0 + 0x4 * ((sensor) / 32)) -+#define CPR3_REG_SENSOR_BYPASS_WRITE_BANK(bank) (0xE0 + 0x4 * (bank)) -+ -+#define CPR3_REG_SENSOR_MASK_WRITE(sensor) (0x120 + 0x4 * ((sensor) / 32)) -+#define CPR3_REG_SENSOR_MASK_WRITE_BANK(bank) (0x120 + 0x4 * (bank)) -+#define CPR3_REG_SENSOR_MASK_READ(sensor) (0x140 + 0x4 * ((sensor) / 32)) -+ -+#define CPR3_REG_SENSOR_OWNER(sensor) (0x200 + 0x4 * (sensor)) -+ -+#define CPR3_REG_CONT_CMD 0x800 -+#define CPR3_CONT_CMD_ACK 0x1 -+#define CPR3_CONT_CMD_NACK 0x0 -+ -+#define CPR3_REG_THRESH(thread) (0x808 + 0x440 * (thread)) -+#define CPR3_THRESH_CONS_DOWN_MASK GENMASK(3, 0) -+#define CPR3_THRESH_CONS_DOWN_SHIFT 0 -+#define CPR3_THRESH_CONS_UP_MASK GENMASK(7, 4) -+#define CPR3_THRESH_CONS_UP_SHIFT 4 -+#define CPR3_THRESH_DOWN_THRESH_MASK GENMASK(12, 8) -+#define CPR3_THRESH_DOWN_THRESH_SHIFT 8 -+#define CPR3_THRESH_UP_THRESH_MASK GENMASK(17, 13) -+#define CPR3_THRESH_UP_THRESH_SHIFT 13 -+ -+#define CPR3_REG_RO_MASK(thread) (0x80C + 0x440 * (thread)) -+ -+#define CPR3_REG_RESULT0(thread) (0x810 + 0x440 * (thread)) -+#define CPR3_RESULT0_BUSY_MASK BIT(0) -+#define CPR3_RESULT0_STEP_DN_MASK BIT(1) -+#define CPR3_RESULT0_STEP_UP_MASK BIT(2) -+#define CPR3_RESULT0_ERROR_STEPS_MASK GENMASK(7, 3) -+#define CPR3_RESULT0_ERROR_STEPS_SHIFT 3 -+#define CPR3_RESULT0_ERROR_MASK GENMASK(19, 8) -+#define CPR3_RESULT0_ERROR_SHIFT 8 -+#define CPR3_RESULT0_NEGATIVE_MASK BIT(20) -+ -+#define CPR3_REG_RESULT1(thread) (0x814 + 0x440 * (thread)) -+#define CPR3_RESULT1_QUOT_MIN_MASK GENMASK(11, 0) -+#define CPR3_RESULT1_QUOT_MIN_SHIFT 0 -+#define CPR3_RESULT1_QUOT_MAX_MASK GENMASK(23, 12) -+#define CPR3_RESULT1_QUOT_MAX_SHIFT 12 -+#define CPR3_RESULT1_RO_MIN_MASK GENMASK(27, 24) -+#define CPR3_RESULT1_RO_MIN_SHIFT 24 -+#define CPR3_RESULT1_RO_MAX_MASK GENMASK(31, 28) -+#define CPR3_RESULT1_RO_MAX_SHIFT 28 -+ -+#define CPR3_REG_RESULT2(thread) (0x818 + 0x440 * (thread)) -+#define CPR3_RESULT2_STEP_QUOT_MIN_MASK GENMASK(5, 0) -+#define CPR3_RESULT2_STEP_QUOT_MIN_SHIFT 0 -+#define CPR3_RESULT2_STEP_QUOT_MAX_MASK GENMASK(11, 6) -+#define CPR3_RESULT2_STEP_QUOT_MAX_SHIFT 6 -+#define CPR3_RESULT2_SENSOR_MIN_MASK GENMASK(23, 16) -+#define CPR3_RESULT2_SENSOR_MIN_SHIFT 16 -+#define CPR3_RESULT2_SENSOR_MAX_MASK GENMASK(31, 24) -+#define CPR3_RESULT2_SENSOR_MAX_SHIFT 24 -+ -+#define CPR3_REG_IRQ_EN 0x81C -+#define CPR3_REG_IRQ_CLEAR 0x820 -+#define CPR3_REG_IRQ_STATUS 0x824 -+#define CPR3_IRQ_UP BIT(3) -+#define CPR3_IRQ_MID BIT(2) -+#define CPR3_IRQ_DOWN BIT(1) -+ -+#define CPR3_REG_TARGET_QUOT(thread, ro) \ -+ (0x840 + 0x440 * (thread) + 0x4 * (ro)) -+ -+/* Registers found only on controllers that support HW closed-loop. */ -+#define CPR3_REG_PD_THROTTLE 0xE8 -+#define CPR3_PD_THROTTLE_DISABLE 0x0 -+ -+#define CPR3_REG_HW_CLOSED_LOOP 0x3000 -+#define CPR3_HW_CLOSED_LOOP_ENABLE 0x0 -+#define CPR3_HW_CLOSED_LOOP_DISABLE 0x1 -+ -+#define CPR3_REG_CPR_TIMER_MID_CONT 0x3004 -+#define CPR3_REG_CPR_TIMER_UP_DN_CONT 0x3008 -+ -+#define CPR3_REG_LAST_MEASUREMENT 0x7F8 -+#define CPR3_LAST_MEASUREMENT_THREAD_DN_SHIFT 0 -+#define CPR3_LAST_MEASUREMENT_THREAD_UP_SHIFT 4 -+#define CPR3_LAST_MEASUREMENT_THREAD_DN(thread) \ -+ (BIT(thread) << CPR3_LAST_MEASUREMENT_THREAD_DN_SHIFT) -+#define CPR3_LAST_MEASUREMENT_THREAD_UP(thread) \ -+ (BIT(thread) << CPR3_LAST_MEASUREMENT_THREAD_UP_SHIFT) -+#define CPR3_LAST_MEASUREMENT_AGGR_DN BIT(8) -+#define CPR3_LAST_MEASUREMENT_AGGR_MID BIT(9) -+#define CPR3_LAST_MEASUREMENT_AGGR_UP BIT(10) -+#define CPR3_LAST_MEASUREMENT_VALID BIT(11) -+#define CPR3_LAST_MEASUREMENT_SAW_ERROR BIT(12) -+#define CPR3_LAST_MEASUREMENT_PD_BYPASS_MASK GENMASK(23, 16) -+#define CPR3_LAST_MEASUREMENT_PD_BYPASS_SHIFT 16 -+ -+/* CPR4 controller specific registers and bit definitions */ -+#define CPR4_REG_CPR_TIMER_CLAMP 0x10 -+#define CPR4_CPR_TIMER_CLAMP_THREAD_AGGREGATION_EN BIT(27) -+ -+#define CPR4_REG_MISC 0x700 -+#define CPR4_MISC_MARGIN_TABLE_ROW_SELECT_MASK GENMASK(23, 20) -+#define CPR4_MISC_MARGIN_TABLE_ROW_SELECT_SHIFT 20 -+#define CPR4_MISC_TEMP_SENSOR_ID_START_MASK GENMASK(27, 24) -+#define CPR4_MISC_TEMP_SENSOR_ID_START_SHIFT 24 -+#define CPR4_MISC_TEMP_SENSOR_ID_END_MASK GENMASK(31, 28) -+#define CPR4_MISC_TEMP_SENSOR_ID_END_SHIFT 28 -+ -+#define CPR4_REG_SAW_ERROR_STEP_LIMIT 0x7A4 -+#define CPR4_SAW_ERROR_STEP_LIMIT_UP_MASK GENMASK(4, 0) -+#define CPR4_SAW_ERROR_STEP_LIMIT_UP_SHIFT 0 -+#define CPR4_SAW_ERROR_STEP_LIMIT_DN_MASK GENMASK(9, 5) -+#define CPR4_SAW_ERROR_STEP_LIMIT_DN_SHIFT 5 -+ -+#define CPR4_REG_MARGIN_TEMP_CORE_TIMERS 0x7A8 -+#define CPR4_MARGIN_TEMP_CORE_TIMERS_SETTLE_VOLTAGE_COUNT_MASK GENMASK(28, 18) -+#define CPR4_MARGIN_TEMP_CORE_TIMERS_SETTLE_VOLTAGE_COUNT_SHIFT 18 -+ -+#define CPR4_REG_MARGIN_TEMP_CORE(core) (0x7AC + 0x4 * (core)) -+#define CPR4_MARGIN_TEMP_CORE_ADJ_MASK GENMASK(7, 0) -+#define CPR4_MARGIN_TEMP_CORE_ADJ_SHIFT 8 -+ -+#define CPR4_REG_MARGIN_TEMP_POINT0N1 0x7F0 -+#define CPR4_MARGIN_TEMP_POINT0_MASK GENMASK(11, 0) -+#define CPR4_MARGIN_TEMP_POINT0_SHIFT 0 -+#define CPR4_MARGIN_TEMP_POINT1_MASK GENMASK(23, 12) -+#define CPR4_MARGIN_TEMP_POINT1_SHIFT 12 -+#define CPR4_REG_MARGIN_TEMP_POINT2 0x7F4 -+#define CPR4_MARGIN_TEMP_POINT2_MASK GENMASK(11, 0) -+#define CPR4_MARGIN_TEMP_POINT2_SHIFT 0 -+ -+#define CPR4_REG_MARGIN_ADJ_CTL 0x7F8 -+#define CPR4_MARGIN_ADJ_CTL_BOOST_EN BIT(0) -+#define CPR4_MARGIN_ADJ_CTL_CORE_ADJ_EN BIT(1) -+#define CPR4_MARGIN_ADJ_CTL_TEMP_ADJ_EN BIT(2) -+#define CPR4_MARGIN_ADJ_CTL_TIMER_SETTLE_VOLTAGE_EN BIT(3) -+#define CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_EN_MASK BIT(4) -+#define CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_ENABLE BIT(4) -+#define CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_DISABLE 0 -+#define CPR4_MARGIN_ADJ_CTL_PER_RO_KV_MARGIN_EN BIT(7) -+#define CPR4_MARGIN_ADJ_CTL_KV_MARGIN_ADJ_EN BIT(8) -+#define CPR4_MARGIN_ADJ_CTL_PMIC_STEP_SIZE_MASK GENMASK(16, 12) -+#define CPR4_MARGIN_ADJ_CTL_PMIC_STEP_SIZE_SHIFT 12 -+#define CPR4_MARGIN_ADJ_CTL_INITIAL_TEMP_BAND_MASK GENMASK(21, 19) -+#define CPR4_MARGIN_ADJ_CTL_INITIAL_TEMP_BAND_SHIFT 19 -+#define CPR4_MARGIN_ADJ_CTL_MAX_NUM_CORES_MASK GENMASK(25, 22) -+#define CPR4_MARGIN_ADJ_CTL_MAX_NUM_CORES_SHIFT 22 -+#define CPR4_MARGIN_ADJ_CTL_KV_MARGIN_ADJ_STEP_QUOT_MASK GENMASK(31, 26) -+#define CPR4_MARGIN_ADJ_CTL_KV_MARGIN_ADJ_STEP_QUOT_SHIFT 26 -+ -+#define CPR4_REG_CPR_MASK_THREAD(thread) (0x80C + 0x440 * (thread)) -+#define CPR4_CPR_MASK_THREAD_DISABLE_THREAD BIT(31) -+#define CPR4_CPR_MASK_THREAD_RO_MASK4THREAD_MASK GENMASK(15, 0) -+ -+/* -+ * The amount of time to wait for the CPR controller to become idle when -+ * performing an aging measurement. -+ */ -+#define CPR3_AGING_MEASUREMENT_TIMEOUT_NS 5000000 -+ -+/* -+ * The number of individual aging measurements to perform which are then -+ * averaged together in order to determine the final aging adjustment value. -+ */ -+#define CPR3_AGING_MEASUREMENT_ITERATIONS 16 -+ -+/* -+ * Aging measurements for the aged and unaged ring oscillators take place a few -+ * microseconds apart. If the vdd-supply voltage fluctuates between the two -+ * measurements, then the difference between them will be incorrect. The -+ * difference could end up too high or too low. This constant defines the -+ * number of lowest and highest measurements to ignore when averaging. -+ */ -+#define CPR3_AGING_MEASUREMENT_FILTER 3 -+ -+/* -+ * The number of times to attempt the full aging measurement sequence before -+ * declaring a measurement failure. -+ */ -+#define CPR3_AGING_RETRY_COUNT 5 -+ -+/* -+ * The maximum time to wait in microseconds for a CPR register write to -+ * complete. -+ */ -+#define CPR3_REGISTER_WRITE_DELAY_US 200 -+ -+static DEFINE_MUTEX(cpr3_controller_list_mutex); -+static LIST_HEAD(cpr3_controller_list); -+static struct dentry *cpr3_debugfs_base; -+ -+/** -+ * cpr3_read() - read four bytes from the memory address specified -+ * @ctrl: Pointer to the CPR3 controller -+ * @offset: Offset in bytes from the CPR3 controller's base address -+ * -+ * Return: memory address value -+ */ -+static inline u32 cpr3_read(struct cpr3_controller *ctrl, u32 offset) -+{ -+ if (!ctrl->cpr_enabled) { -+ cpr3_err(ctrl, "CPR register reads are not possible when CPR clocks are disabled\n"); -+ return 0; -+ } -+ -+ return readl_relaxed(ctrl->cpr_ctrl_base + offset); -+} -+ -+/** -+ * cpr3_write() - write four bytes to the memory address specified -+ * @ctrl: Pointer to the CPR3 controller -+ * @offset: Offset in bytes from the CPR3 controller's base address -+ * @value: Value to write to the memory address -+ * -+ * Return: none -+ */ -+static inline void cpr3_write(struct cpr3_controller *ctrl, u32 offset, -+ u32 value) -+{ -+ if (!ctrl->cpr_enabled) { -+ cpr3_err(ctrl, "CPR register writes are not possible when CPR clocks are disabled\n"); -+ return; -+ } -+ -+ writel_relaxed(value, ctrl->cpr_ctrl_base + offset); -+} -+ -+/** -+ * cpr3_masked_write() - perform a read-modify-write sequence so that only -+ * masked bits are modified -+ * @ctrl: Pointer to the CPR3 controller -+ * @offset: Offset in bytes from the CPR3 controller's base address -+ * @mask: Mask identifying the bits that should be modified -+ * @value: Value to write to the memory address -+ * -+ * Return: none -+ */ -+static inline void cpr3_masked_write(struct cpr3_controller *ctrl, u32 offset, -+ u32 mask, u32 value) -+{ -+ u32 reg_val, orig_val; -+ -+ if (!ctrl->cpr_enabled) { -+ cpr3_err(ctrl, "CPR register writes are not possible when CPR clocks are disabled\n"); -+ return; -+ } -+ -+ reg_val = orig_val = readl_relaxed(ctrl->cpr_ctrl_base + offset); -+ reg_val &= ~mask; -+ reg_val |= value & mask; -+ -+ if (reg_val != orig_val) -+ writel_relaxed(reg_val, ctrl->cpr_ctrl_base + offset); -+} -+ -+/** -+ * cpr3_ctrl_loop_enable() - enable the CPR sensing loop for a given controller -+ * @ctrl: Pointer to the CPR3 controller -+ * -+ * Return: none -+ */ -+static inline void cpr3_ctrl_loop_enable(struct cpr3_controller *ctrl) -+{ -+ if (ctrl->cpr_enabled && !(ctrl->aggr_corner.sdelta -+ && ctrl->aggr_corner.sdelta->allow_boost)) -+ cpr3_masked_write(ctrl, CPR3_REG_CPR_CTL, -+ CPR3_CPR_CTL_LOOP_EN_MASK, CPR3_CPR_CTL_LOOP_ENABLE); -+} -+ -+/** -+ * cpr3_ctrl_loop_disable() - disable the CPR sensing loop for a given -+ * controller -+ * @ctrl: Pointer to the CPR3 controller -+ * -+ * Return: none -+ */ -+static inline void cpr3_ctrl_loop_disable(struct cpr3_controller *ctrl) -+{ -+ if (ctrl->cpr_enabled) -+ cpr3_masked_write(ctrl, CPR3_REG_CPR_CTL, -+ CPR3_CPR_CTL_LOOP_EN_MASK, CPR3_CPR_CTL_LOOP_DISABLE); -+} -+ -+/** -+ * cpr3_clock_enable() - prepare and enable all clocks used by this CPR3 -+ * controller -+ * @ctrl: Pointer to the CPR3 controller -+ * -+ * Return: 0 on success, errno on failure -+ */ -+static int cpr3_clock_enable(struct cpr3_controller *ctrl) -+{ -+ int rc; -+ -+ rc = clk_prepare_enable(ctrl->bus_clk); -+ if (rc) { -+ cpr3_err(ctrl, "failed to enable bus clock, rc=%d\n", rc); -+ return rc; -+ } -+ -+ rc = clk_prepare_enable(ctrl->iface_clk); -+ if (rc) { -+ cpr3_err(ctrl, "failed to enable interface clock, rc=%d\n", rc); -+ clk_disable_unprepare(ctrl->bus_clk); -+ return rc; -+ } -+ -+ rc = clk_prepare_enable(ctrl->core_clk); -+ if (rc) { -+ cpr3_err(ctrl, "failed to enable core clock, rc=%d\n", rc); -+ clk_disable_unprepare(ctrl->iface_clk); -+ clk_disable_unprepare(ctrl->bus_clk); -+ return rc; -+ } -+ -+ return 0; -+} -+ -+/** -+ * cpr3_clock_disable() - disable and unprepare all clocks used by this CPR3 -+ * controller -+ * @ctrl: Pointer to the CPR3 controller -+ * -+ * Return: none -+ */ -+static void cpr3_clock_disable(struct cpr3_controller *ctrl) -+{ -+ clk_disable_unprepare(ctrl->core_clk); -+ clk_disable_unprepare(ctrl->iface_clk); -+ clk_disable_unprepare(ctrl->bus_clk); -+} -+ -+/** -+ * cpr3_ctrl_clear_cpr4_config() - clear the CPR4 register configuration -+ * programmed for current aggregated corner of a given controller -+ * @ctrl: Pointer to the CPR3 controller -+ * -+ * Return: 0 on success, errno on failure -+ */ -+static inline int cpr3_ctrl_clear_cpr4_config(struct cpr3_controller *ctrl) -+{ -+ struct cpr4_sdelta *aggr_sdelta = ctrl->aggr_corner.sdelta; -+ bool cpr_enabled = ctrl->cpr_enabled; -+ int i, rc = 0; -+ -+ if (!aggr_sdelta || !(aggr_sdelta->allow_core_count_adj -+ || aggr_sdelta->allow_temp_adj || aggr_sdelta->allow_boost)) -+ /* cpr4 features are not enabled */ -+ return 0; -+ -+ /* Ensure that CPR clocks are enabled before writing to registers. */ -+ if (!cpr_enabled) { -+ rc = cpr3_clock_enable(ctrl); -+ if (rc) { -+ cpr3_err(ctrl, "clock enable failed, rc=%d\n", rc); -+ return rc; -+ } -+ ctrl->cpr_enabled = true; -+ } -+ -+ /* -+ * Clear feature enable configuration made for current -+ * aggregated corner. -+ */ -+ cpr3_masked_write(ctrl, CPR4_REG_MARGIN_ADJ_CTL, -+ CPR4_MARGIN_ADJ_CTL_MAX_NUM_CORES_MASK -+ | CPR4_MARGIN_ADJ_CTL_CORE_ADJ_EN -+ | CPR4_MARGIN_ADJ_CTL_TEMP_ADJ_EN -+ | CPR4_MARGIN_ADJ_CTL_KV_MARGIN_ADJ_EN -+ | CPR4_MARGIN_ADJ_CTL_BOOST_EN -+ | CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_EN_MASK, 0); -+ -+ cpr3_masked_write(ctrl, CPR4_REG_MISC, -+ CPR4_MISC_MARGIN_TABLE_ROW_SELECT_MASK, -+ 0 << CPR4_MISC_MARGIN_TABLE_ROW_SELECT_SHIFT); -+ -+ for (i = 0; i <= aggr_sdelta->max_core_count; i++) { -+ /* Clear voltage margin adjustments programmed in TEMP_COREi */ -+ cpr3_write(ctrl, CPR4_REG_MARGIN_TEMP_CORE(i), 0); -+ } -+ -+ /* Turn off CPR clocks if they were off before this function call. */ -+ if (!cpr_enabled) { -+ cpr3_clock_disable(ctrl); -+ ctrl->cpr_enabled = false; -+ } -+ -+ return 0; -+} -+ -+/** -+ * cpr3_closed_loop_enable() - enable logical CPR closed-loop operation -+ * @ctrl: Pointer to the CPR3 controller -+ * -+ * Return: 0 on success, errno on failure -+ */ -+static int cpr3_closed_loop_enable(struct cpr3_controller *ctrl) -+{ -+ int rc; -+ -+ if (!ctrl->cpr_allowed_hw || !ctrl->cpr_allowed_sw) { -+ cpr3_err(ctrl, "cannot enable closed-loop CPR operation because it is disallowed\n"); -+ return -EPERM; -+ } else if (ctrl->cpr_enabled) { -+ /* Already enabled */ -+ return 0; -+ } else if (ctrl->cpr_suspended) { -+ /* -+ * CPR must remain disabled as the system is entering suspend. -+ */ -+ return 0; -+ } -+ -+ rc = cpr3_clock_enable(ctrl); -+ if (rc) { -+ cpr3_err(ctrl, "unable to enable CPR clocks, rc=%d\n", rc); -+ return rc; -+ } -+ -+ ctrl->cpr_enabled = true; -+ cpr3_debug(ctrl, "CPR closed-loop operation enabled\n"); -+ -+ return 0; -+} -+ -+/** -+ * cpr3_closed_loop_disable() - disable logical CPR closed-loop operation -+ * @ctrl: Pointer to the CPR3 controller -+ * -+ * Return: 0 on success, errno on failure -+ */ -+static inline int cpr3_closed_loop_disable(struct cpr3_controller *ctrl) -+{ -+ if (!ctrl->cpr_enabled) { -+ /* Already disabled */ -+ return 0; -+ } -+ -+ cpr3_clock_disable(ctrl); -+ ctrl->cpr_enabled = false; -+ cpr3_debug(ctrl, "CPR closed-loop operation disabled\n"); -+ -+ return 0; -+} -+ -+/** -+ * cpr3_regulator_get_gcnt() - returns the GCNT register value corresponding -+ * to the clock rate and sensor time of the CPR3 controller -+ * @ctrl: Pointer to the CPR3 controller -+ * -+ * Return: GCNT value -+ */ -+static u32 cpr3_regulator_get_gcnt(struct cpr3_controller *ctrl) -+{ -+ u64 temp; -+ unsigned int remainder; -+ u32 gcnt; -+ -+ temp = (u64)ctrl->cpr_clock_rate * (u64)ctrl->sensor_time; -+ remainder = do_div(temp, 1000000000); -+ if (remainder) -+ temp++; -+ /* -+ * GCNT == 0 corresponds to a single ref clock measurement interval so -+ * offset GCNT values by 1. -+ */ -+ gcnt = temp - 1; -+ -+ return gcnt; -+} -+ -+/** -+ * cpr3_regulator_init_thread() - performs hardware initialization of CPR -+ * thread registers -+ * @thread: Pointer to the CPR3 thread -+ * -+ * CPR interface/bus clocks must be enabled before calling this function. -+ * -+ * Return: 0 on success, errno on failure -+ */ -+static int cpr3_regulator_init_thread(struct cpr3_thread *thread) -+{ -+ u32 reg; -+ -+ reg = (thread->consecutive_up << CPR3_THRESH_CONS_UP_SHIFT) -+ & CPR3_THRESH_CONS_UP_MASK; -+ reg |= (thread->consecutive_down << CPR3_THRESH_CONS_DOWN_SHIFT) -+ & CPR3_THRESH_CONS_DOWN_MASK; -+ reg |= (thread->up_threshold << CPR3_THRESH_UP_THRESH_SHIFT) -+ & CPR3_THRESH_UP_THRESH_MASK; -+ reg |= (thread->down_threshold << CPR3_THRESH_DOWN_THRESH_SHIFT) -+ & CPR3_THRESH_DOWN_THRESH_MASK; -+ -+ cpr3_write(thread->ctrl, CPR3_REG_THRESH(thread->thread_id), reg); -+ -+ /* -+ * Mask all RO's initially so that unused thread doesn't contribute -+ * to closed-loop voltage. -+ */ -+ cpr3_write(thread->ctrl, CPR3_REG_RO_MASK(thread->thread_id), -+ CPR3_RO_MASK); -+ -+ return 0; -+} -+ -+/** -+ * cpr4_regulator_init_temp_points() - performs hardware initialization of CPR4 -+ * registers to track tsen temperature data and also specify the -+ * temperature band range values to apply different voltage margins -+ * @ctrl: Pointer to the CPR3 controller -+ * -+ * CPR interface/bus clocks must be enabled before calling this function. -+ * -+ * Return: 0 on success, errno on failure -+ */ -+static int cpr4_regulator_init_temp_points(struct cpr3_controller *ctrl) -+{ -+ if (!ctrl->allow_temp_adj) -+ return 0; -+ -+ cpr3_masked_write(ctrl, CPR4_REG_MISC, -+ CPR4_MISC_TEMP_SENSOR_ID_START_MASK, -+ ctrl->temp_sensor_id_start -+ << CPR4_MISC_TEMP_SENSOR_ID_START_SHIFT); -+ -+ cpr3_masked_write(ctrl, CPR4_REG_MISC, -+ CPR4_MISC_TEMP_SENSOR_ID_END_MASK, -+ ctrl->temp_sensor_id_end -+ << CPR4_MISC_TEMP_SENSOR_ID_END_SHIFT); -+ -+ cpr3_masked_write(ctrl, CPR4_REG_MARGIN_TEMP_POINT2, -+ CPR4_MARGIN_TEMP_POINT2_MASK, -+ (ctrl->temp_band_count == 4 ? ctrl->temp_points[2] : 0x7FF) -+ << CPR4_MARGIN_TEMP_POINT2_SHIFT); -+ -+ cpr3_masked_write(ctrl, CPR4_REG_MARGIN_TEMP_POINT0N1, -+ CPR4_MARGIN_TEMP_POINT1_MASK, -+ (ctrl->temp_band_count >= 3 ? ctrl->temp_points[1] : 0x7FF) -+ << CPR4_MARGIN_TEMP_POINT1_SHIFT); -+ -+ cpr3_masked_write(ctrl, CPR4_REG_MARGIN_TEMP_POINT0N1, -+ CPR4_MARGIN_TEMP_POINT0_MASK, -+ (ctrl->temp_band_count >= 2 ? ctrl->temp_points[0] : 0x7FF) -+ << CPR4_MARGIN_TEMP_POINT0_SHIFT); -+ return 0; -+} -+ -+/** -+ * cpr3_regulator_init_cpr4() - performs hardware initialization at the -+ * controller and thread level required for CPR4 operation. -+ * @ctrl: Pointer to the CPR3 controller -+ * -+ * CPR interface/bus clocks must be enabled before calling this function. -+ * This function allocates sdelta structures and sdelta tables for aggregated -+ * corners of the controller and its threads. -+ * -+ * Return: 0 on success, errno on failure -+ */ -+static int cpr3_regulator_init_cpr4(struct cpr3_controller *ctrl) -+{ -+ struct cpr3_thread *thread; -+ struct cpr3_regulator *vreg; -+ struct cpr4_sdelta *sdelta; -+ int i, j, ctrl_max_core_count, thread_max_core_count, rc = 0; -+ bool ctrl_valid_sdelta, thread_valid_sdelta; -+ u32 pmic_step_size = 1; -+ int thread_id = 0; -+ u64 temp; -+ -+ if (ctrl->supports_hw_closed_loop) { -+ if (ctrl->saw_use_unit_mV) -+ pmic_step_size = ctrl->step_volt / 1000; -+ cpr3_masked_write(ctrl, CPR4_REG_MARGIN_ADJ_CTL, -+ CPR4_MARGIN_ADJ_CTL_PMIC_STEP_SIZE_MASK, -+ (pmic_step_size -+ << CPR4_MARGIN_ADJ_CTL_PMIC_STEP_SIZE_SHIFT)); -+ -+ cpr3_masked_write(ctrl, CPR4_REG_SAW_ERROR_STEP_LIMIT, -+ CPR4_SAW_ERROR_STEP_LIMIT_DN_MASK, -+ (ctrl->down_error_step_limit -+ << CPR4_SAW_ERROR_STEP_LIMIT_DN_SHIFT)); -+ -+ cpr3_masked_write(ctrl, CPR4_REG_SAW_ERROR_STEP_LIMIT, -+ CPR4_SAW_ERROR_STEP_LIMIT_UP_MASK, -+ (ctrl->up_error_step_limit -+ << CPR4_SAW_ERROR_STEP_LIMIT_UP_SHIFT)); -+ -+ /* -+ * Enable thread aggregation regardless of which threads are -+ * enabled or disabled. -+ */ -+ cpr3_masked_write(ctrl, CPR4_REG_CPR_TIMER_CLAMP, -+ CPR4_CPR_TIMER_CLAMP_THREAD_AGGREGATION_EN, -+ CPR4_CPR_TIMER_CLAMP_THREAD_AGGREGATION_EN); -+ -+ switch (ctrl->thread_count) { -+ case 0: -+ /* Disable both threads */ -+ cpr3_masked_write(ctrl, CPR4_REG_CPR_MASK_THREAD(0), -+ CPR4_CPR_MASK_THREAD_DISABLE_THREAD -+ | CPR4_CPR_MASK_THREAD_RO_MASK4THREAD_MASK, -+ CPR4_CPR_MASK_THREAD_DISABLE_THREAD -+ | CPR4_CPR_MASK_THREAD_RO_MASK4THREAD_MASK); -+ -+ cpr3_masked_write(ctrl, CPR4_REG_CPR_MASK_THREAD(1), -+ CPR4_CPR_MASK_THREAD_DISABLE_THREAD -+ | CPR4_CPR_MASK_THREAD_RO_MASK4THREAD_MASK, -+ CPR4_CPR_MASK_THREAD_DISABLE_THREAD -+ | CPR4_CPR_MASK_THREAD_RO_MASK4THREAD_MASK); -+ break; -+ case 1: -+ /* Disable unused thread */ -+ thread_id = ctrl->thread[0].thread_id ? 0 : 1; -+ cpr3_masked_write(ctrl, -+ CPR4_REG_CPR_MASK_THREAD(thread_id), -+ CPR4_CPR_MASK_THREAD_DISABLE_THREAD -+ | CPR4_CPR_MASK_THREAD_RO_MASK4THREAD_MASK, -+ CPR4_CPR_MASK_THREAD_DISABLE_THREAD -+ | CPR4_CPR_MASK_THREAD_RO_MASK4THREAD_MASK); -+ break; -+ } -+ } -+ -+ if (!ctrl->allow_core_count_adj && !ctrl->allow_temp_adj -+ && !ctrl->allow_boost) { -+ /* -+ * Skip below configuration as none of the features -+ * are enabled. -+ */ -+ return rc; -+ } -+ -+ if (ctrl->supports_hw_closed_loop) -+ cpr3_masked_write(ctrl, CPR4_REG_MARGIN_ADJ_CTL, -+ CPR4_MARGIN_ADJ_CTL_TIMER_SETTLE_VOLTAGE_EN, -+ CPR4_MARGIN_ADJ_CTL_TIMER_SETTLE_VOLTAGE_EN); -+ -+ cpr3_masked_write(ctrl, CPR4_REG_MARGIN_ADJ_CTL, -+ CPR4_MARGIN_ADJ_CTL_KV_MARGIN_ADJ_STEP_QUOT_MASK, -+ ctrl->step_quot_fixed -+ << CPR4_MARGIN_ADJ_CTL_KV_MARGIN_ADJ_STEP_QUOT_SHIFT); -+ -+ cpr3_masked_write(ctrl, CPR4_REG_MARGIN_ADJ_CTL, -+ CPR4_MARGIN_ADJ_CTL_PER_RO_KV_MARGIN_EN, -+ (ctrl->use_dynamic_step_quot -+ ? CPR4_MARGIN_ADJ_CTL_PER_RO_KV_MARGIN_EN : 0)); -+ -+ cpr3_masked_write(ctrl, CPR4_REG_MARGIN_ADJ_CTL, -+ CPR4_MARGIN_ADJ_CTL_INITIAL_TEMP_BAND_MASK, -+ ctrl->initial_temp_band -+ << CPR4_MARGIN_ADJ_CTL_INITIAL_TEMP_BAND_SHIFT); -+ -+ rc = cpr4_regulator_init_temp_points(ctrl); -+ if (rc) { -+ cpr3_err(ctrl, "initialize temp points failed, rc=%d\n", rc); -+ return rc; -+ } -+ -+ if (ctrl->voltage_settling_time) { -+ /* -+ * Configure the settling timer used to account for -+ * one VDD supply step. -+ */ -+ temp = (u64)ctrl->cpr_clock_rate -+ * (u64)ctrl->voltage_settling_time; -+ do_div(temp, 1000000000); -+ cpr3_masked_write(ctrl, CPR4_REG_MARGIN_TEMP_CORE_TIMERS, -+ CPR4_MARGIN_TEMP_CORE_TIMERS_SETTLE_VOLTAGE_COUNT_MASK, -+ temp -+ << CPR4_MARGIN_TEMP_CORE_TIMERS_SETTLE_VOLTAGE_COUNT_SHIFT); -+ } -+ -+ /* -+ * Allocate memory for cpr4_sdelta structure and sdelta table for -+ * controller aggregated corner by finding the maximum core count -+ * used by any cpr3 regulators. -+ */ -+ ctrl_max_core_count = 1; -+ ctrl_valid_sdelta = false; -+ for (i = 0; i < ctrl->thread_count; i++) { -+ thread = &ctrl->thread[i]; -+ -+ /* -+ * Allocate memory for cpr4_sdelta structure and sdelta table -+ * for thread aggregated corner by finding the maximum core -+ * count used by any cpr3 regulators of the thread. -+ */ -+ thread_max_core_count = 1; -+ thread_valid_sdelta = false; -+ for (j = 0; j < thread->vreg_count; j++) { -+ vreg = &thread->vreg[j]; -+ thread_max_core_count = max(thread_max_core_count, -+ vreg->max_core_count); -+ thread_valid_sdelta |= (vreg->allow_core_count_adj -+ | vreg->allow_temp_adj -+ | vreg->allow_boost); -+ } -+ if (thread_valid_sdelta) { -+ sdelta = devm_kzalloc(ctrl->dev, sizeof(*sdelta), -+ GFP_KERNEL); -+ if (!sdelta) -+ return -ENOMEM; -+ -+ sdelta->table = devm_kcalloc(ctrl->dev, -+ thread_max_core_count -+ * ctrl->temp_band_count, -+ sizeof(*sdelta->table), -+ GFP_KERNEL); -+ if (!sdelta->table) -+ return -ENOMEM; -+ -+ sdelta->boost_table = devm_kcalloc(ctrl->dev, -+ ctrl->temp_band_count, -+ sizeof(*sdelta->boost_table), -+ GFP_KERNEL); -+ if (!sdelta->boost_table) -+ return -ENOMEM; -+ -+ thread->aggr_corner.sdelta = sdelta; -+ } -+ -+ ctrl_valid_sdelta |= thread_valid_sdelta; -+ ctrl_max_core_count = max(ctrl_max_core_count, -+ thread_max_core_count); -+ } -+ -+ if (ctrl_valid_sdelta) { -+ sdelta = devm_kzalloc(ctrl->dev, sizeof(*sdelta), GFP_KERNEL); -+ if (!sdelta) -+ return -ENOMEM; -+ -+ sdelta->table = devm_kcalloc(ctrl->dev, ctrl_max_core_count -+ * ctrl->temp_band_count, -+ sizeof(*sdelta->table), GFP_KERNEL); -+ if (!sdelta->table) -+ return -ENOMEM; -+ -+ sdelta->boost_table = devm_kcalloc(ctrl->dev, -+ ctrl->temp_band_count, -+ sizeof(*sdelta->boost_table), -+ GFP_KERNEL); -+ if (!sdelta->boost_table) -+ return -ENOMEM; -+ -+ ctrl->aggr_corner.sdelta = sdelta; -+ } -+ -+ return 0; -+} -+ -+/** -+ * cpr3_write_temp_core_margin() - programs hardware SDELTA registers with -+ * the voltage margin adjustments that need to be applied for -+ * different online core-count and temperature bands. -+ * @ctrl: Pointer to the CPR3 controller -+ * @addr: SDELTA register address -+ * @temp_core_adj: Array of voltage margin values for different temperature -+ * bands. -+ * -+ * CPR interface/bus clocks must be enabled before calling this function. -+ * -+ * Return: none -+ */ -+static void cpr3_write_temp_core_margin(struct cpr3_controller *ctrl, -+ int addr, int *temp_core_adj) -+{ -+ int i, margin_steps; -+ u32 reg = 0; -+ -+ for (i = 0; i < ctrl->temp_band_count; i++) { -+ margin_steps = max(min(temp_core_adj[i], 127), -128); -+ reg |= (margin_steps & CPR4_MARGIN_TEMP_CORE_ADJ_MASK) << -+ (i * CPR4_MARGIN_TEMP_CORE_ADJ_SHIFT); -+ } -+ -+ cpr3_write(ctrl, addr, reg); -+ cpr3_debug(ctrl, "sdelta offset=0x%08x, val=0x%08x\n", addr, reg); -+} -+ -+/** -+ * cpr3_controller_program_sdelta() - programs hardware SDELTA registers with -+ * the voltage margin adjustments that need to be applied at -+ * different online core-count and temperature bands. Also, -+ * programs hardware register configuration for per-online-core -+ * and per-temperature based adjustments. -+ * @ctrl: Pointer to the CPR3 controller -+ * -+ * CPR interface/bus clocks must be enabled before calling this function. -+ * -+ * Return: 0 on success, errno on failure -+ */ -+static int cpr3_controller_program_sdelta(struct cpr3_controller *ctrl) -+{ -+ struct cpr3_corner *corner = &ctrl->aggr_corner; -+ struct cpr4_sdelta *sdelta = corner->sdelta; -+ int i, index, max_core_count, rc = 0; -+ bool cpr_enabled = ctrl->cpr_enabled; -+ -+ if (!sdelta) -+ /* cpr4_sdelta not defined for current aggregated corner */ -+ return 0; -+ -+ if (ctrl->supports_hw_closed_loop && ctrl->cpr_enabled) { -+ cpr3_masked_write(ctrl, CPR4_REG_MARGIN_ADJ_CTL, -+ CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_EN_MASK, -+ (ctrl->use_hw_closed_loop && !sdelta->allow_boost) -+ ? CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_ENABLE : 0); -+ } -+ -+ if (!sdelta->allow_core_count_adj && !sdelta->allow_temp_adj -+ && !sdelta->allow_boost) { -+ /* -+ * Per-online-core, per-temperature and voltage boost -+ * adjustments are disabled for this aggregation corner. -+ */ -+ return 0; -+ } -+ -+ /* Ensure that CPR clocks are enabled before writing to registers. */ -+ if (!cpr_enabled) { -+ rc = cpr3_clock_enable(ctrl); -+ if (rc) { -+ cpr3_err(ctrl, "clock enable failed, rc=%d\n", rc); -+ return rc; -+ } -+ ctrl->cpr_enabled = true; -+ } -+ -+ max_core_count = sdelta->max_core_count; -+ -+ if (sdelta->allow_core_count_adj || sdelta->allow_temp_adj) { -+ if (sdelta->allow_core_count_adj) { -+ /* Program TEMP_CORE0 to same margins as TEMP_CORE1 */ -+ cpr3_write_temp_core_margin(ctrl, -+ CPR4_REG_MARGIN_TEMP_CORE(0), -+ &sdelta->table[0]); -+ } -+ -+ for (i = 0; i < max_core_count; i++) { -+ index = i * sdelta->temp_band_count; -+ /* -+ * Program TEMP_COREi with voltage margin adjustments -+ * that need to be applied when the number of cores -+ * becomes i. -+ */ -+ cpr3_write_temp_core_margin(ctrl, -+ CPR4_REG_MARGIN_TEMP_CORE( -+ sdelta->allow_core_count_adj -+ ? i + 1 : max_core_count), -+ &sdelta->table[index]); -+ } -+ } -+ -+ if (sdelta->allow_boost) { -+ /* Program only boost_num_cores row of SDELTA */ -+ cpr3_write_temp_core_margin(ctrl, -+ CPR4_REG_MARGIN_TEMP_CORE(sdelta->boost_num_cores), -+ &sdelta->boost_table[0]); -+ } -+ -+ if (!sdelta->allow_core_count_adj && !sdelta->allow_boost) { -+ cpr3_masked_write(ctrl, CPR4_REG_MISC, -+ CPR4_MISC_MARGIN_TABLE_ROW_SELECT_MASK, -+ max_core_count -+ << CPR4_MISC_MARGIN_TABLE_ROW_SELECT_SHIFT); -+ } -+ -+ cpr3_masked_write(ctrl, CPR4_REG_MARGIN_ADJ_CTL, -+ CPR4_MARGIN_ADJ_CTL_MAX_NUM_CORES_MASK -+ | CPR4_MARGIN_ADJ_CTL_CORE_ADJ_EN -+ | CPR4_MARGIN_ADJ_CTL_TEMP_ADJ_EN -+ | CPR4_MARGIN_ADJ_CTL_KV_MARGIN_ADJ_EN -+ | CPR4_MARGIN_ADJ_CTL_BOOST_EN, -+ max_core_count << CPR4_MARGIN_ADJ_CTL_MAX_NUM_CORES_SHIFT -+ | ((sdelta->allow_core_count_adj || sdelta->allow_boost) -+ ? CPR4_MARGIN_ADJ_CTL_CORE_ADJ_EN : 0) -+ | ((sdelta->allow_temp_adj && ctrl->supports_hw_closed_loop) -+ ? CPR4_MARGIN_ADJ_CTL_TEMP_ADJ_EN : 0) -+ | (((ctrl->use_hw_closed_loop && !sdelta->allow_boost) -+ || !ctrl->supports_hw_closed_loop) -+ ? CPR4_MARGIN_ADJ_CTL_KV_MARGIN_ADJ_EN : 0) -+ | (sdelta->allow_boost -+ ? CPR4_MARGIN_ADJ_CTL_BOOST_EN : 0)); -+ -+ /* -+ * Ensure that all previous CPR register writes have completed before -+ * continuing. -+ */ -+ mb(); -+ -+ /* Turn off CPR clocks if they were off before this function call. */ -+ if (!cpr_enabled) { -+ cpr3_clock_disable(ctrl); -+ ctrl->cpr_enabled = false; -+ } -+ -+ return 0; -+} -+ -+/** -+ * cpr3_regulator_init_ctrl() - performs hardware initialization of CPR -+ * controller registers -+ * @ctrl: Pointer to the CPR3 controller -+ * -+ * Return: 0 on success, errno on failure -+ */ -+static int cpr3_regulator_init_ctrl(struct cpr3_controller *ctrl) -+{ -+ int i, j, k, m, rc; -+ u32 ro_used = 0; -+ u32 gcnt, cont_dly, up_down_dly, val; -+ u64 temp; -+ char *mode; -+ -+ if (ctrl->core_clk) { -+ rc = clk_set_rate(ctrl->core_clk, ctrl->cpr_clock_rate); -+ if (rc) { -+ cpr3_err(ctrl, "clk_set_rate(core_clk, %u) failed, rc=%d\n", -+ ctrl->cpr_clock_rate, rc); -+ return rc; -+ } -+ } -+ -+ rc = cpr3_clock_enable(ctrl); -+ if (rc) { -+ cpr3_err(ctrl, "clock enable failed, rc=%d\n", rc); -+ return rc; -+ } -+ ctrl->cpr_enabled = true; -+ -+ /* Find all RO's used by any corner of any regulator. */ -+ for (i = 0; i < ctrl->thread_count; i++) -+ for (j = 0; j < ctrl->thread[i].vreg_count; j++) -+ for (k = 0; k < ctrl->thread[i].vreg[j].corner_count; -+ k++) -+ for (m = 0; m < CPR3_RO_COUNT; m++) -+ if (ctrl->thread[i].vreg[j].corner[k]. -+ target_quot[m]) -+ ro_used |= BIT(m); -+ -+ /* Configure the GCNT of the RO's that will be used */ -+ gcnt = cpr3_regulator_get_gcnt(ctrl); -+ for (i = 0; i < CPR3_RO_COUNT; i++) -+ if (ro_used & BIT(i)) -+ cpr3_write(ctrl, CPR3_REG_GCNT(i), gcnt); -+ -+ /* Configure the loop delay time */ -+ temp = (u64)ctrl->cpr_clock_rate * (u64)ctrl->loop_time; -+ do_div(temp, 1000000000); -+ cont_dly = temp; -+ if (ctrl->supports_hw_closed_loop -+ && ctrl->ctrl_type == CPR_CTRL_TYPE_CPR3) -+ cpr3_write(ctrl, CPR3_REG_CPR_TIMER_MID_CONT, cont_dly); -+ else -+ cpr3_write(ctrl, CPR3_REG_CPR_TIMER_AUTO_CONT, cont_dly); -+ -+ if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR3) { -+ temp = (u64)ctrl->cpr_clock_rate * -+ (u64)ctrl->up_down_delay_time; -+ do_div(temp, 1000000000); -+ up_down_dly = temp; -+ if (ctrl->supports_hw_closed_loop) -+ cpr3_write(ctrl, CPR3_REG_CPR_TIMER_UP_DN_CONT, -+ up_down_dly); -+ cpr3_debug(ctrl, "up_down_dly=%u, up_down_delay_time=%u ns\n", -+ up_down_dly, ctrl->up_down_delay_time); -+ } -+ -+ cpr3_debug(ctrl, "cpr_clock_rate=%u HZ, sensor_time=%u ns, loop_time=%u ns, gcnt=%u, cont_dly=%u\n", -+ ctrl->cpr_clock_rate, ctrl->sensor_time, ctrl->loop_time, -+ gcnt, cont_dly); -+ -+ /* Configure CPR sensor operation */ -+ val = (ctrl->idle_clocks << CPR3_CPR_CTL_IDLE_CLOCKS_SHIFT) -+ & CPR3_CPR_CTL_IDLE_CLOCKS_MASK; -+ val |= (ctrl->count_mode << CPR3_CPR_CTL_COUNT_MODE_SHIFT) -+ & CPR3_CPR_CTL_COUNT_MODE_MASK; -+ val |= (ctrl->count_repeat << CPR3_CPR_CTL_COUNT_REPEAT_SHIFT) -+ & CPR3_CPR_CTL_COUNT_REPEAT_MASK; -+ cpr3_write(ctrl, CPR3_REG_CPR_CTL, val); -+ -+ cpr3_debug(ctrl, "idle_clocks=%u, count_mode=%u, count_repeat=%u; CPR_CTL=0x%08X\n", -+ ctrl->idle_clocks, ctrl->count_mode, ctrl->count_repeat, val); -+ -+ /* Configure CPR default step quotients */ -+ val = (ctrl->step_quot_init_min << CPR3_CPR_STEP_QUOT_MIN_SHIFT) -+ & CPR3_CPR_STEP_QUOT_MIN_MASK; -+ val |= (ctrl->step_quot_init_max << CPR3_CPR_STEP_QUOT_MAX_SHIFT) -+ & CPR3_CPR_STEP_QUOT_MAX_MASK; -+ cpr3_write(ctrl, CPR3_REG_CPR_STEP_QUOT, val); -+ -+ cpr3_debug(ctrl, "step_quot_min=%u, step_quot_max=%u; STEP_QUOT=0x%08X\n", -+ ctrl->step_quot_init_min, ctrl->step_quot_init_max, val); -+ -+ /* Configure the CPR sensor ownership */ -+ for (i = 0; i < ctrl->sensor_count; i++) -+ cpr3_write(ctrl, CPR3_REG_SENSOR_OWNER(i), -+ ctrl->sensor_owner[i]); -+ -+ /* Configure per-thread registers */ -+ for (i = 0; i < ctrl->thread_count; i++) { -+ rc = cpr3_regulator_init_thread(&ctrl->thread[i]); -+ if (rc) { -+ cpr3_err(ctrl, "CPR thread register initialization failed, rc=%d\n", -+ rc); -+ return rc; -+ } -+ } -+ -+ if (ctrl->supports_hw_closed_loop) { -+ if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4) { -+ cpr3_masked_write(ctrl, CPR4_REG_MARGIN_ADJ_CTL, -+ CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_EN_MASK, -+ ctrl->use_hw_closed_loop -+ ? CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_ENABLE -+ : CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_DISABLE); -+ } else if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR3) { -+ cpr3_write(ctrl, CPR3_REG_HW_CLOSED_LOOP, -+ ctrl->use_hw_closed_loop -+ ? CPR3_HW_CLOSED_LOOP_ENABLE -+ : CPR3_HW_CLOSED_LOOP_DISABLE); -+ -+ cpr3_debug(ctrl, "PD_THROTTLE=0x%08X\n", -+ ctrl->proc_clock_throttle); -+ } -+ -+ if ((ctrl->use_hw_closed_loop || -+ ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4) && -+ ctrl->vdd_limit_regulator) { -+ rc = regulator_enable(ctrl->vdd_limit_regulator); -+ if (rc) { -+ cpr3_err(ctrl, "CPR limit regulator enable failed, rc=%d\n", -+ rc); -+ return rc; -+ } -+ } -+ } -+ -+ if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4) { -+ rc = cpr3_regulator_init_cpr4(ctrl); -+ if (rc) { -+ cpr3_err(ctrl, "CPR4-specific controller initialization failed, rc=%d\n", -+ rc); -+ return rc; -+ } -+ } -+ -+ /* Ensure that all register writes complete before disabling clocks. */ -+ wmb(); -+ -+ cpr3_clock_disable(ctrl); -+ ctrl->cpr_enabled = false; -+ -+ if (!ctrl->cpr_allowed_sw || !ctrl->cpr_allowed_hw) -+ mode = "open-loop"; -+ else if (ctrl->supports_hw_closed_loop) -+ mode = ctrl->use_hw_closed_loop -+ ? "HW closed-loop" : "SW closed-loop"; -+ else -+ mode = "closed-loop"; -+ -+ cpr3_info(ctrl, "Default CPR mode = %s", mode); -+ -+ return 0; -+} -+ -+/** -+ * cpr3_regulator_set_target_quot() - configure the target quotient for each -+ * RO of the CPR3 thread and set the RO mask -+ * @thread: Pointer to the CPR3 thread -+ * -+ * Return: none -+ */ -+static void cpr3_regulator_set_target_quot(struct cpr3_thread *thread) -+{ -+ u32 new_quot, last_quot; -+ int i; -+ -+ if (thread->aggr_corner.ro_mask == CPR3_RO_MASK -+ && thread->last_closed_loop_aggr_corner.ro_mask == CPR3_RO_MASK) { -+ /* Avoid writing target quotients since all RO's are masked. */ -+ return; -+ } else if (thread->aggr_corner.ro_mask == CPR3_RO_MASK) { -+ cpr3_write(thread->ctrl, CPR3_REG_RO_MASK(thread->thread_id), -+ CPR3_RO_MASK); -+ thread->last_closed_loop_aggr_corner.ro_mask = CPR3_RO_MASK; -+ /* -+ * Only the RO_MASK register needs to be written since all -+ * RO's are masked. -+ */ -+ return; -+ } else if (thread->aggr_corner.ro_mask -+ != thread->last_closed_loop_aggr_corner.ro_mask) { -+ cpr3_write(thread->ctrl, CPR3_REG_RO_MASK(thread->thread_id), -+ thread->aggr_corner.ro_mask); -+ } -+ -+ for (i = 0; i < CPR3_RO_COUNT; i++) { -+ new_quot = thread->aggr_corner.target_quot[i]; -+ last_quot = thread->last_closed_loop_aggr_corner.target_quot[i]; -+ if (new_quot != last_quot) -+ cpr3_write(thread->ctrl, -+ CPR3_REG_TARGET_QUOT(thread->thread_id, i), -+ new_quot); -+ } -+ -+ thread->last_closed_loop_aggr_corner = thread->aggr_corner; -+ -+ return; -+} -+ -+/** -+ * cpr3_update_vreg_closed_loop_volt() - update the last known settled -+ * closed loop voltage for a CPR3 regulator -+ * @vreg: Pointer to the CPR3 regulator -+ * @vdd_volt: Last known settled voltage in microvolts for the -+ * VDD supply -+ * @reg_last_measurement: Value read from the LAST_MEASUREMENT register -+ * -+ * Return: none -+ */ -+static void cpr3_update_vreg_closed_loop_volt(struct cpr3_regulator *vreg, -+ int vdd_volt, u32 reg_last_measurement) -+{ -+ bool step_dn, step_up, aggr_step_up, aggr_step_dn, aggr_step_mid; -+ bool valid, pd_valid, saw_error; -+ struct cpr3_controller *ctrl = vreg->thread->ctrl; -+ struct cpr3_corner *corner; -+ u32 id; -+ -+ if (vreg->last_closed_loop_corner == CPR3_REGULATOR_CORNER_INVALID) -+ return; -+ else -+ corner = &vreg->corner[vreg->last_closed_loop_corner]; -+ -+ if (vreg->thread->last_closed_loop_aggr_corner.ro_mask -+ == CPR3_RO_MASK || !vreg->aggregated) { -+ return; -+ } else if (!ctrl->cpr_enabled || !ctrl->last_corner_was_closed_loop) { -+ return; -+ } else if (ctrl->thread_count == 1 -+ && vdd_volt >= corner->floor_volt -+ && vdd_volt <= corner->ceiling_volt) { -+ corner->last_volt = vdd_volt; -+ cpr3_debug(vreg, "last_volt updated: last_volt[%d]=%d, ceiling_volt[%d]=%d, floor_volt[%d]=%d\n", -+ vreg->last_closed_loop_corner, corner->last_volt, -+ vreg->last_closed_loop_corner, -+ corner->ceiling_volt, -+ vreg->last_closed_loop_corner, -+ corner->floor_volt); -+ return; -+ } else if (!ctrl->supports_hw_closed_loop) { -+ return; -+ } else if (ctrl->ctrl_type != CPR_CTRL_TYPE_CPR3) { -+ corner->last_volt = vdd_volt; -+ cpr3_debug(vreg, "last_volt updated: last_volt[%d]=%d, ceiling_volt[%d]=%d, floor_volt[%d]=%d\n", -+ vreg->last_closed_loop_corner, corner->last_volt, -+ vreg->last_closed_loop_corner, -+ corner->ceiling_volt, -+ vreg->last_closed_loop_corner, -+ corner->floor_volt); -+ return; -+ } -+ -+ /* CPR clocks are on and HW closed loop is supported */ -+ valid = !!(reg_last_measurement & CPR3_LAST_MEASUREMENT_VALID); -+ if (!valid) { -+ cpr3_debug(vreg, "CPR_LAST_VALID_MEASUREMENT=0x%X valid bit not set\n", -+ reg_last_measurement); -+ return; -+ } -+ -+ id = vreg->thread->thread_id; -+ -+ step_dn -+ = !!(reg_last_measurement & CPR3_LAST_MEASUREMENT_THREAD_DN(id)); -+ step_up -+ = !!(reg_last_measurement & CPR3_LAST_MEASUREMENT_THREAD_UP(id)); -+ aggr_step_dn = !!(reg_last_measurement & CPR3_LAST_MEASUREMENT_AGGR_DN); -+ aggr_step_mid -+ = !!(reg_last_measurement & CPR3_LAST_MEASUREMENT_AGGR_MID); -+ aggr_step_up = !!(reg_last_measurement & CPR3_LAST_MEASUREMENT_AGGR_UP); -+ saw_error = !!(reg_last_measurement & CPR3_LAST_MEASUREMENT_SAW_ERROR); -+ pd_valid -+ = !((((reg_last_measurement & CPR3_LAST_MEASUREMENT_PD_BYPASS_MASK) -+ >> CPR3_LAST_MEASUREMENT_PD_BYPASS_SHIFT) -+ & vreg->pd_bypass_mask) == vreg->pd_bypass_mask); -+ -+ if (!pd_valid) { -+ cpr3_debug(vreg, "CPR_LAST_VALID_MEASUREMENT=0x%X, all power domains bypassed\n", -+ reg_last_measurement); -+ return; -+ } else if (step_dn && step_up) { -+ cpr3_err(vreg, "both up and down status bits set, CPR_LAST_VALID_MEASUREMENT=0x%X\n", -+ reg_last_measurement); -+ return; -+ } else if (aggr_step_dn && step_dn && vdd_volt < corner->last_volt -+ && vdd_volt >= corner->floor_volt) { -+ corner->last_volt = vdd_volt; -+ } else if (aggr_step_up && step_up && vdd_volt > corner->last_volt -+ && vdd_volt <= corner->ceiling_volt) { -+ corner->last_volt = vdd_volt; -+ } else if (aggr_step_mid -+ && vdd_volt >= corner->floor_volt -+ && vdd_volt <= corner->ceiling_volt) { -+ corner->last_volt = vdd_volt; -+ } else if (saw_error && (vdd_volt == corner->ceiling_volt -+ || vdd_volt == corner->floor_volt)) { -+ corner->last_volt = vdd_volt; -+ } else { -+ cpr3_debug(vreg, "last_volt not updated: last_volt[%d]=%d, ceiling_volt[%d]=%d, floor_volt[%d]=%d, vdd_volt=%d, CPR_LAST_VALID_MEASUREMENT=0x%X\n", -+ vreg->last_closed_loop_corner, corner->last_volt, -+ vreg->last_closed_loop_corner, -+ corner->ceiling_volt, -+ vreg->last_closed_loop_corner, corner->floor_volt, -+ vdd_volt, reg_last_measurement); -+ return; -+ } -+ -+ cpr3_debug(vreg, "last_volt updated: last_volt[%d]=%d, ceiling_volt[%d]=%d, floor_volt[%d]=%d, CPR_LAST_VALID_MEASUREMENT=0x%X\n", -+ vreg->last_closed_loop_corner, corner->last_volt, -+ vreg->last_closed_loop_corner, corner->ceiling_volt, -+ vreg->last_closed_loop_corner, corner->floor_volt, -+ reg_last_measurement); -+} -+ -+/** -+ * cpr3_regulator_mem_acc_bhs_used() - determines if mem-acc regulators powered -+ * through a BHS are associated with the CPR3 controller or any of -+ * the CPR3 regulators it controls. -+ * @ctrl: Pointer to the CPR3 controller -+ * -+ * This function determines if the CPR3 controller or any of its CPR3 regulators -+ * need to manage mem-acc regulators that are currently powered through a BHS -+ * and whose corner selection is based upon a particular voltage threshold. -+ * -+ * Return: true or false -+ */ -+static bool cpr3_regulator_mem_acc_bhs_used(struct cpr3_controller *ctrl) -+{ -+ struct cpr3_regulator *vreg; -+ int i, j; -+ -+ if (!ctrl->mem_acc_threshold_volt) -+ return false; -+ -+ if (ctrl->mem_acc_regulator) -+ return true; -+ -+ for (i = 0; i < ctrl->thread_count; i++) { -+ for (j = 0; j < ctrl->thread[i].vreg_count; j++) { -+ vreg = &ctrl->thread[i].vreg[j]; -+ -+ if (vreg->mem_acc_regulator) -+ return true; -+ } -+ } -+ -+ return false; -+} -+ -+/** -+ * cpr3_regulator_config_bhs_mem_acc() - configure the mem-acc regulator -+ * settings for hardware blocks currently powered through the BHS. -+ * @ctrl: Pointer to the CPR3 controller -+ * @new_volt: New voltage in microvolts that VDD supply needs to -+ * end up at -+ * @last_volt: Pointer to the last known voltage in microvolts for the -+ * VDD supply -+ * @aggr_corner: Pointer to the CPR3 corner which corresponds to the max -+ * corner aggregated from all CPR3 threads managed by the -+ * CPR3 controller -+ * -+ * This function programs the mem-acc regulator corners for CPR3 regulators -+ * whose LDO regulators are in bypassed state. The function also handles -+ * CPR3 controllers which utilize mem-acc regulators that operate independently -+ * from the LDO hardware and that must be programmed when the VDD supply -+ * crosses a particular voltage threshold. -+ * -+ * Return: 0 on success, errno on failure. If the VDD supply voltage is -+ * modified, last_volt is updated to reflect the new voltage setpoint. -+ */ -+static int cpr3_regulator_config_bhs_mem_acc(struct cpr3_controller *ctrl, -+ int new_volt, int *last_volt, -+ struct cpr3_corner *aggr_corner) -+{ -+ struct cpr3_regulator *vreg; -+ int i, j, rc, mem_acc_corn, safe_volt; -+ int mem_acc_volt = ctrl->mem_acc_threshold_volt; -+ int ref_volt; -+ -+ if (!cpr3_regulator_mem_acc_bhs_used(ctrl)) -+ return 0; -+ -+ ref_volt = ctrl->use_hw_closed_loop ? aggr_corner->floor_volt : -+ new_volt; -+ -+ if (((*last_volt < mem_acc_volt && mem_acc_volt <= ref_volt) || -+ (*last_volt >= mem_acc_volt && mem_acc_volt > ref_volt))) { -+ if (ref_volt < *last_volt) -+ safe_volt = max(mem_acc_volt, aggr_corner->last_volt); -+ else -+ safe_volt = max(mem_acc_volt, *last_volt); -+ -+ rc = regulator_set_voltage(ctrl->vdd_regulator, safe_volt, -+ new_volt < *last_volt ? -+ ctrl->aggr_corner.ceiling_volt : -+ new_volt); -+ if (rc) { -+ cpr3_err(ctrl, "regulator_set_voltage(vdd) == %d failed, rc=%d\n", -+ safe_volt, rc); -+ return rc; -+ } -+ -+ *last_volt = safe_volt; -+ -+ mem_acc_corn = ref_volt < mem_acc_volt ? -+ ctrl->mem_acc_corner_map[CPR3_MEM_ACC_LOW_CORNER] : -+ ctrl->mem_acc_corner_map[CPR3_MEM_ACC_HIGH_CORNER]; -+ -+ if (ctrl->mem_acc_regulator) { -+ rc = regulator_set_voltage(ctrl->mem_acc_regulator, -+ mem_acc_corn, mem_acc_corn); -+ if (rc) { -+ cpr3_err(ctrl, "regulator_set_voltage(mem_acc) == %d failed, rc=%d\n", -+ mem_acc_corn, rc); -+ return rc; -+ } -+ } -+ -+ for (i = 0; i < ctrl->thread_count; i++) { -+ for (j = 0; j < ctrl->thread[i].vreg_count; j++) { -+ vreg = &ctrl->thread[i].vreg[j]; -+ -+ if (!vreg->mem_acc_regulator) -+ continue; -+ -+ rc = regulator_set_voltage( -+ vreg->mem_acc_regulator, mem_acc_corn, -+ mem_acc_corn); -+ if (rc) { -+ cpr3_err(vreg, "regulator_set_voltage(mem_acc) == %d failed, rc=%d\n", -+ mem_acc_corn, rc); -+ return rc; -+ } -+ } -+ } -+ } -+ -+ return 0; -+} -+ -+/** -+ * cpr3_regulator_switch_apm_mode() - switch the mode of the APM controller -+ * associated with a given CPR3 controller -+ * @ctrl: Pointer to the CPR3 controller -+ * @new_volt: New voltage in microvolts that VDD supply needs to -+ * end up at -+ * @last_volt: Pointer to the last known voltage in microvolts for the -+ * VDD supply -+ * @aggr_corner: Pointer to the CPR3 corner which corresponds to the max -+ * corner aggregated from all CPR3 threads managed by the -+ * CPR3 controller -+ * -+ * This function requests a switch of the APM mode while guaranteeing -+ * any LDO regulator hardware requirements are satisfied. The function must -+ * be called once it is known a new VDD supply setpoint crosses the APM -+ * voltage threshold. -+ * -+ * Return: 0 on success, errno on failure. If the VDD supply voltage is -+ * modified, last_volt is updated to reflect the new voltage setpoint. -+ */ -+static int cpr3_regulator_switch_apm_mode(struct cpr3_controller *ctrl, -+ int new_volt, int *last_volt, -+ struct cpr3_corner *aggr_corner) -+{ -+ struct regulator *vdd = ctrl->vdd_regulator; -+ int apm_volt = ctrl->apm_threshold_volt; -+ int orig_last_volt = *last_volt; -+ int rc; -+ -+ rc = regulator_set_voltage(vdd, apm_volt, apm_volt); -+ if (rc) { -+ cpr3_err(ctrl, "regulator_set_voltage(vdd) == %d failed, rc=%d\n", -+ apm_volt, rc); -+ return rc; -+ } -+ -+ *last_volt = apm_volt; -+ -+ rc = msm_apm_set_supply(ctrl->apm, new_volt >= apm_volt -+ ? ctrl->apm_high_supply : ctrl->apm_low_supply); -+ if (rc) { -+ cpr3_err(ctrl, "APM switch failed, rc=%d\n", rc); -+ /* Roll back the voltage. */ -+ regulator_set_voltage(vdd, orig_last_volt, INT_MAX); -+ *last_volt = orig_last_volt; -+ return rc; -+ } -+ return 0; -+} -+ -+/** -+ * cpr3_regulator_config_voltage_crossings() - configure APM and mem-acc -+ * settings depending upon a new VDD supply setpoint -+ * -+ * @ctrl: Pointer to the CPR3 controller -+ * @new_volt: New voltage in microvolts that VDD supply needs to -+ * end up at -+ * @last_volt: Pointer to the last known voltage in microvolts for the -+ * VDD supply -+ * @aggr_corner: Pointer to the CPR3 corner which corresponds to the max -+ * corner aggregated from all CPR3 threads managed by the -+ * CPR3 controller -+ * -+ * This function handles the APM and mem-acc regulator reconfiguration if -+ * the new VDD supply voltage will result in crossing their respective voltage -+ * thresholds. -+ * -+ * Return: 0 on success, errno on failure. If the VDD supply voltage is -+ * modified, last_volt is updated to reflect the new voltage setpoint. -+ */ -+static int cpr3_regulator_config_voltage_crossings(struct cpr3_controller *ctrl, -+ int new_volt, int *last_volt, -+ struct cpr3_corner *aggr_corner) -+{ -+ bool apm_crossing = false, mem_acc_crossing = false; -+ bool mem_acc_bhs_used; -+ int apm_volt = ctrl->apm_threshold_volt; -+ int mem_acc_volt = ctrl->mem_acc_threshold_volt; -+ int ref_volt, rc; -+ -+ if (ctrl->apm && apm_volt > 0 -+ && ((*last_volt < apm_volt && apm_volt <= new_volt) -+ || (*last_volt >= apm_volt && apm_volt > new_volt))) -+ apm_crossing = true; -+ -+ mem_acc_bhs_used = cpr3_regulator_mem_acc_bhs_used(ctrl); -+ -+ ref_volt = ctrl->use_hw_closed_loop ? aggr_corner->floor_volt : -+ new_volt; -+ -+ if (mem_acc_bhs_used && -+ (((*last_volt < mem_acc_volt && mem_acc_volt <= ref_volt) || -+ (*last_volt >= mem_acc_volt && mem_acc_volt > ref_volt)))) -+ mem_acc_crossing = true; -+ -+ if (apm_crossing && mem_acc_crossing) { -+ if ((new_volt < *last_volt && apm_volt >= mem_acc_volt) || -+ (new_volt >= *last_volt && apm_volt < mem_acc_volt)) { -+ rc = cpr3_regulator_switch_apm_mode(ctrl, new_volt, -+ last_volt, -+ aggr_corner); -+ if (rc) { -+ cpr3_err(ctrl, "unable to switch APM mode\n"); -+ return rc; -+ } -+ -+ rc = cpr3_regulator_config_bhs_mem_acc(ctrl, new_volt, -+ last_volt, aggr_corner); -+ if (rc) { -+ cpr3_err(ctrl, "unable to configure BHS mem-acc settings\n"); -+ return rc; -+ } -+ } else { -+ rc = cpr3_regulator_config_bhs_mem_acc(ctrl, new_volt, -+ last_volt, aggr_corner); -+ if (rc) { -+ cpr3_err(ctrl, "unable to configure BHS mem-acc settings\n"); -+ return rc; -+ } -+ -+ rc = cpr3_regulator_switch_apm_mode(ctrl, new_volt, -+ last_volt, -+ aggr_corner); -+ if (rc) { -+ cpr3_err(ctrl, "unable to switch APM mode\n"); -+ return rc; -+ } -+ } -+ } else if (apm_crossing) { -+ rc = cpr3_regulator_switch_apm_mode(ctrl, new_volt, last_volt, -+ aggr_corner); -+ if (rc) { -+ cpr3_err(ctrl, "unable to switch APM mode\n"); -+ return rc; -+ } -+ } else if (mem_acc_crossing) { -+ rc = cpr3_regulator_config_bhs_mem_acc(ctrl, new_volt, -+ last_volt, aggr_corner); -+ if (rc) { -+ cpr3_err(ctrl, "unable to configure BHS mem-acc settings\n"); -+ return rc; -+ } -+ } -+ -+ return 0; -+} -+ -+/** -+ * cpr3_regulator_config_mem_acc() - configure the corner of the mem-acc -+ * regulator associated with the CPR3 controller -+ * @ctrl: Pointer to the CPR3 controller -+ * @aggr_corner: Pointer to the CPR3 corner which corresponds to the max -+ * corner aggregated from all CPR3 threads managed by the -+ * CPR3 controller -+ * -+ * Return: 0 on success, errno on failure -+ */ -+static int cpr3_regulator_config_mem_acc(struct cpr3_controller *ctrl, -+ struct cpr3_corner *aggr_corner) -+{ -+ int rc; -+ -+ if (ctrl->mem_acc_regulator && aggr_corner->mem_acc_volt) { -+ rc = regulator_set_voltage(ctrl->mem_acc_regulator, -+ aggr_corner->mem_acc_volt, -+ aggr_corner->mem_acc_volt); -+ if (rc) { -+ cpr3_err(ctrl, "regulator_set_voltage(mem_acc) == %d failed, rc=%d\n", -+ aggr_corner->mem_acc_volt, rc); -+ return rc; -+ } -+ } -+ -+ return 0; -+} -+ -+/** -+ * cpr3_regulator_scale_vdd_voltage() - scale the CPR controlled VDD supply -+ * voltage to the new level while satisfying any other hardware -+ * requirements -+ * @ctrl: Pointer to the CPR3 controller -+ * @new_volt: New voltage in microvolts that VDD supply needs to end -+ * up at -+ * @last_volt: Last known voltage in microvolts for the VDD supply -+ * @aggr_corner: Pointer to the CPR3 corner which corresponds to the max -+ * corner aggregated from all CPR3 threads managed by the -+ * CPR3 controller -+ * -+ * This function scales the CPR controlled VDD supply voltage from its -+ * current level to the new voltage that is specified. If the supply is -+ * configured to use the APM and the APM threshold is crossed as a result of -+ * the voltage scaling, then this function also stops at the APM threshold, -+ * switches the APM source, and finally sets the final new voltage. -+ * -+ * Return: 0 on success, errno on failure -+ */ -+static int cpr3_regulator_scale_vdd_voltage(struct cpr3_controller *ctrl, -+ int new_volt, int last_volt, -+ struct cpr3_corner *aggr_corner) -+{ -+ struct regulator *vdd = ctrl->vdd_regulator; -+ int rc; -+ -+ if (new_volt < last_volt) { -+ rc = cpr3_regulator_config_mem_acc(ctrl, aggr_corner); -+ if (rc) -+ return rc; -+ } else { -+ /* Increasing VDD voltage */ -+ if (ctrl->system_regulator) { -+ rc = regulator_set_voltage(ctrl->system_regulator, -+ aggr_corner->system_volt, INT_MAX); -+ if (rc) { -+ cpr3_err(ctrl, "regulator_set_voltage(system) == %d failed, rc=%d\n", -+ aggr_corner->system_volt, rc); -+ return rc; -+ } -+ } -+ } -+ -+ rc = cpr3_regulator_config_voltage_crossings(ctrl, new_volt, &last_volt, -+ aggr_corner); -+ if (rc) { -+ cpr3_err(ctrl, "unable to handle voltage threshold crossing configurations, rc=%d\n", -+ rc); -+ return rc; -+ } -+ -+ /* -+ * Subtract a small amount from the min_uV parameter so that the -+ * set voltage request is not dropped by the framework due to being -+ * duplicate. This is needed in order to switch from hardware -+ * closed-loop to open-loop successfully. -+ */ -+ rc = regulator_set_voltage(vdd, new_volt - (ctrl->cpr_enabled ? 0 : 1), -+ aggr_corner->ceiling_volt); -+ if (rc) { -+ cpr3_err(ctrl, "regulator_set_voltage(vdd) == %d failed, rc=%d\n", -+ new_volt, rc); -+ return rc; -+ } -+ -+ if (new_volt == last_volt && ctrl->supports_hw_closed_loop -+ && ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4) { -+ /* -+ * CPR4 features enforce voltage reprogramming when the last -+ * set voltage and new set voltage are same. This way, we can -+ * ensure that SAW PMIC STATUS register is updated with newly -+ * programmed voltage. -+ */ -+ rc = regulator_sync_voltage(vdd); -+ if (rc) { -+ cpr3_err(ctrl, "regulator_sync_voltage(vdd) == %d failed, rc=%d\n", -+ new_volt, rc); -+ return rc; -+ } -+ } -+ -+ if (new_volt >= last_volt) { -+ rc = cpr3_regulator_config_mem_acc(ctrl, aggr_corner); -+ if (rc) -+ return rc; -+ } else { -+ /* Decreasing VDD voltage */ -+ if (ctrl->system_regulator) { -+ rc = regulator_set_voltage(ctrl->system_regulator, -+ aggr_corner->system_volt, INT_MAX); -+ if (rc) { -+ cpr3_err(ctrl, "regulator_set_voltage(system) == %d failed, rc=%d\n", -+ aggr_corner->system_volt, rc); -+ return rc; -+ } -+ } -+ } -+ -+ return 0; -+} -+ -+/** -+ * cpr3_regulator_get_dynamic_floor_volt() - returns the current dynamic floor -+ * voltage based upon static configurations and the state of all -+ * power domains during the last CPR measurement -+ * @ctrl: Pointer to the CPR3 controller -+ * @reg_last_measurement: Value read from the LAST_MEASUREMENT register -+ * -+ * When using HW closed-loop, the dynamic floor voltage is always returned -+ * regardless of the current state of the power domains. -+ * -+ * Return: dynamic floor voltage in microvolts or 0 if dynamic floor is not -+ * currently required -+ */ -+static int cpr3_regulator_get_dynamic_floor_volt(struct cpr3_controller *ctrl, -+ u32 reg_last_measurement) -+{ -+ int dynamic_floor_volt = 0; -+ struct cpr3_regulator *vreg; -+ bool valid, pd_valid; -+ u32 bypass_bits; -+ int i, j; -+ -+ if (!ctrl->supports_hw_closed_loop) -+ return 0; -+ -+ if (likely(!ctrl->use_hw_closed_loop)) { -+ valid = !!(reg_last_measurement & CPR3_LAST_MEASUREMENT_VALID); -+ bypass_bits -+ = (reg_last_measurement & CPR3_LAST_MEASUREMENT_PD_BYPASS_MASK) -+ >> CPR3_LAST_MEASUREMENT_PD_BYPASS_SHIFT; -+ } else { -+ /* -+ * Ensure that the dynamic floor voltage is always used for -+ * HW closed-loop since the conditions below cannot be evaluated -+ * after each CPR measurement. -+ */ -+ valid = false; -+ bypass_bits = 0; -+ } -+ -+ for (i = 0; i < ctrl->thread_count; i++) { -+ for (j = 0; j < ctrl->thread[i].vreg_count; j++) { -+ vreg = &ctrl->thread[i].vreg[j]; -+ -+ if (!vreg->uses_dynamic_floor) -+ continue; -+ -+ pd_valid = !((bypass_bits & vreg->pd_bypass_mask) -+ == vreg->pd_bypass_mask); -+ -+ if (!valid || !pd_valid) -+ dynamic_floor_volt = max(dynamic_floor_volt, -+ vreg->corner[ -+ vreg->dynamic_floor_corner].last_volt); -+ } -+ } -+ -+ return dynamic_floor_volt; -+} -+ -+/** -+ * cpr3_regulator_max_sdelta_diff() - returns the maximum voltage difference in -+ * microvolts that can result from different operating conditions -+ * for the specified sdelta struct -+ * @sdelta: Pointer to the sdelta structure -+ * @step_volt: Step size in microvolts between available set -+ * points of the VDD supply. -+ * -+ * Return: voltage difference between the highest and lowest adjustments if -+ * sdelta and sdelta->table are valid, else 0. -+ */ -+static int cpr3_regulator_max_sdelta_diff(const struct cpr4_sdelta *sdelta, -+ int step_volt) -+{ -+ int i, j, index, sdelta_min = INT_MAX, sdelta_max = INT_MIN; -+ -+ if (!sdelta || !sdelta->table) -+ return 0; -+ -+ for (i = 0; i < sdelta->max_core_count; i++) { -+ for (j = 0; j < sdelta->temp_band_count; j++) { -+ index = i * sdelta->temp_band_count + j; -+ sdelta_min = min(sdelta_min, sdelta->table[index]); -+ sdelta_max = max(sdelta_max, sdelta->table[index]); -+ } -+ } -+ -+ return (sdelta_max - sdelta_min) * step_volt; -+} -+ -+/** -+ * cpr3_regulator_aggregate_sdelta() - check open-loop voltages of current -+ * aggregated corner and current corner of a given regulator -+ * and adjust the sdelta strucuture data of aggregate corner. -+ * @aggr_corner: Pointer to accumulated aggregated corner which -+ * is both an input and an output -+ * @corner: Pointer to the corner to be aggregated with -+ * aggr_corner -+ * @step_volt: Step size in microvolts between available set -+ * points of the VDD supply. -+ * -+ * Return: none -+ */ -+static void cpr3_regulator_aggregate_sdelta( -+ struct cpr3_corner *aggr_corner, -+ const struct cpr3_corner *corner, int step_volt) -+{ -+ struct cpr4_sdelta *aggr_sdelta, *sdelta; -+ int aggr_core_count, core_count, temp_band_count; -+ u32 aggr_index, index; -+ int i, j, sdelta_size, cap_steps, adjust_sdelta; -+ -+ aggr_sdelta = aggr_corner->sdelta; -+ sdelta = corner->sdelta; -+ -+ if (aggr_corner->open_loop_volt < corner->open_loop_volt) { -+ /* -+ * Found the new dominant regulator as its open-loop requirement -+ * is higher than previous dominant regulator. Calculate cap -+ * voltage to limit the SDELTA values to make sure the runtime -+ * (Core-count/temp) adjustments do not violate other -+ * regulators' voltage requirements. Use cpr4_sdelta values of -+ * new dominant regulator. -+ */ -+ aggr_sdelta->cap_volt = min(aggr_sdelta->cap_volt, -+ (corner->open_loop_volt - -+ aggr_corner->open_loop_volt)); -+ -+ /* Clear old data in the sdelta table */ -+ sdelta_size = aggr_sdelta->max_core_count -+ * aggr_sdelta->temp_band_count; -+ -+ if (aggr_sdelta->allow_core_count_adj -+ || aggr_sdelta->allow_temp_adj) -+ memset(aggr_sdelta->table, 0, sdelta_size -+ * sizeof(*aggr_sdelta->table)); -+ -+ if (sdelta->allow_temp_adj || sdelta->allow_core_count_adj) { -+ /* Copy new data in sdelta table */ -+ sdelta_size = sdelta->max_core_count -+ * sdelta->temp_band_count; -+ if (sdelta->table) -+ memcpy(aggr_sdelta->table, sdelta->table, -+ sdelta_size * sizeof(*sdelta->table)); -+ } -+ -+ if (sdelta->allow_boost) { -+ memcpy(aggr_sdelta->boost_table, sdelta->boost_table, -+ sdelta->temp_band_count -+ * sizeof(*sdelta->boost_table)); -+ aggr_sdelta->boost_num_cores = sdelta->boost_num_cores; -+ } else if (aggr_sdelta->allow_boost) { -+ for (i = 0; i < aggr_sdelta->temp_band_count; i++) { -+ adjust_sdelta = (corner->open_loop_volt -+ - aggr_corner->open_loop_volt) -+ / step_volt; -+ aggr_sdelta->boost_table[i] += adjust_sdelta; -+ aggr_sdelta->boost_table[i] -+ = min(aggr_sdelta->boost_table[i], 0); -+ } -+ } -+ -+ aggr_corner->open_loop_volt = corner->open_loop_volt; -+ aggr_sdelta->allow_temp_adj = sdelta->allow_temp_adj; -+ aggr_sdelta->allow_core_count_adj -+ = sdelta->allow_core_count_adj; -+ aggr_sdelta->max_core_count = sdelta->max_core_count; -+ aggr_sdelta->temp_band_count = sdelta->temp_band_count; -+ } else if (aggr_corner->open_loop_volt > corner->open_loop_volt) { -+ /* -+ * Adjust the cap voltage if the open-loop requirement of new -+ * regulator is the next highest. -+ */ -+ aggr_sdelta->cap_volt = min(aggr_sdelta->cap_volt, -+ (aggr_corner->open_loop_volt -+ - corner->open_loop_volt)); -+ -+ if (sdelta->allow_boost) { -+ for (i = 0; i < aggr_sdelta->temp_band_count; i++) { -+ adjust_sdelta = (aggr_corner->open_loop_volt -+ - corner->open_loop_volt) -+ / step_volt; -+ aggr_sdelta->boost_table[i] = -+ sdelta->boost_table[i] + adjust_sdelta; -+ aggr_sdelta->boost_table[i] -+ = min(aggr_sdelta->boost_table[i], 0); -+ } -+ aggr_sdelta->boost_num_cores = sdelta->boost_num_cores; -+ } -+ } else { -+ /* -+ * Found another dominant regulator with same open-loop -+ * requirement. Make cap voltage to '0'. Disable core-count -+ * adjustments as we couldn't support for both regulators. -+ * Keep enable temp based adjustments if enabled for both -+ * regulators and choose mininum margin adjustment values -+ * between them. -+ */ -+ aggr_sdelta->cap_volt = 0; -+ aggr_sdelta->allow_core_count_adj = false; -+ -+ if (aggr_sdelta->allow_temp_adj -+ && sdelta->allow_temp_adj) { -+ aggr_core_count = aggr_sdelta->max_core_count - 1; -+ core_count = sdelta->max_core_count - 1; -+ temp_band_count = sdelta->temp_band_count; -+ for (j = 0; j < temp_band_count; j++) { -+ aggr_index = aggr_core_count * temp_band_count -+ + j; -+ index = core_count * temp_band_count + j; -+ aggr_sdelta->table[aggr_index] = -+ min(aggr_sdelta->table[aggr_index], -+ sdelta->table[index]); -+ } -+ } else { -+ aggr_sdelta->allow_temp_adj = false; -+ } -+ -+ if (sdelta->allow_boost) { -+ memcpy(aggr_sdelta->boost_table, sdelta->boost_table, -+ sdelta->temp_band_count -+ * sizeof(*sdelta->boost_table)); -+ aggr_sdelta->boost_num_cores = sdelta->boost_num_cores; -+ } -+ } -+ -+ /* Keep non-dominant clients boost enable state */ -+ aggr_sdelta->allow_boost |= sdelta->allow_boost; -+ if (aggr_sdelta->allow_boost) -+ aggr_sdelta->allow_core_count_adj = false; -+ -+ if (aggr_sdelta->cap_volt && !(aggr_sdelta->cap_volt == INT_MAX)) { -+ core_count = aggr_sdelta->max_core_count; -+ temp_band_count = aggr_sdelta->temp_band_count; -+ /* -+ * Convert cap voltage from uV to PMIC steps and use to limit -+ * sdelta margin adjustments. -+ */ -+ cap_steps = aggr_sdelta->cap_volt / step_volt; -+ for (i = 0; i < core_count; i++) -+ for (j = 0; j < temp_band_count; j++) { -+ index = i * temp_band_count + j; -+ aggr_sdelta->table[index] = -+ min(aggr_sdelta->table[index], -+ cap_steps); -+ } -+ } -+} -+ -+/** -+ * cpr3_regulator_aggregate_corners() - aggregate two corners together -+ * @aggr_corner: Pointer to accumulated aggregated corner which -+ * is both an input and an output -+ * @corner: Pointer to the corner to be aggregated with -+ * aggr_corner -+ * @aggr_quot: Flag indicating that target quotients should be -+ * aggregated as well. -+ * @step_volt: Step size in microvolts between available set -+ * points of the VDD supply. -+ * -+ * Return: none -+ */ -+static void cpr3_regulator_aggregate_corners(struct cpr3_corner *aggr_corner, -+ const struct cpr3_corner *corner, bool aggr_quot, -+ int step_volt) -+{ -+ int i; -+ -+ aggr_corner->ceiling_volt -+ = max(aggr_corner->ceiling_volt, corner->ceiling_volt); -+ aggr_corner->floor_volt -+ = max(aggr_corner->floor_volt, corner->floor_volt); -+ aggr_corner->last_volt -+ = max(aggr_corner->last_volt, corner->last_volt); -+ aggr_corner->system_volt -+ = max(aggr_corner->system_volt, corner->system_volt); -+ aggr_corner->mem_acc_volt -+ = max(aggr_corner->mem_acc_volt, corner->mem_acc_volt); -+ aggr_corner->irq_en |= corner->irq_en; -+ aggr_corner->use_open_loop |= corner->use_open_loop; -+ -+ if (aggr_quot) { -+ aggr_corner->ro_mask &= corner->ro_mask; -+ -+ for (i = 0; i < CPR3_RO_COUNT; i++) -+ aggr_corner->target_quot[i] -+ = max(aggr_corner->target_quot[i], -+ corner->target_quot[i]); -+ } -+ -+ if (aggr_corner->sdelta && corner->sdelta -+ && (aggr_corner->sdelta->table -+ || aggr_corner->sdelta->boost_table)) { -+ cpr3_regulator_aggregate_sdelta(aggr_corner, corner, step_volt); -+ } else { -+ aggr_corner->open_loop_volt -+ = max(aggr_corner->open_loop_volt, -+ corner->open_loop_volt); -+ } -+} -+ -+/** -+ * cpr3_regulator_update_ctrl_state() - update the state of the CPR controller -+ * to reflect the corners used by all CPR3 regulators as well as -+ * the CPR operating mode -+ * @ctrl: Pointer to the CPR3 controller -+ * -+ * This function aggregates the CPR parameters for all CPR3 regulators -+ * associated with the VDD supply. Upon success, it sets the aggregated last -+ * known good voltage. -+ * -+ * The VDD supply voltage will not be physically configured unless this -+ * condition is met by at least one of the regulators of the controller: -+ * regulator->vreg_enabled == true && -+ * regulator->current_corner != CPR3_REGULATOR_CORNER_INVALID -+ * -+ * CPR registers for the controller and each thread are updated as long as -+ * ctrl->cpr_enabled == true. -+ * -+ * Note, CPR3 controller lock must be held by the caller. -+ * -+ * Return: 0 on success, errno on failure -+ */ -+static int _cpr3_regulator_update_ctrl_state(struct cpr3_controller *ctrl) -+{ -+ struct cpr3_corner aggr_corner = {}; -+ struct cpr3_thread *thread; -+ struct cpr3_regulator *vreg; -+ struct cpr4_sdelta *sdelta; -+ bool valid = false; -+ bool thread_valid; -+ int i, j, rc, new_volt, vdd_volt, dynamic_floor_volt, last_corner_volt; -+ u32 reg_last_measurement = 0, sdelta_size; -+ int *sdelta_table, *boost_table; -+ -+ last_corner_volt = 0; -+ if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4) { -+ rc = cpr3_ctrl_clear_cpr4_config(ctrl); -+ if (rc) { -+ cpr3_err(ctrl, "failed to clear CPR4 configuration,rc=%d\n", -+ rc); -+ return rc; -+ } -+ } -+ -+ cpr3_ctrl_loop_disable(ctrl); -+ -+ vdd_volt = regulator_get_voltage(ctrl->vdd_regulator); -+ if (vdd_volt < 0) { -+ cpr3_err(ctrl, "regulator_get_voltage(vdd) failed, rc=%d\n", -+ vdd_volt); -+ return vdd_volt; -+ } -+ -+ if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4) { -+ /* -+ * Save aggregated corner open-loop voltage which was programmed -+ * during last corner switch which is used when programming new -+ * aggregated corner open-loop voltage. -+ */ -+ last_corner_volt = ctrl->aggr_corner.open_loop_volt; -+ } -+ -+ if (ctrl->cpr_enabled && ctrl->use_hw_closed_loop && -+ ctrl->ctrl_type == CPR_CTRL_TYPE_CPR3) -+ reg_last_measurement -+ = cpr3_read(ctrl, CPR3_REG_LAST_MEASUREMENT); -+ -+ aggr_corner.sdelta = ctrl->aggr_corner.sdelta; -+ if (aggr_corner.sdelta) { -+ sdelta = aggr_corner.sdelta; -+ sdelta_table = sdelta->table; -+ if (sdelta_table) { -+ sdelta_size = sdelta->max_core_count * -+ sdelta->temp_band_count; -+ memset(sdelta_table, 0, sdelta_size -+ * sizeof(*sdelta_table)); -+ } -+ -+ boost_table = sdelta->boost_table; -+ if (boost_table) -+ memset(boost_table, 0, sdelta->temp_band_count -+ * sizeof(*boost_table)); -+ -+ memset(sdelta, 0, sizeof(*sdelta)); -+ sdelta->table = sdelta_table; -+ sdelta->cap_volt = INT_MAX; -+ sdelta->boost_table = boost_table; -+ } -+ -+ /* Aggregate the requests of all threads */ -+ for (i = 0; i < ctrl->thread_count; i++) { -+ thread = &ctrl->thread[i]; -+ thread_valid = false; -+ -+ sdelta = thread->aggr_corner.sdelta; -+ if (sdelta) { -+ sdelta_table = sdelta->table; -+ if (sdelta_table) { -+ sdelta_size = sdelta->max_core_count * -+ sdelta->temp_band_count; -+ memset(sdelta_table, 0, sdelta_size -+ * sizeof(*sdelta_table)); -+ } -+ -+ boost_table = sdelta->boost_table; -+ if (boost_table) -+ memset(boost_table, 0, sdelta->temp_band_count -+ * sizeof(*boost_table)); -+ -+ memset(sdelta, 0, sizeof(*sdelta)); -+ sdelta->table = sdelta_table; -+ sdelta->cap_volt = INT_MAX; -+ sdelta->boost_table = boost_table; -+ } -+ -+ memset(&thread->aggr_corner, 0, sizeof(thread->aggr_corner)); -+ thread->aggr_corner.sdelta = sdelta; -+ thread->aggr_corner.ro_mask = CPR3_RO_MASK; -+ -+ for (j = 0; j < thread->vreg_count; j++) { -+ vreg = &thread->vreg[j]; -+ -+ if (ctrl->cpr_enabled && ctrl->use_hw_closed_loop) -+ cpr3_update_vreg_closed_loop_volt(vreg, -+ vdd_volt, reg_last_measurement); -+ -+ if (!vreg->vreg_enabled -+ || vreg->current_corner -+ == CPR3_REGULATOR_CORNER_INVALID) { -+ /* Cannot participate in aggregation. */ -+ vreg->aggregated = false; -+ continue; -+ } else { -+ vreg->aggregated = true; -+ thread_valid = true; -+ } -+ -+ cpr3_regulator_aggregate_corners(&thread->aggr_corner, -+ &vreg->corner[vreg->current_corner], -+ true, ctrl->step_volt); -+ } -+ -+ valid |= thread_valid; -+ -+ if (thread_valid) -+ cpr3_regulator_aggregate_corners(&aggr_corner, -+ &thread->aggr_corner, -+ false, ctrl->step_volt); -+ } -+ -+ if (valid && ctrl->cpr_allowed_hw && ctrl->cpr_allowed_sw) { -+ rc = cpr3_closed_loop_enable(ctrl); -+ if (rc) { -+ cpr3_err(ctrl, "could not enable CPR, rc=%d\n", rc); -+ return rc; -+ } -+ } else { -+ rc = cpr3_closed_loop_disable(ctrl); -+ if (rc) { -+ cpr3_err(ctrl, "could not disable CPR, rc=%d\n", rc); -+ return rc; -+ } -+ } -+ -+ /* No threads are enabled with a valid corner so exit. */ -+ if (!valid) -+ return 0; -+ -+ /* -+ * When using CPR hardware closed-loop, the voltage may vary anywhere -+ * between the floor and ceiling voltage without software notification. -+ * Therefore, it is required that the floor to ceiling range for the -+ * aggregated corner not intersect the APM threshold voltage. Adjust -+ * the floor to ceiling range if this requirement is violated. -+ * -+ * The following algorithm is applied in the case that -+ * floor < threshold <= ceiling: -+ * if open_loop >= threshold - adj, then floor = threshold -+ * else ceiling = threshold - step -+ * where adj = an adjustment factor to ensure sufficient voltage margin -+ * and step = VDD output step size -+ * -+ * The open-loop and last known voltages are also bounded by the new -+ * floor or ceiling value as needed. -+ */ -+ if (ctrl->use_hw_closed_loop -+ && aggr_corner.ceiling_volt >= ctrl->apm_threshold_volt -+ && aggr_corner.floor_volt < ctrl->apm_threshold_volt) { -+ -+ if (aggr_corner.open_loop_volt -+ >= ctrl->apm_threshold_volt - ctrl->apm_adj_volt) -+ aggr_corner.floor_volt = ctrl->apm_threshold_volt; -+ else -+ aggr_corner.ceiling_volt -+ = ctrl->apm_threshold_volt - ctrl->step_volt; -+ -+ aggr_corner.last_volt -+ = max(aggr_corner.last_volt, aggr_corner.floor_volt); -+ aggr_corner.last_volt -+ = min(aggr_corner.last_volt, aggr_corner.ceiling_volt); -+ aggr_corner.open_loop_volt -+ = max(aggr_corner.open_loop_volt, aggr_corner.floor_volt); -+ aggr_corner.open_loop_volt -+ = min(aggr_corner.open_loop_volt, aggr_corner.ceiling_volt); -+ } -+ -+ if (ctrl->use_hw_closed_loop -+ && aggr_corner.ceiling_volt >= ctrl->mem_acc_threshold_volt -+ && aggr_corner.floor_volt < ctrl->mem_acc_threshold_volt) { -+ aggr_corner.floor_volt = ctrl->mem_acc_threshold_volt; -+ aggr_corner.last_volt = max(aggr_corner.last_volt, -+ aggr_corner.floor_volt); -+ aggr_corner.open_loop_volt = max(aggr_corner.open_loop_volt, -+ aggr_corner.floor_volt); -+ } -+ -+ if (ctrl->use_hw_closed_loop) { -+ dynamic_floor_volt -+ = cpr3_regulator_get_dynamic_floor_volt(ctrl, -+ reg_last_measurement); -+ if (aggr_corner.floor_volt < dynamic_floor_volt) { -+ aggr_corner.floor_volt = dynamic_floor_volt; -+ aggr_corner.last_volt = max(aggr_corner.last_volt, -+ aggr_corner.floor_volt); -+ aggr_corner.open_loop_volt -+ = max(aggr_corner.open_loop_volt, -+ aggr_corner.floor_volt); -+ aggr_corner.ceiling_volt = max(aggr_corner.ceiling_volt, -+ aggr_corner.floor_volt); -+ } -+ } -+ -+ if (ctrl->cpr_enabled && ctrl->last_corner_was_closed_loop) { -+ /* -+ * Always program open-loop voltage for CPR4 controllers which -+ * support hardware closed-loop. Storing the last closed loop -+ * voltage in corner structure can still help with debugging. -+ */ -+ if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR3) -+ new_volt = aggr_corner.last_volt; -+ else if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4 -+ && ctrl->supports_hw_closed_loop) -+ new_volt = aggr_corner.open_loop_volt; -+ else -+ new_volt = min(aggr_corner.last_volt + -+ cpr3_regulator_max_sdelta_diff(aggr_corner.sdelta, -+ ctrl->step_volt), -+ aggr_corner.ceiling_volt); -+ -+ aggr_corner.last_volt = new_volt; -+ } else { -+ new_volt = aggr_corner.open_loop_volt; -+ aggr_corner.last_volt = aggr_corner.open_loop_volt; -+ } -+ -+ if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4 -+ && ctrl->supports_hw_closed_loop) { -+ /* -+ * Store last aggregated corner open-loop voltage in vdd_volt -+ * which is used when programming current aggregated corner -+ * required voltage. -+ */ -+ vdd_volt = last_corner_volt; -+ } -+ -+ cpr3_debug(ctrl, "setting new voltage=%d uV\n", new_volt); -+ rc = cpr3_regulator_scale_vdd_voltage(ctrl, new_volt, -+ vdd_volt, &aggr_corner); -+ if (rc) { -+ cpr3_err(ctrl, "vdd voltage scaling failed, rc=%d\n", rc); -+ return rc; -+ } -+ -+ /* Only update registers if CPR is enabled. */ -+ if (ctrl->cpr_enabled) { -+ if (ctrl->use_hw_closed_loop) { -+ /* Hardware closed-loop */ -+ -+ /* Set ceiling and floor limits in hardware */ -+ rc = regulator_set_voltage(ctrl->vdd_limit_regulator, -+ aggr_corner.floor_volt, -+ aggr_corner.ceiling_volt); -+ if (rc) { -+ cpr3_err(ctrl, "could not configure HW closed-loop voltage limits, rc=%d\n", -+ rc); -+ return rc; -+ } -+ } else { -+ /* Software closed-loop */ -+ -+ /* -+ * Disable UP or DOWN interrupts when at ceiling or -+ * floor respectively. -+ */ -+ if (new_volt == aggr_corner.floor_volt) -+ aggr_corner.irq_en &= ~CPR3_IRQ_DOWN; -+ if (new_volt == aggr_corner.ceiling_volt) -+ aggr_corner.irq_en &= ~CPR3_IRQ_UP; -+ -+ cpr3_write(ctrl, CPR3_REG_IRQ_CLEAR, -+ CPR3_IRQ_UP | CPR3_IRQ_DOWN); -+ cpr3_write(ctrl, CPR3_REG_IRQ_EN, aggr_corner.irq_en); -+ } -+ -+ for (i = 0; i < ctrl->thread_count; i++) { -+ cpr3_regulator_set_target_quot(&ctrl->thread[i]); -+ -+ for (j = 0; j < ctrl->thread[i].vreg_count; j++) { -+ vreg = &ctrl->thread[i].vreg[j]; -+ -+ if (vreg->vreg_enabled) -+ vreg->last_closed_loop_corner -+ = vreg->current_corner; -+ } -+ } -+ -+ if (ctrl->proc_clock_throttle) { -+ if (aggr_corner.ceiling_volt > aggr_corner.floor_volt -+ && (ctrl->use_hw_closed_loop -+ || new_volt < aggr_corner.ceiling_volt)) -+ cpr3_write(ctrl, CPR3_REG_PD_THROTTLE, -+ ctrl->proc_clock_throttle); -+ else -+ cpr3_write(ctrl, CPR3_REG_PD_THROTTLE, -+ CPR3_PD_THROTTLE_DISABLE); -+ } -+ -+ /* -+ * Ensure that all CPR register writes complete before -+ * re-enabling CPR loop operation. -+ */ -+ wmb(); -+ } else if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4 -+ && ctrl->vdd_limit_regulator) { -+ /* Set ceiling and floor limits in hardware */ -+ rc = regulator_set_voltage(ctrl->vdd_limit_regulator, -+ aggr_corner.floor_volt, -+ aggr_corner.ceiling_volt); -+ if (rc) { -+ cpr3_err(ctrl, "could not configure HW closed-loop voltage limits, rc=%d\n", -+ rc); -+ return rc; -+ } -+ } -+ -+ ctrl->aggr_corner = aggr_corner; -+ -+ if (ctrl->allow_core_count_adj || ctrl->allow_temp_adj -+ || ctrl->allow_boost) { -+ rc = cpr3_controller_program_sdelta(ctrl); -+ if (rc) { -+ cpr3_err(ctrl, "failed to program sdelta, rc=%d\n", rc); -+ return rc; -+ } -+ } -+ -+ /* -+ * Only enable the CPR controller if it is possible to set more than -+ * one vdd-supply voltage. -+ */ -+ if (aggr_corner.ceiling_volt > aggr_corner.floor_volt && -+ !aggr_corner.use_open_loop) -+ cpr3_ctrl_loop_enable(ctrl); -+ -+ ctrl->last_corner_was_closed_loop = ctrl->cpr_enabled; -+ cpr3_debug(ctrl, "CPR configuration updated\n"); -+ -+ return 0; -+} -+ -+/** -+ * cpr3_regulator_wait_for_idle() - wait for the CPR controller to no longer be -+ * busy -+ * @ctrl: Pointer to the CPR3 controller -+ * @max_wait_ns: Max wait time in nanoseconds -+ * -+ * Return: 0 on success or -ETIMEDOUT if the controller was still busy after -+ * the maximum delay time -+ */ -+static int cpr3_regulator_wait_for_idle(struct cpr3_controller *ctrl, -+ s64 max_wait_ns) -+{ -+ ktime_t start, end; -+ s64 time_ns; -+ u32 reg; -+ -+ /* -+ * Ensure that all previous CPR register writes have completed before -+ * checking the status register. -+ */ -+ mb(); -+ -+ start = ktime_get(); -+ do { -+ end = ktime_get(); -+ time_ns = ktime_to_ns(ktime_sub(end, start)); -+ if (time_ns > max_wait_ns) { -+ cpr3_err(ctrl, "CPR controller still busy after %lld us\n", -+ div_s64(time_ns, 1000)); -+ return -ETIMEDOUT; -+ } -+ usleep_range(50, 100); -+ reg = cpr3_read(ctrl, CPR3_REG_CPR_STATUS); -+ } while (reg & CPR3_CPR_STATUS_BUSY_MASK); -+ -+ return 0; -+} -+ -+/** -+ * cmp_int() - int comparison function to be passed into the sort() function -+ * which leads to ascending sorting -+ * @a: First int value -+ * @b: Second int value -+ * -+ * Return: >0 if a > b, 0 if a == b, <0 if a < b -+ */ -+static int cmp_int(const void *a, const void *b) -+{ -+ return *(int *)a - *(int *)b; -+} -+ -+/** -+ * cpr3_regulator_measure_aging() - measure the quotient difference for the -+ * specified CPR aging sensor -+ * @ctrl: Pointer to the CPR3 controller -+ * @aging_sensor: Aging sensor to measure -+ * -+ * Note that vdd-supply must be configured to the aging reference voltage before -+ * calling this function. -+ * -+ * Return: 0 on success, errno on failure -+ */ -+static int cpr3_regulator_measure_aging(struct cpr3_controller *ctrl, -+ struct cpr3_aging_sensor_info *aging_sensor) -+{ -+ u32 mask, reg, result, quot_min, quot_max, sel_min, sel_max; -+ u32 quot_min_scaled, quot_max_scaled; -+ u32 gcnt, gcnt_ref, gcnt0_restore, gcnt1_restore, irq_restore; -+ u32 ro_mask_restore, cont_dly_restore, up_down_dly_restore = 0; -+ int quot_delta, quot_delta_scaled, quot_delta_scaled_sum; -+ int *quot_delta_results; -+ int rc, rc2, i, aging_measurement_count, filtered_count; -+ bool is_aging_measurement; -+ -+ quot_delta_results = kcalloc(CPR3_AGING_MEASUREMENT_ITERATIONS, -+ sizeof(*quot_delta_results), GFP_KERNEL); -+ if (!quot_delta_results) -+ return -ENOMEM; -+ -+ if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4) { -+ rc = cpr3_ctrl_clear_cpr4_config(ctrl); -+ if (rc) { -+ cpr3_err(ctrl, "failed to clear CPR4 configuration,rc=%d\n", -+ rc); -+ kfree(quot_delta_results); -+ return rc; -+ } -+ } -+ -+ cpr3_ctrl_loop_disable(ctrl); -+ -+ /* Enable up, down, and mid CPR interrupts */ -+ irq_restore = cpr3_read(ctrl, CPR3_REG_IRQ_EN); -+ cpr3_write(ctrl, CPR3_REG_IRQ_EN, -+ CPR3_IRQ_UP | CPR3_IRQ_DOWN | CPR3_IRQ_MID); -+ -+ /* Ensure that the aging sensor is assigned to CPR thread 0 */ -+ cpr3_write(ctrl, CPR3_REG_SENSOR_OWNER(aging_sensor->sensor_id), 0); -+ -+ /* Switch from HW to SW closed-loop if necessary */ -+ if (ctrl->supports_hw_closed_loop) { -+ if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4) { -+ cpr3_masked_write(ctrl, CPR4_REG_MARGIN_ADJ_CTL, -+ CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_EN_MASK, -+ CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_DISABLE); -+ } else if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR3) { -+ cpr3_write(ctrl, CPR3_REG_HW_CLOSED_LOOP, -+ CPR3_HW_CLOSED_LOOP_DISABLE); -+ } -+ } -+ -+ /* Configure the GCNT for RO0 and RO1 that are used for aging */ -+ gcnt0_restore = cpr3_read(ctrl, CPR3_REG_GCNT(0)); -+ gcnt1_restore = cpr3_read(ctrl, CPR3_REG_GCNT(1)); -+ gcnt_ref = cpr3_regulator_get_gcnt(ctrl); -+ gcnt = gcnt_ref * 3 / 2; -+ cpr3_write(ctrl, CPR3_REG_GCNT(0), gcnt); -+ cpr3_write(ctrl, CPR3_REG_GCNT(1), gcnt); -+ -+ /* Unmask all RO's */ -+ ro_mask_restore = cpr3_read(ctrl, CPR3_REG_RO_MASK(0)); -+ cpr3_write(ctrl, CPR3_REG_RO_MASK(0), 0); -+ -+ /* -+ * Mask all sensors except for the one to measure and bypass all -+ * sensors in collapsible domains. -+ */ -+ for (i = 0; i <= ctrl->sensor_count / 32; i++) { -+ mask = GENMASK(min(31, ctrl->sensor_count - i * 32), 0); -+ if (aging_sensor->sensor_id / 32 >= i -+ && aging_sensor->sensor_id / 32 < (i + 1)) -+ mask &= ~BIT(aging_sensor->sensor_id % 32); -+ cpr3_write(ctrl, CPR3_REG_SENSOR_MASK_WRITE_BANK(i), mask); -+ cpr3_write(ctrl, CPR3_REG_SENSOR_BYPASS_WRITE_BANK(i), -+ aging_sensor->bypass_mask[i]); -+ } -+ -+ /* Set CPR loop delays to 0 us */ -+ if (ctrl->supports_hw_closed_loop -+ && ctrl->ctrl_type == CPR_CTRL_TYPE_CPR3) { -+ cont_dly_restore = cpr3_read(ctrl, CPR3_REG_CPR_TIMER_MID_CONT); -+ up_down_dly_restore = cpr3_read(ctrl, -+ CPR3_REG_CPR_TIMER_UP_DN_CONT); -+ cpr3_write(ctrl, CPR3_REG_CPR_TIMER_MID_CONT, 0); -+ cpr3_write(ctrl, CPR3_REG_CPR_TIMER_UP_DN_CONT, 0); -+ } else { -+ cont_dly_restore = cpr3_read(ctrl, -+ CPR3_REG_CPR_TIMER_AUTO_CONT); -+ cpr3_write(ctrl, CPR3_REG_CPR_TIMER_AUTO_CONT, 0); -+ } -+ -+ /* Set count mode to all-at-once min with no repeat */ -+ cpr3_masked_write(ctrl, CPR3_REG_CPR_CTL, -+ CPR3_CPR_CTL_COUNT_MODE_MASK | CPR3_CPR_CTL_COUNT_REPEAT_MASK, -+ CPR3_CPR_CTL_COUNT_MODE_ALL_AT_ONCE_MIN -+ << CPR3_CPR_CTL_COUNT_MODE_SHIFT); -+ -+ cpr3_ctrl_loop_enable(ctrl); -+ -+ rc = cpr3_regulator_wait_for_idle(ctrl, -+ CPR3_AGING_MEASUREMENT_TIMEOUT_NS); -+ if (rc) -+ goto cleanup; -+ -+ /* Set count mode to all-at-once aging */ -+ cpr3_masked_write(ctrl, CPR3_REG_CPR_CTL, CPR3_CPR_CTL_COUNT_MODE_MASK, -+ CPR3_CPR_CTL_COUNT_MODE_ALL_AT_ONCE_AGE -+ << CPR3_CPR_CTL_COUNT_MODE_SHIFT); -+ -+ aging_measurement_count = 0; -+ for (i = 0; i < CPR3_AGING_MEASUREMENT_ITERATIONS; i++) { -+ /* Send CONT_NACK */ -+ cpr3_write(ctrl, CPR3_REG_CONT_CMD, CPR3_CONT_CMD_NACK); -+ -+ rc = cpr3_regulator_wait_for_idle(ctrl, -+ CPR3_AGING_MEASUREMENT_TIMEOUT_NS); -+ if (rc) -+ goto cleanup; -+ -+ /* Check for PAGE_IS_AGE flag in status register */ -+ reg = cpr3_read(ctrl, CPR3_REG_CPR_STATUS); -+ is_aging_measurement -+ = reg & CPR3_CPR_STATUS_AGING_MEASUREMENT_MASK; -+ -+ /* Read CPR measurement results */ -+ result = cpr3_read(ctrl, CPR3_REG_RESULT1(0)); -+ quot_min = (result & CPR3_RESULT1_QUOT_MIN_MASK) -+ >> CPR3_RESULT1_QUOT_MIN_SHIFT; -+ quot_max = (result & CPR3_RESULT1_QUOT_MAX_MASK) -+ >> CPR3_RESULT1_QUOT_MAX_SHIFT; -+ sel_min = (result & CPR3_RESULT1_RO_MIN_MASK) -+ >> CPR3_RESULT1_RO_MIN_SHIFT; -+ sel_max = (result & CPR3_RESULT1_RO_MAX_MASK) -+ >> CPR3_RESULT1_RO_MAX_SHIFT; -+ -+ /* -+ * Scale the quotients so that they are equivalent to the fused -+ * values. This accounts for the difference in measurement -+ * interval times. -+ */ -+ quot_min_scaled = quot_min * (gcnt_ref + 1) / (gcnt + 1); -+ quot_max_scaled = quot_max * (gcnt_ref + 1) / (gcnt + 1); -+ -+ if (sel_max == 1) { -+ quot_delta = quot_max - quot_min; -+ quot_delta_scaled = quot_max_scaled - quot_min_scaled; -+ } else { -+ quot_delta = quot_min - quot_max; -+ quot_delta_scaled = quot_min_scaled - quot_max_scaled; -+ } -+ -+ if (is_aging_measurement) -+ quot_delta_results[aging_measurement_count++] -+ = quot_delta_scaled; -+ -+ cpr3_debug(ctrl, "aging results: page_is_age=%u, sel_min=%u, sel_max=%u, quot_min=%u, quot_max=%u, quot_delta=%d, quot_min_scaled=%u, quot_max_scaled=%u, quot_delta_scaled=%d\n", -+ is_aging_measurement, sel_min, sel_max, quot_min, -+ quot_max, quot_delta, quot_min_scaled, quot_max_scaled, -+ quot_delta_scaled); -+ } -+ -+ filtered_count -+ = aging_measurement_count - CPR3_AGING_MEASUREMENT_FILTER * 2; -+ if (filtered_count > 0) { -+ sort(quot_delta_results, aging_measurement_count, -+ sizeof(*quot_delta_results), cmp_int, NULL); -+ -+ quot_delta_scaled_sum = 0; -+ for (i = 0; i < filtered_count; i++) -+ quot_delta_scaled_sum -+ += quot_delta_results[i -+ + CPR3_AGING_MEASUREMENT_FILTER]; -+ -+ aging_sensor->measured_quot_diff -+ = quot_delta_scaled_sum / filtered_count; -+ cpr3_info(ctrl, "average quotient delta=%d (count=%d)\n", -+ aging_sensor->measured_quot_diff, -+ filtered_count); -+ } else { -+ cpr3_err(ctrl, "%d aging measurements completed after %d iterations\n", -+ aging_measurement_count, -+ CPR3_AGING_MEASUREMENT_ITERATIONS); -+ rc = -EBUSY; -+ } -+ -+cleanup: -+ kfree(quot_delta_results); -+ -+ if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4) { -+ rc2 = cpr3_ctrl_clear_cpr4_config(ctrl); -+ if (rc2) { -+ cpr3_err(ctrl, "failed to clear CPR4 configuration,rc=%d\n", -+ rc2); -+ rc = rc2; -+ } -+ } -+ -+ cpr3_ctrl_loop_disable(ctrl); -+ -+ cpr3_write(ctrl, CPR3_REG_IRQ_EN, irq_restore); -+ -+ cpr3_write(ctrl, CPR3_REG_RO_MASK(0), ro_mask_restore); -+ -+ cpr3_write(ctrl, CPR3_REG_GCNT(0), gcnt0_restore); -+ cpr3_write(ctrl, CPR3_REG_GCNT(1), gcnt1_restore); -+ -+ if (ctrl->supports_hw_closed_loop -+ && ctrl->ctrl_type == CPR_CTRL_TYPE_CPR3) { -+ cpr3_write(ctrl, CPR3_REG_CPR_TIMER_MID_CONT, cont_dly_restore); -+ cpr3_write(ctrl, CPR3_REG_CPR_TIMER_UP_DN_CONT, -+ up_down_dly_restore); -+ } else { -+ cpr3_write(ctrl, CPR3_REG_CPR_TIMER_AUTO_CONT, -+ cont_dly_restore); -+ } -+ -+ for (i = 0; i <= ctrl->sensor_count / 32; i++) { -+ cpr3_write(ctrl, CPR3_REG_SENSOR_MASK_WRITE_BANK(i), 0); -+ cpr3_write(ctrl, CPR3_REG_SENSOR_BYPASS_WRITE_BANK(i), 0); -+ } -+ -+ cpr3_masked_write(ctrl, CPR3_REG_CPR_CTL, -+ CPR3_CPR_CTL_COUNT_MODE_MASK | CPR3_CPR_CTL_COUNT_REPEAT_MASK, -+ (ctrl->count_mode << CPR3_CPR_CTL_COUNT_MODE_SHIFT) -+ | (ctrl->count_repeat << CPR3_CPR_CTL_COUNT_REPEAT_SHIFT)); -+ -+ cpr3_write(ctrl, CPR3_REG_SENSOR_OWNER(aging_sensor->sensor_id), -+ ctrl->sensor_owner[aging_sensor->sensor_id]); -+ -+ cpr3_write(ctrl, CPR3_REG_IRQ_CLEAR, -+ CPR3_IRQ_UP | CPR3_IRQ_DOWN | CPR3_IRQ_MID); -+ -+ if (ctrl->supports_hw_closed_loop) { -+ if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4) { -+ cpr3_masked_write(ctrl, CPR4_REG_MARGIN_ADJ_CTL, -+ CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_EN_MASK, -+ ctrl->use_hw_closed_loop -+ ? CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_ENABLE -+ : CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_DISABLE); -+ } else if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR3) { -+ cpr3_write(ctrl, CPR3_REG_HW_CLOSED_LOOP, -+ ctrl->use_hw_closed_loop -+ ? CPR3_HW_CLOSED_LOOP_ENABLE -+ : CPR3_HW_CLOSED_LOOP_DISABLE); -+ } -+ } -+ -+ return rc; -+} -+ -+/** -+ * cpr3_regulator_readjust_volt_and_quot() - readjust the target quotients as -+ * well as the floor, ceiling, and open-loop voltages for the -+ * regulator by removing the old adjustment and adding the new one -+ * @vreg: Pointer to the CPR3 regulator -+ * @old_adjust_volt: Old aging adjustment voltage in microvolts -+ * @new_adjust_volt: New aging adjustment voltage in microvolts -+ * -+ * Also reset the cached closed loop voltage (last_volt) to equal the open-loop -+ * voltage for each corner. -+ * -+ * Return: None -+ */ -+static void cpr3_regulator_readjust_volt_and_quot(struct cpr3_regulator *vreg, -+ int old_adjust_volt, int new_adjust_volt) -+{ -+ unsigned long long temp; -+ int i, j, old_volt, new_volt, rounded_volt; -+ -+ if (!vreg->aging_allowed) -+ return; -+ -+ for (i = 0; i < vreg->corner_count; i++) { -+ temp = (unsigned long long)old_adjust_volt -+ * (unsigned long long)vreg->corner[i].aging_derate; -+ do_div(temp, 1000); -+ old_volt = temp; -+ -+ temp = (unsigned long long)new_adjust_volt -+ * (unsigned long long)vreg->corner[i].aging_derate; -+ do_div(temp, 1000); -+ new_volt = temp; -+ -+ old_volt = min(vreg->aging_max_adjust_volt, old_volt); -+ new_volt = min(vreg->aging_max_adjust_volt, new_volt); -+ -+ for (j = 0; j < CPR3_RO_COUNT; j++) { -+ if (vreg->corner[i].target_quot[j] != 0) { -+ vreg->corner[i].target_quot[j] -+ += cpr3_quot_adjustment( -+ vreg->corner[i].ro_scale[j], -+ new_volt) -+ - cpr3_quot_adjustment( -+ vreg->corner[i].ro_scale[j], -+ old_volt); -+ } -+ } -+ -+ rounded_volt = CPR3_ROUND(new_volt, -+ vreg->thread->ctrl->step_volt); -+ -+ if (!vreg->aging_allow_open_loop_adj) -+ rounded_volt = 0; -+ -+ vreg->corner[i].ceiling_volt -+ = vreg->corner[i].unaged_ceiling_volt + rounded_volt; -+ vreg->corner[i].ceiling_volt = min(vreg->corner[i].ceiling_volt, -+ vreg->corner[i].abs_ceiling_volt); -+ vreg->corner[i].floor_volt -+ = vreg->corner[i].unaged_floor_volt + rounded_volt; -+ vreg->corner[i].floor_volt = min(vreg->corner[i].floor_volt, -+ vreg->corner[i].ceiling_volt); -+ vreg->corner[i].open_loop_volt -+ = vreg->corner[i].unaged_open_loop_volt + rounded_volt; -+ vreg->corner[i].open_loop_volt -+ = min(vreg->corner[i].open_loop_volt, -+ vreg->corner[i].ceiling_volt); -+ -+ vreg->corner[i].last_volt = vreg->corner[i].open_loop_volt; -+ -+ cpr3_debug(vreg, "corner %d: applying %d uV closed-loop and %d uV open-loop voltage margin adjustment\n", -+ i, new_volt, rounded_volt); -+ } -+} -+ -+/** -+ * cpr3_regulator_set_aging_ref_adjustment() - adjust target quotients for the -+ * regulators managed by this CPR controller to account for aging -+ * @ctrl: Pointer to the CPR3 controller -+ * @ref_adjust_volt: New aging reference adjustment voltage in microvolts to -+ * apply to all regulators managed by this CPR controller -+ * -+ * The existing aging adjustment as defined by ctrl->aging_ref_adjust_volt is -+ * first removed and then the adjustment is applied. Lastly, the value of -+ * ctrl->aging_ref_adjust_volt is updated to ref_adjust_volt. -+ */ -+static void cpr3_regulator_set_aging_ref_adjustment( -+ struct cpr3_controller *ctrl, int ref_adjust_volt) -+{ -+ struct cpr3_regulator *vreg; -+ int i, j; -+ -+ for (i = 0; i < ctrl->thread_count; i++) { -+ for (j = 0; j < ctrl->thread[i].vreg_count; j++) { -+ vreg = &ctrl->thread[i].vreg[j]; -+ cpr3_regulator_readjust_volt_and_quot(vreg, -+ ctrl->aging_ref_adjust_volt, ref_adjust_volt); -+ } -+ } -+ -+ ctrl->aging_ref_adjust_volt = ref_adjust_volt; -+} -+ -+/** -+ * cpr3_regulator_aging_adjust() - adjust the target quotients for regulators -+ * based on the output of CPR aging sensors -+ * @ctrl: Pointer to the CPR3 controller -+ * -+ * Return: 0 on success, errno on failure -+ */ -+static int cpr3_regulator_aging_adjust(struct cpr3_controller *ctrl) -+{ -+ struct cpr3_regulator *vreg; -+ struct cpr3_corner restore_aging_corner; -+ struct cpr3_corner *corner; -+ int *restore_current_corner; -+ bool *restore_vreg_enabled; -+ int i, j, id, rc, rc2, vreg_count, aging_volt, max_aging_volt = 0; -+ u32 reg; -+ -+ if (!ctrl->aging_required || !ctrl->cpr_enabled -+ || ctrl->aggr_corner.ceiling_volt == 0 -+ || ctrl->aggr_corner.ceiling_volt > ctrl->aging_ref_volt) -+ return 0; -+ -+ for (i = 0, vreg_count = 0; i < ctrl->thread_count; i++) { -+ for (j = 0; j < ctrl->thread[i].vreg_count; j++) { -+ vreg = &ctrl->thread[i].vreg[j]; -+ vreg_count++; -+ -+ if (vreg->aging_allowed && vreg->vreg_enabled -+ && vreg->current_corner > vreg->aging_corner) -+ return 0; -+ } -+ } -+ -+ /* Verify that none of the aging sensors are currently masked. */ -+ for (i = 0; i < ctrl->aging_sensor_count; i++) { -+ id = ctrl->aging_sensor[i].sensor_id; -+ reg = cpr3_read(ctrl, CPR3_REG_SENSOR_MASK_READ(id)); -+ if (reg & BIT(id % 32)) -+ return 0; -+ } -+ -+ /* -+ * Verify that the aging possible register (if specified) has an -+ * acceptable value. -+ */ -+ if (ctrl->aging_possible_reg) { -+ reg = readl_relaxed(ctrl->aging_possible_reg); -+ reg &= ctrl->aging_possible_mask; -+ if (reg != ctrl->aging_possible_val) -+ return 0; -+ } -+ -+ restore_current_corner = kcalloc(vreg_count, -+ sizeof(*restore_current_corner), GFP_KERNEL); -+ restore_vreg_enabled = kcalloc(vreg_count, -+ sizeof(*restore_vreg_enabled), GFP_KERNEL); -+ if (!restore_current_corner || !restore_vreg_enabled) { -+ kfree(restore_current_corner); -+ kfree(restore_vreg_enabled); -+ return -ENOMEM; -+ } -+ -+ /* Force all regulators to the aging corner */ -+ for (i = 0, vreg_count = 0; i < ctrl->thread_count; i++) { -+ for (j = 0; j < ctrl->thread[i].vreg_count; j++, vreg_count++) { -+ vreg = &ctrl->thread[i].vreg[j]; -+ -+ restore_current_corner[vreg_count] -+ = vreg->current_corner; -+ restore_vreg_enabled[vreg_count] -+ = vreg->vreg_enabled; -+ -+ vreg->current_corner = vreg->aging_corner; -+ vreg->vreg_enabled = true; -+ } -+ } -+ -+ /* Force one of the regulators to require the aging reference voltage */ -+ vreg = &ctrl->thread[0].vreg[0]; -+ corner = &vreg->corner[vreg->current_corner]; -+ restore_aging_corner = *corner; -+ corner->ceiling_volt = ctrl->aging_ref_volt; -+ corner->floor_volt = ctrl->aging_ref_volt; -+ corner->open_loop_volt = ctrl->aging_ref_volt; -+ corner->last_volt = ctrl->aging_ref_volt; -+ -+ /* Skip last_volt caching */ -+ ctrl->last_corner_was_closed_loop = false; -+ -+ /* Set the vdd supply voltage to the aging reference voltage */ -+ rc = _cpr3_regulator_update_ctrl_state(ctrl); -+ if (rc) { -+ cpr3_err(ctrl, "unable to force vdd-supply to the aging reference voltage=%d uV, rc=%d\n", -+ ctrl->aging_ref_volt, rc); -+ goto cleanup; -+ } -+ -+ if (ctrl->aging_vdd_mode) { -+ rc = regulator_set_mode(ctrl->vdd_regulator, -+ ctrl->aging_vdd_mode); -+ if (rc) { -+ cpr3_err(ctrl, "unable to configure vdd-supply for mode=%u, rc=%d\n", -+ ctrl->aging_vdd_mode, rc); -+ goto cleanup; -+ } -+ } -+ -+ /* Perform aging measurement on all aging sensors */ -+ for (i = 0; i < ctrl->aging_sensor_count; i++) { -+ for (j = 0; j < CPR3_AGING_RETRY_COUNT; j++) { -+ rc = cpr3_regulator_measure_aging(ctrl, -+ &ctrl->aging_sensor[i]); -+ if (!rc) -+ break; -+ } -+ -+ if (!rc) { -+ aging_volt = -+ cpr3_voltage_adjustment( -+ ctrl->aging_sensor[i].ro_scale, -+ ctrl->aging_sensor[i].measured_quot_diff -+ - ctrl->aging_sensor[i].init_quot_diff); -+ max_aging_volt = max(max_aging_volt, aging_volt); -+ } else { -+ cpr3_err(ctrl, "CPR aging measurement failed after %d tries, rc=%d\n", -+ j, rc); -+ ctrl->aging_failed = true; -+ ctrl->aging_required = false; -+ goto cleanup; -+ } -+ } -+ -+cleanup: -+ vreg = &ctrl->thread[0].vreg[0]; -+ vreg->corner[vreg->current_corner] = restore_aging_corner; -+ -+ for (i = 0, vreg_count = 0; i < ctrl->thread_count; i++) { -+ for (j = 0; j < ctrl->thread[i].vreg_count; j++, vreg_count++) { -+ vreg = &ctrl->thread[i].vreg[j]; -+ vreg->current_corner -+ = restore_current_corner[vreg_count]; -+ vreg->vreg_enabled = restore_vreg_enabled[vreg_count]; -+ } -+ } -+ -+ kfree(restore_current_corner); -+ kfree(restore_vreg_enabled); -+ -+ /* Adjust the CPR target quotients according to the aging measurement */ -+ if (!rc) { -+ cpr3_regulator_set_aging_ref_adjustment(ctrl, max_aging_volt); -+ -+ cpr3_info(ctrl, "aging measurement successful; aging reference adjustment voltage=%d uV\n", -+ ctrl->aging_ref_adjust_volt); -+ ctrl->aging_succeeded = true; -+ ctrl->aging_required = false; -+ } -+ -+ if (ctrl->aging_complete_vdd_mode) { -+ rc = regulator_set_mode(ctrl->vdd_regulator, -+ ctrl->aging_complete_vdd_mode); -+ if (rc) -+ cpr3_err(ctrl, "unable to configure vdd-supply for mode=%u, rc=%d\n", -+ ctrl->aging_complete_vdd_mode, rc); -+ } -+ -+ /* Skip last_volt caching */ -+ ctrl->last_corner_was_closed_loop = false; -+ -+ /* -+ * Restore vdd-supply to the voltage before the aging measurement and -+ * restore the CPR3 controller hardware state. -+ */ -+ rc2 = _cpr3_regulator_update_ctrl_state(ctrl); -+ -+ /* Stop last_volt caching on for the next request */ -+ ctrl->last_corner_was_closed_loop = false; -+ -+ return rc ? rc : rc2; -+} -+ -+/** -+ * cpr3_regulator_update_ctrl_state() - update the state of the CPR controller -+ * to reflect the corners used by all CPR3 regulators as well as -+ * the CPR operating mode and perform aging adjustments if needed -+ * @ctrl: Pointer to the CPR3 controller -+ * -+ * Note, CPR3 controller lock must be held by the caller. -+ * -+ * Return: 0 on success, errno on failure -+ */ -+static int cpr3_regulator_update_ctrl_state(struct cpr3_controller *ctrl) -+{ -+ int rc; -+ -+ rc = _cpr3_regulator_update_ctrl_state(ctrl); -+ if (rc) -+ return rc; -+ -+ return cpr3_regulator_aging_adjust(ctrl); -+} -+ -+/** -+ * cpr3_regulator_set_voltage() - set the voltage corner for the CPR3 regulator -+ * associated with the regulator device -+ * @rdev: Regulator device pointer for the cpr3-regulator -+ * @corner: New voltage corner to set (offset by CPR3_CORNER_OFFSET) -+ * @corner_max: Maximum voltage corner allowed (offset by -+ * CPR3_CORNER_OFFSET) -+ * @selector: Pointer which is filled with the selector value for the -+ * corner -+ * -+ * This function is passed as a callback function into the regulator ops that -+ * are registered for each cpr3-regulator device. The VDD voltage will not be -+ * physically configured until both this function and cpr3_regulator_enable() -+ * are called. -+ * -+ * Return: 0 on success, errno on failure -+ */ -+static int cpr3_regulator_set_voltage(struct regulator_dev *rdev, -+ int corner, int corner_max, unsigned *selector) -+{ -+ struct cpr3_regulator *vreg = rdev_get_drvdata(rdev); -+ struct cpr3_controller *ctrl = vreg->thread->ctrl; -+ int rc = 0; -+ int last_corner; -+ -+ corner -= CPR3_CORNER_OFFSET; -+ corner_max -= CPR3_CORNER_OFFSET; -+ *selector = corner; -+ -+ mutex_lock(&ctrl->lock); -+ -+ if (!vreg->vreg_enabled) { -+ vreg->current_corner = corner; -+ cpr3_debug(vreg, "stored corner=%d\n", corner); -+ goto done; -+ } else if (vreg->current_corner == corner) { -+ goto done; -+ } -+ -+ last_corner = vreg->current_corner; -+ vreg->current_corner = corner; -+ -+ if (vreg->cpr4_regulator_data != NULL) -+ if (vreg->cpr4_regulator_data->mem_acc_funcs != NULL) -+ vreg->cpr4_regulator_data->mem_acc_funcs->set_mem_acc(rdev); -+ -+ rc = cpr3_regulator_update_ctrl_state(ctrl); -+ if (rc) { -+ cpr3_err(vreg, "could not update CPR state, rc=%d\n", rc); -+ vreg->current_corner = last_corner; -+ } -+ -+ if (vreg->cpr4_regulator_data != NULL) -+ if (vreg->cpr4_regulator_data->mem_acc_funcs != NULL) -+ vreg->cpr4_regulator_data->mem_acc_funcs->clear_mem_acc(rdev); -+ -+ cpr3_debug(vreg, "set corner=%d\n", corner); -+done: -+ mutex_unlock(&ctrl->lock); -+ -+ return rc; -+} -+ -+/** -+ * cpr3_handle_temp_open_loop_adjustment() - voltage based cold temperature -+ * -+ * @rdev: Regulator device pointer for the cpr3-regulator -+ * @is_cold: Flag to denote enter/exit cold condition -+ * -+ * This function is adjusts voltage margin based on cold condition -+ * -+ * Return: 0 = success -+ */ -+ -+int cpr3_handle_temp_open_loop_adjustment(struct cpr3_controller *ctrl, -+ bool is_cold) -+{ -+ int i ,j, k, rc; -+ struct cpr3_regulator *vreg; -+ -+ mutex_lock(&ctrl->lock); -+ for (i = 0; i < ctrl->thread_count; i++) { -+ for (j = 0; j < ctrl->thread[i].vreg_count; j++) { -+ vreg = &ctrl->thread[i].vreg[j]; -+ for (k = 0; k < vreg->corner_count; k++) { -+ vreg->corner[k].open_loop_volt = is_cold ? -+ vreg->corner[k].cold_temp_open_loop_volt : -+ vreg->corner[k].normal_temp_open_loop_volt; -+ } -+ } -+ } -+ rc = cpr3_regulator_update_ctrl_state(ctrl); -+ mutex_unlock(&ctrl->lock); -+ -+ return rc; -+} -+ -+/** -+ * cpr3_regulator_get_voltage() - get the voltage corner for the CPR3 regulator -+ * associated with the regulator device -+ * @rdev: Regulator device pointer for the cpr3-regulator -+ * -+ * This function is passed as a callback function into the regulator ops that -+ * are registered for each cpr3-regulator device. -+ * -+ * Return: voltage corner value offset by CPR3_CORNER_OFFSET -+ */ -+static int cpr3_regulator_get_voltage(struct regulator_dev *rdev) -+{ -+ struct cpr3_regulator *vreg = rdev_get_drvdata(rdev); -+ -+ if (vreg->current_corner == CPR3_REGULATOR_CORNER_INVALID) -+ return CPR3_CORNER_OFFSET; -+ else -+ return vreg->current_corner + CPR3_CORNER_OFFSET; -+} -+ -+/** -+ * cpr3_regulator_list_voltage() - return the voltage corner mapped to the -+ * specified selector -+ * @rdev: Regulator device pointer for the cpr3-regulator -+ * @selector: Regulator selector -+ * -+ * This function is passed as a callback function into the regulator ops that -+ * are registered for each cpr3-regulator device. -+ * -+ * Return: voltage corner value offset by CPR3_CORNER_OFFSET -+ */ -+static int cpr3_regulator_list_voltage(struct regulator_dev *rdev, -+ unsigned selector) -+{ -+ struct cpr3_regulator *vreg = rdev_get_drvdata(rdev); -+ -+ if (selector < vreg->corner_count) -+ return selector + CPR3_CORNER_OFFSET; -+ else -+ return 0; -+} -+ -+/** -+ * cpr3_regulator_is_enabled() - return the enable state of the CPR3 regulator -+ * @rdev: Regulator device pointer for the cpr3-regulator -+ * -+ * This function is passed as a callback function into the regulator ops that -+ * are registered for each cpr3-regulator device. -+ * -+ * Return: true if regulator is enabled, false if regulator is disabled -+ */ -+static int cpr3_regulator_is_enabled(struct regulator_dev *rdev) -+{ -+ struct cpr3_regulator *vreg = rdev_get_drvdata(rdev); -+ -+ return vreg->vreg_enabled; -+} -+ -+/** -+ * cpr3_regulator_enable() - enable the CPR3 regulator -+ * @rdev: Regulator device pointer for the cpr3-regulator -+ * -+ * This function is passed as a callback function into the regulator ops that -+ * are registered for each cpr3-regulator device. -+ * -+ * Return: 0 on success, errno on failure -+ */ -+static int cpr3_regulator_enable(struct regulator_dev *rdev) -+{ -+ struct cpr3_regulator *vreg = rdev_get_drvdata(rdev); -+ struct cpr3_controller *ctrl = vreg->thread->ctrl; -+ int rc = 0; -+ -+ if (vreg->vreg_enabled == true) -+ return 0; -+ -+ mutex_lock(&ctrl->lock); -+ -+ if (ctrl->system_regulator) { -+ rc = regulator_enable(ctrl->system_regulator); -+ if (rc) { -+ cpr3_err(ctrl, "regulator_enable(system) failed, rc=%d\n", -+ rc); -+ goto done; -+ } -+ } -+ -+ rc = regulator_enable(ctrl->vdd_regulator); -+ if (rc) { -+ cpr3_err(vreg, "regulator_enable(vdd) failed, rc=%d\n", rc); -+ goto done; -+ } -+ -+ vreg->vreg_enabled = true; -+ rc = cpr3_regulator_update_ctrl_state(ctrl); -+ if (rc) { -+ cpr3_err(vreg, "could not update CPR state, rc=%d\n", rc); -+ regulator_disable(ctrl->vdd_regulator); -+ vreg->vreg_enabled = false; -+ goto done; -+ } -+ -+ cpr3_debug(vreg, "Enabled\n"); -+done: -+ mutex_unlock(&ctrl->lock); -+ -+ return rc; -+} -+ -+/** -+ * cpr3_regulator_disable() - disable the CPR3 regulator -+ * @rdev: Regulator device pointer for the cpr3-regulator -+ * -+ * This function is passed as a callback function into the regulator ops that -+ * are registered for each cpr3-regulator device. -+ * -+ * Return: 0 on success, errno on failure -+ */ -+static int cpr3_regulator_disable(struct regulator_dev *rdev) -+{ -+ struct cpr3_regulator *vreg = rdev_get_drvdata(rdev); -+ struct cpr3_controller *ctrl = vreg->thread->ctrl; -+ int rc, rc2; -+ -+ if (vreg->vreg_enabled == false) -+ return 0; -+ -+ mutex_lock(&ctrl->lock); -+ rc = regulator_disable(ctrl->vdd_regulator); -+ if (rc) { -+ cpr3_err(vreg, "regulator_disable(vdd) failed, rc=%d\n", rc); -+ goto done; -+ } -+ -+ vreg->vreg_enabled = false; -+ rc = cpr3_regulator_update_ctrl_state(ctrl); -+ if (rc) { -+ cpr3_err(vreg, "could not update CPR state, rc=%d\n", rc); -+ rc2 = regulator_enable(ctrl->vdd_regulator); -+ vreg->vreg_enabled = true; -+ goto done; -+ } -+ -+ if (ctrl->system_regulator) { -+ rc = regulator_disable(ctrl->system_regulator); -+ if (rc) { -+ cpr3_err(ctrl, "regulator_disable(system) failed, rc=%d\n", -+ rc); -+ goto done; -+ } -+ } -+ -+ cpr3_debug(vreg, "Disabled\n"); -+done: -+ mutex_unlock(&ctrl->lock); -+ -+ return rc; -+} -+ -+static struct regulator_ops cpr3_regulator_ops = { -+ .enable = cpr3_regulator_enable, -+ .disable = cpr3_regulator_disable, -+ .is_enabled = cpr3_regulator_is_enabled, -+ .set_voltage = cpr3_regulator_set_voltage, -+ .get_voltage = cpr3_regulator_get_voltage, -+ .list_voltage = cpr3_regulator_list_voltage, -+}; -+ -+/** -+ * cpr3_print_result() - print CPR measurement results to the kernel log for -+ * debugging purposes -+ * @thread: Pointer to the CPR3 thread -+ * -+ * Return: None -+ */ -+static void cpr3_print_result(struct cpr3_thread *thread) -+{ -+ struct cpr3_controller *ctrl = thread->ctrl; -+ u32 result[3], busy, step_dn, step_up, error_steps, error, negative; -+ u32 quot_min, quot_max, ro_min, ro_max, step_quot_min, step_quot_max; -+ u32 sensor_min, sensor_max; -+ char *sign; -+ -+ result[0] = cpr3_read(ctrl, CPR3_REG_RESULT0(thread->thread_id)); -+ result[1] = cpr3_read(ctrl, CPR3_REG_RESULT1(thread->thread_id)); -+ result[2] = cpr3_read(ctrl, CPR3_REG_RESULT2(thread->thread_id)); -+ -+ busy = !!(result[0] & CPR3_RESULT0_BUSY_MASK); -+ step_dn = !!(result[0] & CPR3_RESULT0_STEP_DN_MASK); -+ step_up = !!(result[0] & CPR3_RESULT0_STEP_UP_MASK); -+ error_steps = (result[0] & CPR3_RESULT0_ERROR_STEPS_MASK) -+ >> CPR3_RESULT0_ERROR_STEPS_SHIFT; -+ error = (result[0] & CPR3_RESULT0_ERROR_MASK) -+ >> CPR3_RESULT0_ERROR_SHIFT; -+ negative = !!(result[0] & CPR3_RESULT0_NEGATIVE_MASK); -+ -+ quot_min = (result[1] & CPR3_RESULT1_QUOT_MIN_MASK) -+ >> CPR3_RESULT1_QUOT_MIN_SHIFT; -+ quot_max = (result[1] & CPR3_RESULT1_QUOT_MAX_MASK) -+ >> CPR3_RESULT1_QUOT_MAX_SHIFT; -+ ro_min = (result[1] & CPR3_RESULT1_RO_MIN_MASK) -+ >> CPR3_RESULT1_RO_MIN_SHIFT; -+ ro_max = (result[1] & CPR3_RESULT1_RO_MAX_MASK) -+ >> CPR3_RESULT1_RO_MAX_SHIFT; -+ -+ step_quot_min = (result[2] & CPR3_RESULT2_STEP_QUOT_MIN_MASK) -+ >> CPR3_RESULT2_STEP_QUOT_MIN_SHIFT; -+ step_quot_max = (result[2] & CPR3_RESULT2_STEP_QUOT_MAX_MASK) -+ >> CPR3_RESULT2_STEP_QUOT_MAX_SHIFT; -+ sensor_min = (result[2] & CPR3_RESULT2_SENSOR_MIN_MASK) -+ >> CPR3_RESULT2_SENSOR_MIN_SHIFT; -+ sensor_max = (result[2] & CPR3_RESULT2_SENSOR_MAX_MASK) -+ >> CPR3_RESULT2_SENSOR_MAX_SHIFT; -+ -+ sign = negative ? "-" : ""; -+ cpr3_debug(ctrl, "thread %u: busy=%u, step_dn=%u, step_up=%u, error_steps=%s%u, error=%s%u\n", -+ thread->thread_id, busy, step_dn, step_up, sign, error_steps, -+ sign, error); -+ cpr3_debug(ctrl, "thread %u: quot_min=%u, quot_max=%u, ro_min=%u, ro_max=%u\n", -+ thread->thread_id, quot_min, quot_max, ro_min, ro_max); -+ cpr3_debug(ctrl, "thread %u: step_quot_min=%u, step_quot_max=%u, sensor_min=%u, sensor_max=%u\n", -+ thread->thread_id, step_quot_min, step_quot_max, sensor_min, -+ sensor_max); -+} -+ -+/** -+ * cpr3_thread_busy() - returns if the specified CPR3 thread is busy taking -+ * a measurement -+ * @thread: Pointer to the CPR3 thread -+ * -+ * Return: CPR3 busy status -+ */ -+static bool cpr3_thread_busy(struct cpr3_thread *thread) -+{ -+ u32 result; -+ -+ result = cpr3_read(thread->ctrl, CPR3_REG_RESULT0(thread->thread_id)); -+ -+ return !!(result & CPR3_RESULT0_BUSY_MASK); -+} -+ -+/** -+ * cpr3_irq_handler() - CPR interrupt handler callback function used for -+ * software closed-loop operation -+ * @irq: CPR interrupt number -+ * @data: Private data corresponding to the CPR3 controller -+ * pointer -+ * -+ * This function increases or decreases the vdd supply voltage based upon the -+ * CPR controller recommendation. -+ * -+ * Return: IRQ_HANDLED -+ */ -+static irqreturn_t cpr3_irq_handler(int irq, void *data) -+{ -+ struct cpr3_controller *ctrl = data; -+ struct cpr3_corner *aggr = &ctrl->aggr_corner; -+ u32 cont = CPR3_CONT_CMD_NACK; -+ u32 reg_last_measurement = 0; -+ struct cpr3_regulator *vreg; -+ struct cpr3_corner *corner; -+ unsigned long flags; -+ int i, j, new_volt, last_volt, dynamic_floor_volt, rc; -+ u32 irq_en, status, cpr_status, ctl; -+ bool up, down; -+ -+ mutex_lock(&ctrl->lock); -+ -+ if (!ctrl->cpr_enabled) { -+ cpr3_debug(ctrl, "CPR interrupt received but CPR is disabled\n"); -+ mutex_unlock(&ctrl->lock); -+ return IRQ_HANDLED; -+ } else if (ctrl->use_hw_closed_loop) { -+ cpr3_debug(ctrl, "CPR interrupt received but CPR is using HW closed-loop\n"); -+ goto done; -+ } -+ -+ /* -+ * CPR IRQ status checking and CPR controller disabling must happen -+ * atomically and without invening delay in order to avoid an interrupt -+ * storm caused by the handler racing with the CPR controller. -+ */ -+ local_irq_save(flags); -+ preempt_disable(); -+ -+ status = cpr3_read(ctrl, CPR3_REG_IRQ_STATUS); -+ up = status & CPR3_IRQ_UP; -+ down = status & CPR3_IRQ_DOWN; -+ -+ if (!up && !down) { -+ /* -+ * Toggle the CPR controller off and then back on since the -+ * hardware and software states are out of sync. This condition -+ * occurs after an aging measurement completes as the CPR IRQ -+ * physically triggers during the aging measurement but the -+ * handler is stuck waiting on the mutex lock. -+ */ -+ cpr3_ctrl_loop_disable(ctrl); -+ -+ local_irq_restore(flags); -+ preempt_enable(); -+ -+ /* Wait for the loop disable write to complete */ -+ mb(); -+ -+ /* Wait for BUSY=1 and LOOP_EN=0 in CPR controller registers. */ -+ for (i = 0; i < CPR3_REGISTER_WRITE_DELAY_US / 10; i++) { -+ cpr_status = cpr3_read(ctrl, CPR3_REG_CPR_STATUS); -+ ctl = cpr3_read(ctrl, CPR3_REG_CPR_CTL); -+ if (cpr_status & CPR3_CPR_STATUS_BUSY_MASK -+ && (ctl & CPR3_CPR_CTL_LOOP_EN_MASK) -+ == CPR3_CPR_CTL_LOOP_DISABLE) -+ break; -+ udelay(10); -+ } -+ if (i == CPR3_REGISTER_WRITE_DELAY_US / 10) -+ cpr3_debug(ctrl, "CPR controller not disabled after %d us\n", -+ CPR3_REGISTER_WRITE_DELAY_US); -+ -+ /* Clear interrupt status */ -+ cpr3_write(ctrl, CPR3_REG_IRQ_CLEAR, -+ CPR3_IRQ_UP | CPR3_IRQ_DOWN); -+ -+ /* Wait for the interrupt clearing write to complete */ -+ mb(); -+ -+ /* Wait for IRQ_STATUS register to be cleared. */ -+ for (i = 0; i < CPR3_REGISTER_WRITE_DELAY_US / 10; i++) { -+ status = cpr3_read(ctrl, CPR3_REG_IRQ_STATUS); -+ if (!(status & (CPR3_IRQ_UP | CPR3_IRQ_DOWN))) -+ break; -+ udelay(10); -+ } -+ if (i == CPR3_REGISTER_WRITE_DELAY_US / 10) -+ cpr3_debug(ctrl, "CPR interrupts not cleared after %d us\n", -+ CPR3_REGISTER_WRITE_DELAY_US); -+ -+ cpr3_ctrl_loop_enable(ctrl); -+ -+ cpr3_debug(ctrl, "CPR interrupt received but no up or down status bit is set\n"); -+ -+ mutex_unlock(&ctrl->lock); -+ return IRQ_HANDLED; -+ } else if (up && down) { -+ cpr3_debug(ctrl, "both up and down status bits set\n"); -+ /* The up flag takes precedence over the down flag. */ -+ down = false; -+ } -+ -+ if (ctrl->supports_hw_closed_loop) -+ reg_last_measurement -+ = cpr3_read(ctrl, CPR3_REG_LAST_MEASUREMENT); -+ dynamic_floor_volt = cpr3_regulator_get_dynamic_floor_volt(ctrl, -+ reg_last_measurement); -+ -+ local_irq_restore(flags); -+ preempt_enable(); -+ -+ irq_en = aggr->irq_en; -+ last_volt = aggr->last_volt; -+ -+ for (i = 0; i < ctrl->thread_count; i++) { -+ if (cpr3_thread_busy(&ctrl->thread[i])) { -+ cpr3_debug(ctrl, "CPR thread %u busy when it should be waiting for SW cont\n", -+ ctrl->thread[i].thread_id); -+ goto done; -+ } -+ } -+ -+ new_volt = up ? last_volt + ctrl->step_volt -+ : last_volt - ctrl->step_volt; -+ -+ /* Re-enable UP/DOWN interrupt when its opposite is received. */ -+ irq_en |= up ? CPR3_IRQ_DOWN : CPR3_IRQ_UP; -+ -+ if (new_volt > aggr->ceiling_volt) { -+ new_volt = aggr->ceiling_volt; -+ irq_en &= ~CPR3_IRQ_UP; -+ cpr3_debug(ctrl, "limiting to ceiling=%d uV\n", -+ aggr->ceiling_volt); -+ } else if (new_volt < aggr->floor_volt) { -+ new_volt = aggr->floor_volt; -+ irq_en &= ~CPR3_IRQ_DOWN; -+ cpr3_debug(ctrl, "limiting to floor=%d uV\n", aggr->floor_volt); -+ } -+ -+ if (down && new_volt < dynamic_floor_volt) { -+ /* -+ * The vdd-supply voltage should not be decreased below the -+ * dynamic floor voltage. However, it is not necessary (and -+ * counter productive) to force the voltage up to this level -+ * if it happened to be below it since the closed-loop voltage -+ * must have gotten there in a safe manner while the power -+ * domains for the CPR3 regulator imposing the dynamic floor -+ * were not bypassed. -+ */ -+ new_volt = last_volt; -+ irq_en &= ~CPR3_IRQ_DOWN; -+ cpr3_debug(ctrl, "limiting to dynamic floor=%d uV\n", -+ dynamic_floor_volt); -+ } -+ -+ for (i = 0; i < ctrl->thread_count; i++) -+ cpr3_print_result(&ctrl->thread[i]); -+ -+ cpr3_debug(ctrl, "%s: new_volt=%d uV, last_volt=%d uV\n", -+ up ? "UP" : "DN", new_volt, last_volt); -+ -+ if (ctrl->proc_clock_throttle && last_volt == aggr->ceiling_volt -+ && new_volt < last_volt) -+ cpr3_write(ctrl, CPR3_REG_PD_THROTTLE, -+ ctrl->proc_clock_throttle); -+ -+ if (new_volt != last_volt) { -+ rc = cpr3_regulator_scale_vdd_voltage(ctrl, new_volt, -+ last_volt, -+ aggr); -+ if (rc) { -+ cpr3_err(ctrl, "scale_vdd() failed to set vdd=%d uV, rc=%d\n", -+ new_volt, rc); -+ goto done; -+ } -+ cont = CPR3_CONT_CMD_ACK; -+ -+ /* -+ * Update the closed-loop voltage for all regulators managed -+ * by this CPR controller. -+ */ -+ for (i = 0; i < ctrl->thread_count; i++) { -+ for (j = 0; j < ctrl->thread[i].vreg_count; j++) { -+ vreg = &ctrl->thread[i].vreg[j]; -+ cpr3_update_vreg_closed_loop_volt(vreg, -+ new_volt, reg_last_measurement); -+ } -+ } -+ } -+ -+ if (ctrl->proc_clock_throttle && new_volt == aggr->ceiling_volt) -+ cpr3_write(ctrl, CPR3_REG_PD_THROTTLE, -+ CPR3_PD_THROTTLE_DISABLE); -+ -+ corner = &ctrl->thread[0].vreg[0].corner[ -+ ctrl->thread[0].vreg[0].current_corner]; -+ -+ if (irq_en != aggr->irq_en) { -+ aggr->irq_en = irq_en; -+ cpr3_write(ctrl, CPR3_REG_IRQ_EN, irq_en); -+ } -+ -+ aggr->last_volt = new_volt; -+ -+done: -+ /* Clear interrupt status */ -+ cpr3_write(ctrl, CPR3_REG_IRQ_CLEAR, CPR3_IRQ_UP | CPR3_IRQ_DOWN); -+ -+ /* ACK or NACK the CPR controller */ -+ cpr3_write(ctrl, CPR3_REG_CONT_CMD, cont); -+ -+ mutex_unlock(&ctrl->lock); -+ return IRQ_HANDLED; -+} -+ -+/** -+ * cpr3_ceiling_irq_handler() - CPR ceiling reached interrupt handler callback -+ * function used for hardware closed-loop operation -+ * @irq: CPR ceiling interrupt number -+ * @data: Private data corresponding to the CPR3 controller -+ * pointer -+ * -+ * This function disables processor clock throttling and closed-loop operation -+ * when the ceiling voltage is reached. -+ * -+ * Return: IRQ_HANDLED -+ */ -+static irqreturn_t cpr3_ceiling_irq_handler(int irq, void *data) -+{ -+ struct cpr3_controller *ctrl = data; -+ int volt; -+ -+ mutex_lock(&ctrl->lock); -+ -+ if (!ctrl->cpr_enabled) { -+ cpr3_debug(ctrl, "CPR ceiling interrupt received but CPR is disabled\n"); -+ goto done; -+ } else if (!ctrl->use_hw_closed_loop) { -+ cpr3_debug(ctrl, "CPR ceiling interrupt received but CPR is using SW closed-loop\n"); -+ goto done; -+ } -+ -+ volt = regulator_get_voltage(ctrl->vdd_regulator); -+ if (volt < 0) { -+ cpr3_err(ctrl, "could not get vdd voltage, rc=%d\n", volt); -+ goto done; -+ } else if (volt != ctrl->aggr_corner.ceiling_volt) { -+ cpr3_debug(ctrl, "CPR ceiling interrupt received but vdd voltage: %d uV != ceiling voltage: %d uV\n", -+ volt, ctrl->aggr_corner.ceiling_volt); -+ goto done; -+ } -+ -+ if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR3) { -+ /* -+ * Since the ceiling voltage has been reached, disable processor -+ * clock throttling as well as CPR closed-loop operation. -+ */ -+ cpr3_write(ctrl, CPR3_REG_PD_THROTTLE, -+ CPR3_PD_THROTTLE_DISABLE); -+ cpr3_ctrl_loop_disable(ctrl); -+ cpr3_debug(ctrl, "CPR closed-loop and throttling disabled\n"); -+ } -+ -+done: -+ mutex_unlock(&ctrl->lock); -+ return IRQ_HANDLED; -+} -+ -+/** -+ * cpr3_regulator_vreg_register() - register a regulator device for a CPR3 -+ * regulator -+ * @vreg: Pointer to the CPR3 regulator -+ * -+ * This function initializes all regulator framework related structures and then -+ * calls regulator_register() for the CPR3 regulator. -+ * -+ * Return: 0 on success, errno on failure -+ */ -+static int cpr3_regulator_vreg_register(struct cpr3_regulator *vreg) -+{ -+ struct regulator_config config = {}; -+ struct regulator_desc *rdesc; -+ struct regulator_init_data *init_data; -+ int rc; -+ -+ init_data = of_get_regulator_init_data(vreg->thread->ctrl->dev, -+ vreg->of_node, &vreg->rdesc); -+ if (!init_data) { -+ cpr3_err(vreg, "regulator init data is missing\n"); -+ return -EINVAL; -+ } -+ -+ init_data->constraints.input_uV = init_data->constraints.max_uV; -+ rdesc = &vreg->rdesc; -+ init_data->constraints.valid_ops_mask |= -+ REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS; -+ rdesc->ops = &cpr3_regulator_ops; -+ -+ rdesc->n_voltages = vreg->corner_count; -+ rdesc->name = init_data->constraints.name; -+ rdesc->owner = THIS_MODULE; -+ rdesc->type = REGULATOR_VOLTAGE; -+ -+ config.dev = vreg->thread->ctrl->dev; -+ config.driver_data = vreg; -+ config.init_data = init_data; -+ config.of_node = vreg->of_node; -+ -+ vreg->rdev = regulator_register(rdesc, &config); -+ if (IS_ERR(vreg->rdev)) { -+ rc = PTR_ERR(vreg->rdev); -+ cpr3_err(vreg, "regulator_register failed, rc=%d\n", rc); -+ return rc; -+ } -+ -+ return 0; -+} -+ -+static int debugfs_int_set(void *data, u64 val) -+{ -+ *(int *)data = val; -+ return 0; -+} -+ -+static int debugfs_int_get(void *data, u64 *val) -+{ -+ *val = *(int *)data; -+ return 0; -+} -+DEFINE_SIMPLE_ATTRIBUTE(fops_int, debugfs_int_get, debugfs_int_set, "%lld\n"); -+DEFINE_SIMPLE_ATTRIBUTE(fops_int_ro, debugfs_int_get, NULL, "%lld\n"); -+DEFINE_SIMPLE_ATTRIBUTE(fops_int_wo, NULL, debugfs_int_set, "%lld\n"); -+ -+/** -+ * debugfs_create_int - create a debugfs file that is used to read and write a -+ * signed int value -+ * @name: Pointer to a string containing the name of the file to -+ * create -+ * @mode: The permissions that the file should have -+ * @parent: Pointer to the parent dentry for this file. This should -+ * be a directory dentry if set. If this parameter is -+ * %NULL, then the file will be created in the root of the -+ * debugfs filesystem. -+ * @value: Pointer to the variable that the file should read to and -+ * write from -+ * -+ * This function creates a file in debugfs with the given name that -+ * contains the value of the variable @value. If the @mode variable is so -+ * set, it can be read from, and written to. -+ * -+ * This function will return a pointer to a dentry if it succeeds. This -+ * pointer must be passed to the debugfs_remove() function when the file is -+ * to be removed. If an error occurs, %NULL will be returned. -+ */ -+static struct dentry *debugfs_create_int(const char *name, umode_t mode, -+ struct dentry *parent, int *value) -+{ -+ /* if there are no write bits set, make read only */ -+ if (!(mode & S_IWUGO)) -+ return debugfs_create_file(name, mode, parent, value, -+ &fops_int_ro); -+ /* if there are no read bits set, make write only */ -+ if (!(mode & S_IRUGO)) -+ return debugfs_create_file(name, mode, parent, value, -+ &fops_int_wo); -+ -+ return debugfs_create_file(name, mode, parent, value, &fops_int); -+} -+ -+static int debugfs_bool_get(void *data, u64 *val) -+{ -+ *val = *(bool *)data; -+ return 0; -+} -+DEFINE_SIMPLE_ATTRIBUTE(fops_bool_ro, debugfs_bool_get, NULL, "%lld\n"); -+ -+/** -+ * struct cpr3_debug_corner_info - data structure used by the -+ * cpr3_debugfs_create_corner_int function -+ * @vreg: Pointer to the CPR3 regulator -+ * @index: Pointer to the corner array index -+ * @member_offset: Offset in bytes from the beginning of struct cpr3_corner -+ * to the beginning of the value to be read from -+ * @corner: Pointer to the CPR3 corner array -+ */ -+struct cpr3_debug_corner_info { -+ struct cpr3_regulator *vreg; -+ int *index; -+ size_t member_offset; -+ struct cpr3_corner *corner; -+}; -+ -+static int cpr3_debug_corner_int_get(void *data, u64 *val) -+{ -+ struct cpr3_debug_corner_info *info = data; -+ struct cpr3_controller *ctrl = info->vreg->thread->ctrl; -+ int i; -+ -+ mutex_lock(&ctrl->lock); -+ -+ i = *info->index; -+ if (i < 0) -+ i = 0; -+ -+ *val = *(int *)((char *)&info->vreg->corner[i] + info->member_offset); -+ -+ mutex_unlock(&ctrl->lock); -+ -+ return 0; -+} -+DEFINE_SIMPLE_ATTRIBUTE(cpr3_debug_corner_int_fops, cpr3_debug_corner_int_get, -+ NULL, "%lld\n"); -+ -+/** -+ * cpr3_debugfs_create_corner_int - create a debugfs file that is used to read -+ * a signed int value out of a CPR3 regulator's corner array -+ * @vreg: Pointer to the CPR3 regulator -+ * @name: Pointer to a string containing the name of the file to -+ * create -+ * @mode: The permissions that the file should have -+ * @parent: Pointer to the parent dentry for this file. This should -+ * be a directory dentry if set. If this parameter is -+ * %NULL, then the file will be created in the root of the -+ * debugfs filesystem. -+ * @index: Pointer to the corner array index -+ * @member_offset: Offset in bytes from the beginning of struct cpr3_corner -+ * to the beginning of the value to be read from -+ * -+ * This function creates a file in debugfs with the given name that -+ * contains the value of the int type variable vreg->corner[index].member -+ * where member_offset == offsetof(struct cpr3_corner, member). -+ */ -+static struct dentry *cpr3_debugfs_create_corner_int( -+ struct cpr3_regulator *vreg, const char *name, umode_t mode, -+ struct dentry *parent, int *index, size_t member_offset) -+{ -+ struct cpr3_debug_corner_info *info; -+ -+ info = devm_kzalloc(vreg->thread->ctrl->dev, sizeof(*info), GFP_KERNEL); -+ if (!info) -+ return NULL; -+ -+ info->vreg = vreg; -+ info->index = index; -+ info->member_offset = member_offset; -+ -+ return debugfs_create_file(name, mode, parent, info, -+ &cpr3_debug_corner_int_fops); -+} -+ -+static int cpr3_debug_quot_open(struct inode *inode, struct file *file) -+{ -+ struct cpr3_debug_corner_info *info = inode->i_private; -+ struct cpr3_thread *thread = info->vreg->thread; -+ int size, i, pos; -+ u32 *quot; -+ char *buf; -+ -+ /* -+ * Max size: -+ * - 10 digits + ' ' or '\n' = 11 bytes per number -+ * - terminating '\0' -+ */ -+ size = CPR3_RO_COUNT * 11; -+ buf = kzalloc(size + 1, GFP_KERNEL); -+ if (!buf) -+ return -ENOMEM; -+ -+ file->private_data = buf; -+ -+ mutex_lock(&thread->ctrl->lock); -+ -+ quot = info->corner[*info->index].target_quot; -+ -+ for (i = 0, pos = 0; i < CPR3_RO_COUNT; i++) -+ pos += scnprintf(buf + pos, size - pos, "%u%c", -+ quot[i], i < CPR3_RO_COUNT - 1 ? ' ' : '\n'); -+ -+ mutex_unlock(&thread->ctrl->lock); -+ -+ return nonseekable_open(inode, file); -+} -+ -+static ssize_t cpr3_debug_quot_read(struct file *file, char __user *buf, -+ size_t len, loff_t *ppos) -+{ -+ return simple_read_from_buffer(buf, len, ppos, file->private_data, -+ strlen(file->private_data)); -+} -+ -+static int cpr3_debug_quot_release(struct inode *inode, struct file *file) -+{ -+ kfree(file->private_data); -+ -+ return 0; -+} -+ -+static const struct file_operations cpr3_debug_quot_fops = { -+ .owner = THIS_MODULE, -+ .open = cpr3_debug_quot_open, -+ .release = cpr3_debug_quot_release, -+ .read = cpr3_debug_quot_read, -+ .llseek = no_llseek, -+}; -+ -+/** -+ * cpr3_regulator_debugfs_corner_add() - add debugfs files to expose -+ * configuration data for the CPR corner -+ * @vreg: Pointer to the CPR3 regulator -+ * @corner_dir: Pointer to the parent corner dentry for the new files -+ * @index: Pointer to the corner array index -+ * -+ * Return: none -+ */ -+static void cpr3_regulator_debugfs_corner_add(struct cpr3_regulator *vreg, -+ struct dentry *corner_dir, int *index) -+{ -+ struct cpr3_debug_corner_info *info; -+ struct dentry *temp; -+ -+ temp = cpr3_debugfs_create_corner_int(vreg, "floor_volt", S_IRUGO, -+ corner_dir, index, offsetof(struct cpr3_corner, floor_volt)); -+ if (IS_ERR_OR_NULL(temp)) { -+ cpr3_err(vreg, "floor_volt debugfs file creation failed\n"); -+ return; -+ } -+ -+ temp = cpr3_debugfs_create_corner_int(vreg, "ceiling_volt", S_IRUGO, -+ corner_dir, index, offsetof(struct cpr3_corner, ceiling_volt)); -+ if (IS_ERR_OR_NULL(temp)) { -+ cpr3_err(vreg, "ceiling_volt debugfs file creation failed\n"); -+ return; -+ } -+ -+ temp = cpr3_debugfs_create_corner_int(vreg, "open_loop_volt", S_IRUGO, -+ corner_dir, index, -+ offsetof(struct cpr3_corner, open_loop_volt)); -+ if (IS_ERR_OR_NULL(temp)) { -+ cpr3_err(vreg, "open_loop_volt debugfs file creation failed\n"); -+ return; -+ } -+ -+ temp = cpr3_debugfs_create_corner_int(vreg, "last_volt", S_IRUGO, -+ corner_dir, index, offsetof(struct cpr3_corner, last_volt)); -+ if (IS_ERR_OR_NULL(temp)) { -+ cpr3_err(vreg, "last_volt debugfs file creation failed\n"); -+ return; -+ } -+ -+ info = devm_kzalloc(vreg->thread->ctrl->dev, sizeof(*info), GFP_KERNEL); -+ if (!info) -+ return; -+ -+ info->vreg = vreg; -+ info->index = index; -+ info->corner = vreg->corner; -+ -+ temp = debugfs_create_file("target_quots", S_IRUGO, corner_dir, -+ info, &cpr3_debug_quot_fops); -+ if (IS_ERR_OR_NULL(temp)) { -+ cpr3_err(vreg, "target_quots debugfs file creation failed\n"); -+ return; -+ } -+} -+ -+/** -+ * cpr3_debug_corner_index_set() - debugfs callback used to change the -+ * value of the CPR3 regulator debug_corner index -+ * @data: Pointer to private data which is equal to the CPR3 -+ * regulator pointer -+ * @val: New value for debug_corner -+ * -+ * Return: 0 on success, errno on failure -+ */ -+static int cpr3_debug_corner_index_set(void *data, u64 val) -+{ -+ struct cpr3_regulator *vreg = data; -+ -+ if (val < CPR3_CORNER_OFFSET || val > vreg->corner_count) { -+ cpr3_err(vreg, "invalid corner index %llu; allowed values: %d-%d\n", -+ val, CPR3_CORNER_OFFSET, vreg->corner_count); -+ return -EINVAL; -+ } -+ -+ mutex_lock(&vreg->thread->ctrl->lock); -+ vreg->debug_corner = val - CPR3_CORNER_OFFSET; -+ mutex_unlock(&vreg->thread->ctrl->lock); -+ -+ return 0; -+} -+ -+/** -+ * cpr3_debug_corner_index_get() - debugfs callback used to retrieve -+ * the value of the CPR3 regulator debug_corner index -+ * @data: Pointer to private data which is equal to the CPR3 -+ * regulator pointer -+ * @val: Output parameter written with the value of -+ * debug_corner -+ * -+ * Return: 0 on success, errno on failure -+ */ -+static int cpr3_debug_corner_index_get(void *data, u64 *val) -+{ -+ struct cpr3_regulator *vreg = data; -+ -+ *val = vreg->debug_corner + CPR3_CORNER_OFFSET; -+ -+ return 0; -+} -+DEFINE_SIMPLE_ATTRIBUTE(cpr3_debug_corner_index_fops, -+ cpr3_debug_corner_index_get, -+ cpr3_debug_corner_index_set, -+ "%llu\n"); -+ -+/** -+ * cpr3_debug_current_corner_index_get() - debugfs callback used to retrieve -+ * the value of the CPR3 regulator current_corner index -+ * @data: Pointer to private data which is equal to the CPR3 -+ * regulator pointer -+ * @val: Output parameter written with the value of -+ * current_corner -+ * -+ * Return: 0 on success, errno on failure -+ */ -+static int cpr3_debug_current_corner_index_get(void *data, u64 *val) -+{ -+ struct cpr3_regulator *vreg = data; -+ -+ *val = vreg->current_corner + CPR3_CORNER_OFFSET; -+ -+ return 0; -+} -+DEFINE_SIMPLE_ATTRIBUTE(cpr3_debug_current_corner_index_fops, -+ cpr3_debug_current_corner_index_get, -+ NULL, "%llu\n"); -+ -+/** -+ * cpr3_regulator_debugfs_vreg_add() - add debugfs files to expose configuration -+ * data for the CPR3 regulator -+ * @vreg: Pointer to the CPR3 regulator -+ * @thread_dir CPR3 thread debugfs directory handle -+ * -+ * Return: none -+ */ -+static void cpr3_regulator_debugfs_vreg_add(struct cpr3_regulator *vreg, -+ struct dentry *thread_dir) -+{ -+ struct dentry *temp, *corner_dir, *vreg_dir; -+ -+ vreg_dir = debugfs_create_dir(vreg->name, thread_dir); -+ if (IS_ERR_OR_NULL(vreg_dir)) { -+ cpr3_err(vreg, "%s debugfs directory creation failed\n", -+ vreg->name); -+ return; -+ } -+ -+ temp = debugfs_create_int("speed_bin_fuse", S_IRUGO, vreg_dir, -+ &vreg->speed_bin_fuse); -+ if (IS_ERR_OR_NULL(temp)) { -+ cpr3_err(vreg, "speed_bin_fuse debugfs file creation failed\n"); -+ return; -+ } -+ -+ temp = debugfs_create_int("cpr_rev_fuse", S_IRUGO, vreg_dir, -+ &vreg->cpr_rev_fuse); -+ if (IS_ERR_OR_NULL(temp)) { -+ cpr3_err(vreg, "cpr_rev_fuse debugfs file creation failed\n"); -+ return; -+ } -+ -+ temp = debugfs_create_int("fuse_combo", S_IRUGO, vreg_dir, -+ &vreg->fuse_combo); -+ if (IS_ERR_OR_NULL(temp)) { -+ cpr3_err(vreg, "fuse_combo debugfs file creation failed\n"); -+ return; -+ } -+ -+ temp = debugfs_create_int("corner_count", S_IRUGO, vreg_dir, -+ &vreg->corner_count); -+ if (IS_ERR_OR_NULL(temp)) { -+ cpr3_err(vreg, "corner_count debugfs file creation failed\n"); -+ return; -+ } -+ -+ corner_dir = debugfs_create_dir("corner", vreg_dir); -+ if (IS_ERR_OR_NULL(corner_dir)) { -+ cpr3_err(vreg, "corner debugfs directory creation failed\n"); -+ return; -+ } -+ -+ temp = debugfs_create_file("index", S_IRUGO | S_IWUSR, corner_dir, -+ vreg, &cpr3_debug_corner_index_fops); -+ if (IS_ERR_OR_NULL(temp)) { -+ cpr3_err(vreg, "index debugfs file creation failed\n"); -+ return; -+ } -+ -+ cpr3_regulator_debugfs_corner_add(vreg, corner_dir, -+ &vreg->debug_corner); -+ -+ corner_dir = debugfs_create_dir("current_corner", vreg_dir); -+ if (IS_ERR_OR_NULL(corner_dir)) { -+ cpr3_err(vreg, "current_corner debugfs directory creation failed\n"); -+ return; -+ } -+ -+ temp = debugfs_create_file("index", S_IRUGO, corner_dir, -+ vreg, &cpr3_debug_current_corner_index_fops); -+ if (IS_ERR_OR_NULL(temp)) { -+ cpr3_err(vreg, "index debugfs file creation failed\n"); -+ return; -+ } -+ -+ cpr3_regulator_debugfs_corner_add(vreg, corner_dir, -+ &vreg->current_corner); -+} -+ -+/** -+ * cpr3_regulator_debugfs_thread_add() - add debugfs files to expose -+ * configuration data for the CPR thread -+ * @thread: Pointer to the CPR3 thread -+ * -+ * Return: none -+ */ -+static void cpr3_regulator_debugfs_thread_add(struct cpr3_thread *thread) -+{ -+ struct cpr3_controller *ctrl = thread->ctrl; -+ struct dentry *aggr_dir, *temp, *thread_dir; -+ struct cpr3_debug_corner_info *info; -+ char buf[20]; -+ int *index; -+ int i; -+ -+ scnprintf(buf, sizeof(buf), "thread%u", thread->thread_id); -+ thread_dir = debugfs_create_dir(buf, thread->ctrl->debugfs); -+ if (IS_ERR_OR_NULL(thread_dir)) { -+ cpr3_err(ctrl, "thread %u %s debugfs directory creation failed\n", -+ thread->thread_id, buf); -+ return; -+ } -+ -+ aggr_dir = debugfs_create_dir("max_aggregated_params", thread_dir); -+ if (IS_ERR_OR_NULL(aggr_dir)) { -+ cpr3_err(ctrl, "thread %u max_aggregated_params debugfs directory creation failed\n", -+ thread->thread_id); -+ return; -+ } -+ -+ temp = debugfs_create_int("floor_volt", S_IRUGO, aggr_dir, -+ &thread->aggr_corner.floor_volt); -+ if (IS_ERR_OR_NULL(temp)) { -+ cpr3_err(ctrl, "thread %u aggr floor_volt debugfs file creation failed\n", -+ thread->thread_id); -+ return; -+ } -+ -+ temp = debugfs_create_int("ceiling_volt", S_IRUGO, aggr_dir, -+ &thread->aggr_corner.ceiling_volt); -+ if (IS_ERR_OR_NULL(temp)) { -+ cpr3_err(ctrl, "thread %u aggr ceiling_volt debugfs file creation failed\n", -+ thread->thread_id); -+ return; -+ } -+ -+ temp = debugfs_create_int("open_loop_volt", S_IRUGO, aggr_dir, -+ &thread->aggr_corner.open_loop_volt); -+ if (IS_ERR_OR_NULL(temp)) { -+ cpr3_err(ctrl, "thread %u aggr open_loop_volt debugfs file creation failed\n", -+ thread->thread_id); -+ return; -+ } -+ -+ temp = debugfs_create_int("last_volt", S_IRUGO, aggr_dir, -+ &thread->aggr_corner.last_volt); -+ if (IS_ERR_OR_NULL(temp)) { -+ cpr3_err(ctrl, "thread %u aggr last_volt debugfs file creation failed\n", -+ thread->thread_id); -+ return; -+ } -+ -+ info = devm_kzalloc(thread->ctrl->dev, sizeof(*info), GFP_KERNEL); -+ index = devm_kzalloc(thread->ctrl->dev, sizeof(*index), GFP_KERNEL); -+ if (!info || !index) -+ return; -+ *index = 0; -+ info->vreg = &thread->vreg[0]; -+ info->index = index; -+ info->corner = &thread->aggr_corner; -+ -+ temp = debugfs_create_file("target_quots", S_IRUGO, aggr_dir, -+ info, &cpr3_debug_quot_fops); -+ if (IS_ERR_OR_NULL(temp)) { -+ cpr3_err(ctrl, "thread %u target_quots debugfs file creation failed\n", -+ thread->thread_id); -+ return; -+ } -+ -+ for (i = 0; i < thread->vreg_count; i++) -+ cpr3_regulator_debugfs_vreg_add(&thread->vreg[i], thread_dir); -+} -+ -+/** -+ * cpr3_debug_closed_loop_enable_set() - debugfs callback used to change the -+ * value of the CPR controller cpr_allowed_sw flag which enables or -+ * disables closed-loop operation -+ * @data: Pointer to private data which is equal to the CPR -+ * controller pointer -+ * @val: New value for cpr_allowed_sw -+ * -+ * Return: 0 on success, errno on failure -+ */ -+static int cpr3_debug_closed_loop_enable_set(void *data, u64 val) -+{ -+ struct cpr3_controller *ctrl = data; -+ bool enable = !!val; -+ int rc; -+ -+ mutex_lock(&ctrl->lock); -+ -+ if (ctrl->cpr_allowed_sw == enable) -+ goto done; -+ -+ if (enable && !ctrl->cpr_allowed_hw) { -+ cpr3_err(ctrl, "CPR closed-loop operation is not allowed\n"); -+ goto done; -+ } -+ -+ ctrl->cpr_allowed_sw = enable; -+ -+ rc = cpr3_regulator_update_ctrl_state(ctrl); -+ if (rc) { -+ cpr3_err(ctrl, "could not change CPR enable state=%u, rc=%d\n", -+ enable, rc); -+ goto done; -+ } -+ -+ if (ctrl->proc_clock_throttle && !ctrl->cpr_enabled) { -+ rc = cpr3_clock_enable(ctrl); -+ if (rc) { -+ cpr3_err(ctrl, "clock enable failed, rc=%d\n", -+ rc); -+ goto done; -+ } -+ ctrl->cpr_enabled = true; -+ -+ cpr3_write(ctrl, CPR3_REG_PD_THROTTLE, -+ CPR3_PD_THROTTLE_DISABLE); -+ -+ cpr3_clock_disable(ctrl); -+ ctrl->cpr_enabled = false; -+ } -+ -+ cpr3_debug(ctrl, "closed-loop=%s\n", enable ? "enabled" : "disabled"); -+done: -+ mutex_unlock(&ctrl->lock); -+ return 0; -+} -+ -+/** -+ * cpr3_debug_closed_loop_enable_get() - debugfs callback used to retrieve -+ * the value of the CPR controller cpr_allowed_sw flag which -+ * indicates if closed-loop operation is enabled -+ * @data: Pointer to private data which is equal to the CPR -+ * controller pointer -+ * @val: Output parameter written with the value of -+ * cpr_allowed_sw -+ * -+ * Return: 0 on success, errno on failure -+ */ -+static int cpr3_debug_closed_loop_enable_get(void *data, u64 *val) -+{ -+ struct cpr3_controller *ctrl = data; -+ -+ *val = ctrl->cpr_allowed_sw; -+ -+ return 0; -+} -+DEFINE_SIMPLE_ATTRIBUTE(cpr3_debug_closed_loop_enable_fops, -+ cpr3_debug_closed_loop_enable_get, -+ cpr3_debug_closed_loop_enable_set, -+ "%llu\n"); -+ -+/** -+ * cpr3_debug_hw_closed_loop_enable_set() - debugfs callback used to change the -+ * value of the CPR controller use_hw_closed_loop flag which -+ * switches between software closed-loop and hardware closed-loop -+ * operation for CPR3 and CPR4 controllers and between open-loop -+ * and full hardware closed-loop operation for CPRh controllers. -+ * @data: Pointer to private data which is equal to the CPR -+ * controller pointer -+ * @val: New value for use_hw_closed_loop -+ * -+ * Return: 0 on success, errno on failure -+ */ -+static int cpr3_debug_hw_closed_loop_enable_set(void *data, u64 val) -+{ -+ struct cpr3_controller *ctrl = data; -+ bool use_hw_closed_loop = !!val; -+ struct cpr3_regulator *vreg; -+ bool cpr_enabled; -+ int i, j, k, rc; -+ -+ mutex_lock(&ctrl->lock); -+ -+ if (ctrl->use_hw_closed_loop == use_hw_closed_loop) -+ goto done; -+ -+ if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4) { -+ rc = cpr3_ctrl_clear_cpr4_config(ctrl); -+ if (rc) { -+ cpr3_err(ctrl, "failed to clear CPR4 configuration,rc=%d\n", -+ rc); -+ goto done; -+ } -+ } -+ -+ cpr3_ctrl_loop_disable(ctrl); -+ -+ ctrl->use_hw_closed_loop = use_hw_closed_loop; -+ -+ cpr_enabled = ctrl->cpr_enabled; -+ -+ /* Ensure that CPR clocks are enabled before writing to registers. */ -+ if (!cpr_enabled) { -+ rc = cpr3_clock_enable(ctrl); -+ if (rc) { -+ cpr3_err(ctrl, "clock enable failed, rc=%d\n", rc); -+ goto done; -+ } -+ ctrl->cpr_enabled = true; -+ } -+ -+ if (ctrl->use_hw_closed_loop) -+ cpr3_write(ctrl, CPR3_REG_IRQ_EN, 0); -+ -+ if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4) { -+ cpr3_masked_write(ctrl, CPR4_REG_MARGIN_ADJ_CTL, -+ CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_EN_MASK, -+ ctrl->use_hw_closed_loop -+ ? CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_ENABLE -+ : CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_DISABLE); -+ } else if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR3) { -+ cpr3_write(ctrl, CPR3_REG_HW_CLOSED_LOOP, -+ ctrl->use_hw_closed_loop -+ ? CPR3_HW_CLOSED_LOOP_ENABLE -+ : CPR3_HW_CLOSED_LOOP_DISABLE); -+ } -+ -+ /* Turn off CPR clocks if they were off before this function call. */ -+ if (!cpr_enabled) { -+ cpr3_clock_disable(ctrl); -+ ctrl->cpr_enabled = false; -+ } -+ -+ if (ctrl->use_hw_closed_loop && ctrl->ctrl_type == CPR_CTRL_TYPE_CPR3) { -+ rc = regulator_enable(ctrl->vdd_limit_regulator); -+ if (rc) { -+ cpr3_err(ctrl, "CPR limit regulator enable failed, rc=%d\n", -+ rc); -+ goto done; -+ } -+ } else if (!ctrl->use_hw_closed_loop -+ && ctrl->ctrl_type == CPR_CTRL_TYPE_CPR3) { -+ rc = regulator_disable(ctrl->vdd_limit_regulator); -+ if (rc) { -+ cpr3_err(ctrl, "CPR limit regulator disable failed, rc=%d\n", -+ rc); -+ goto done; -+ } -+ } -+ -+ /* -+ * Due to APM and mem-acc floor restriction constraints, -+ * the closed-loop voltage may be different when using -+ * software closed-loop vs hardware closed-loop. Therefore, -+ * reset the cached closed-loop voltage for all corners to the -+ * corresponding open-loop voltage when switching between -+ * SW and HW closed-loop mode. -+ */ -+ for (i = 0; i < ctrl->thread_count; i++) { -+ for (j = 0; j < ctrl->thread[i].vreg_count; j++) { -+ vreg = &ctrl->thread[i].vreg[j]; -+ for (k = 0; k < vreg->corner_count; k++) -+ vreg->corner[k].last_volt -+ = vreg->corner[k].open_loop_volt; -+ } -+ } -+ -+ /* Skip last_volt caching */ -+ ctrl->last_corner_was_closed_loop = false; -+ -+ rc = cpr3_regulator_update_ctrl_state(ctrl); -+ if (rc) { -+ cpr3_err(ctrl, "could not change CPR HW closed-loop enable state=%u, rc=%d\n", -+ use_hw_closed_loop, rc); -+ goto done; -+ } -+ -+ cpr3_debug(ctrl, "CPR mode=%s\n", -+ use_hw_closed_loop ? -+ "HW closed-loop" : "SW closed-loop"); -+done: -+ mutex_unlock(&ctrl->lock); -+ return 0; -+} -+ -+/** -+ * cpr3_debug_hw_closed_loop_enable_get() - debugfs callback used to retrieve -+ * the value of the CPR controller use_hw_closed_loop flag which -+ * indicates if hardware closed-loop operation is being used in -+ * place of software closed-loop operation -+ * @data: Pointer to private data which is equal to the CPR -+ * controller pointer -+ * @val: Output parameter written with the value of -+ * use_hw_closed_loop -+ * -+ * Return: 0 on success, errno on failure -+ */ -+static int cpr3_debug_hw_closed_loop_enable_get(void *data, u64 *val) -+{ -+ struct cpr3_controller *ctrl = data; -+ -+ *val = ctrl->use_hw_closed_loop; -+ -+ return 0; -+} -+DEFINE_SIMPLE_ATTRIBUTE(cpr3_debug_hw_closed_loop_enable_fops, -+ cpr3_debug_hw_closed_loop_enable_get, -+ cpr3_debug_hw_closed_loop_enable_set, -+ "%llu\n"); -+ -+/** -+ * cpr3_debug_trigger_aging_measurement_set() - debugfs callback used to trigger -+ * another CPR measurement -+ * @data: Pointer to private data which is equal to the CPR -+ * controller pointer -+ * @val: Unused -+ * -+ * Return: 0 on success, errno on failure -+ */ -+static int cpr3_debug_trigger_aging_measurement_set(void *data, u64 val) -+{ -+ struct cpr3_controller *ctrl = data; -+ int rc; -+ -+ mutex_lock(&ctrl->lock); -+ -+ if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4) { -+ rc = cpr3_ctrl_clear_cpr4_config(ctrl); -+ if (rc) { -+ cpr3_err(ctrl, "failed to clear CPR4 configuration,rc=%d\n", -+ rc); -+ goto done; -+ } -+ } -+ -+ cpr3_ctrl_loop_disable(ctrl); -+ -+ cpr3_regulator_set_aging_ref_adjustment(ctrl, INT_MAX); -+ ctrl->aging_required = true; -+ ctrl->aging_succeeded = false; -+ ctrl->aging_failed = false; -+ -+ rc = cpr3_regulator_update_ctrl_state(ctrl); -+ if (rc) { -+ cpr3_err(ctrl, "could not update the CPR controller state, rc=%d\n", -+ rc); -+ goto done; -+ } -+ -+done: -+ mutex_unlock(&ctrl->lock); -+ return 0; -+} -+DEFINE_SIMPLE_ATTRIBUTE(cpr3_debug_trigger_aging_measurement_fops, -+ NULL, -+ cpr3_debug_trigger_aging_measurement_set, -+ "%llu\n"); -+ -+/** -+ * cpr3_regulator_debugfs_ctrl_add() - add debugfs files to expose configuration -+ * data for the CPR controller -+ * @ctrl: Pointer to the CPR3 controller -+ * -+ * Return: none -+ */ -+static void cpr3_regulator_debugfs_ctrl_add(struct cpr3_controller *ctrl) -+{ -+ struct dentry *temp, *aggr_dir; -+ int i; -+ -+ /* Add cpr3-regulator base directory if it isn't present already. */ -+ if (cpr3_debugfs_base == NULL) { -+ cpr3_debugfs_base = debugfs_create_dir("cpr3-regulator", NULL); -+ if (IS_ERR_OR_NULL(cpr3_debugfs_base)) { -+ cpr3_err(ctrl, "cpr3-regulator debugfs base directory creation failed\n"); -+ cpr3_debugfs_base = NULL; -+ return; -+ } -+ } -+ -+ ctrl->debugfs = debugfs_create_dir(ctrl->name, cpr3_debugfs_base); -+ if (IS_ERR_OR_NULL(ctrl->debugfs)) { -+ cpr3_err(ctrl, "cpr3-regulator controller debugfs directory creation failed\n"); -+ return; -+ } -+ -+ temp = debugfs_create_file("cpr_closed_loop_enable", S_IRUGO | S_IWUSR, -+ ctrl->debugfs, ctrl, -+ &cpr3_debug_closed_loop_enable_fops); -+ if (IS_ERR_OR_NULL(temp)) { -+ cpr3_err(ctrl, "cpr_closed_loop_enable debugfs file creation failed\n"); -+ return; -+ } -+ -+ if (ctrl->supports_hw_closed_loop) { -+ temp = debugfs_create_file("use_hw_closed_loop", -+ S_IRUGO | S_IWUSR, ctrl->debugfs, ctrl, -+ &cpr3_debug_hw_closed_loop_enable_fops); -+ if (IS_ERR_OR_NULL(temp)) { -+ cpr3_err(ctrl, "use_hw_closed_loop debugfs file creation failed\n"); -+ return; -+ } -+ } -+ -+ temp = debugfs_create_int("thread_count", S_IRUGO, ctrl->debugfs, -+ &ctrl->thread_count); -+ if (IS_ERR_OR_NULL(temp)) { -+ cpr3_err(ctrl, "thread_count debugfs file creation failed\n"); -+ return; -+ } -+ -+ if (ctrl->apm) { -+ temp = debugfs_create_int("apm_threshold_volt", S_IRUGO, -+ ctrl->debugfs, &ctrl->apm_threshold_volt); -+ if (IS_ERR_OR_NULL(temp)) { -+ cpr3_err(ctrl, "apm_threshold_volt debugfs file creation failed\n"); -+ return; -+ } -+ } -+ -+ if (ctrl->aging_required || ctrl->aging_succeeded -+ || ctrl->aging_failed) { -+ temp = debugfs_create_int("aging_adj_volt", S_IRUGO, -+ ctrl->debugfs, &ctrl->aging_ref_adjust_volt); -+ if (IS_ERR_OR_NULL(temp)) { -+ cpr3_err(ctrl, "aging_adj_volt debugfs file creation failed\n"); -+ return; -+ } -+ -+ temp = debugfs_create_file("aging_succeeded", S_IRUGO, -+ ctrl->debugfs, &ctrl->aging_succeeded, &fops_bool_ro); -+ if (IS_ERR_OR_NULL(temp)) { -+ cpr3_err(ctrl, "aging_succeeded debugfs file creation failed\n"); -+ return; -+ } -+ -+ temp = debugfs_create_file("aging_failed", S_IRUGO, -+ ctrl->debugfs, &ctrl->aging_failed, &fops_bool_ro); -+ if (IS_ERR_OR_NULL(temp)) { -+ cpr3_err(ctrl, "aging_failed debugfs file creation failed\n"); -+ return; -+ } -+ -+ temp = debugfs_create_file("aging_trigger", S_IWUSR, -+ ctrl->debugfs, ctrl, -+ &cpr3_debug_trigger_aging_measurement_fops); -+ if (IS_ERR_OR_NULL(temp)) { -+ cpr3_err(ctrl, "aging_trigger debugfs file creation failed\n"); -+ return; -+ } -+ } -+ -+ aggr_dir = debugfs_create_dir("max_aggregated_voltages", ctrl->debugfs); -+ if (IS_ERR_OR_NULL(aggr_dir)) { -+ cpr3_err(ctrl, "max_aggregated_voltages debugfs directory creation failed\n"); -+ return; -+ } -+ -+ temp = debugfs_create_int("floor_volt", S_IRUGO, aggr_dir, -+ &ctrl->aggr_corner.floor_volt); -+ if (IS_ERR_OR_NULL(temp)) { -+ cpr3_err(ctrl, "aggr floor_volt debugfs file creation failed\n"); -+ return; -+ } -+ -+ temp = debugfs_create_int("ceiling_volt", S_IRUGO, aggr_dir, -+ &ctrl->aggr_corner.ceiling_volt); -+ if (IS_ERR_OR_NULL(temp)) { -+ cpr3_err(ctrl, "aggr ceiling_volt debugfs file creation failed\n"); -+ return; -+ } -+ -+ temp = debugfs_create_int("open_loop_volt", S_IRUGO, aggr_dir, -+ &ctrl->aggr_corner.open_loop_volt); -+ if (IS_ERR_OR_NULL(temp)) { -+ cpr3_err(ctrl, "aggr open_loop_volt debugfs file creation failed\n"); -+ return; -+ } -+ -+ temp = debugfs_create_int("last_volt", S_IRUGO, aggr_dir, -+ &ctrl->aggr_corner.last_volt); -+ if (IS_ERR_OR_NULL(temp)) { -+ cpr3_err(ctrl, "aggr last_volt debugfs file creation failed\n"); -+ return; -+ } -+ -+ for (i = 0; i < ctrl->thread_count; i++) -+ cpr3_regulator_debugfs_thread_add(&ctrl->thread[i]); -+} -+ -+/** -+ * cpr3_regulator_debugfs_ctrl_remove() - remove debugfs files for the CPR -+ * controller -+ * @ctrl: Pointer to the CPR3 controller -+ * -+ * Note, this function must be called after the controller has been removed from -+ * cpr3_controller_list and while the cpr3_controller_list_mutex lock is held. -+ * -+ * Return: none -+ */ -+static void cpr3_regulator_debugfs_ctrl_remove(struct cpr3_controller *ctrl) -+{ -+ if (list_empty(&cpr3_controller_list)) { -+ debugfs_remove_recursive(cpr3_debugfs_base); -+ cpr3_debugfs_base = NULL; -+ } else { -+ debugfs_remove_recursive(ctrl->debugfs); -+ } -+} -+ -+/** -+ * cpr3_regulator_init_ctrl_data() - performs initialization of CPR controller -+ * elements -+ * @ctrl: Pointer to the CPR3 controller -+ * -+ * Return: 0 on success, errno on failure -+ */ -+static int cpr3_regulator_init_ctrl_data(struct cpr3_controller *ctrl) -+{ -+ /* Read the initial vdd voltage from hardware. */ -+ ctrl->aggr_corner.last_volt -+ = regulator_get_voltage(ctrl->vdd_regulator); -+ if (ctrl->aggr_corner.last_volt < 0) { -+ cpr3_err(ctrl, "regulator_get_voltage(vdd) failed, rc=%d\n", -+ ctrl->aggr_corner.last_volt); -+ return ctrl->aggr_corner.last_volt; -+ } -+ ctrl->aggr_corner.open_loop_volt = ctrl->aggr_corner.last_volt; -+ -+ return 0; -+} -+ -+/** -+ * cpr3_regulator_init_vreg_data() - performs initialization of common CPR3 -+ * regulator elements and validate aging configurations -+ * @vreg: Pointer to the CPR3 regulator -+ * -+ * Return: 0 on success, errno on failure -+ */ -+static int cpr3_regulator_init_vreg_data(struct cpr3_regulator *vreg) -+{ -+ int i, j; -+ bool init_aging; -+ -+ vreg->current_corner = CPR3_REGULATOR_CORNER_INVALID; -+ vreg->last_closed_loop_corner = CPR3_REGULATOR_CORNER_INVALID; -+ -+ init_aging = vreg->aging_allowed && vreg->thread->ctrl->aging_required; -+ -+ for (i = 0; i < vreg->corner_count; i++) { -+ vreg->corner[i].last_volt = vreg->corner[i].open_loop_volt; -+ vreg->corner[i].irq_en = CPR3_IRQ_UP | CPR3_IRQ_DOWN; -+ -+ vreg->corner[i].ro_mask = 0; -+ for (j = 0; j < CPR3_RO_COUNT; j++) { -+ if (vreg->corner[i].target_quot[j] == 0) -+ vreg->corner[i].ro_mask |= BIT(j); -+ } -+ -+ if (init_aging) { -+ vreg->corner[i].unaged_floor_volt -+ = vreg->corner[i].floor_volt; -+ vreg->corner[i].unaged_ceiling_volt -+ = vreg->corner[i].ceiling_volt; -+ vreg->corner[i].unaged_open_loop_volt -+ = vreg->corner[i].open_loop_volt; -+ } -+ -+ if (vreg->aging_allowed) { -+ if (vreg->corner[i].unaged_floor_volt <= 0) { -+ cpr3_err(vreg, "invalid unaged_floor_volt[%d] = %d\n", -+ i, vreg->corner[i].unaged_floor_volt); -+ return -EINVAL; -+ } -+ if (vreg->corner[i].unaged_ceiling_volt <= 0) { -+ cpr3_err(vreg, "invalid unaged_ceiling_volt[%d] = %d\n", -+ i, vreg->corner[i].unaged_ceiling_volt); -+ return -EINVAL; -+ } -+ if (vreg->corner[i].unaged_open_loop_volt <= 0) { -+ cpr3_err(vreg, "invalid unaged_open_loop_volt[%d] = %d\n", -+ i, vreg->corner[i].unaged_open_loop_volt); -+ return -EINVAL; -+ } -+ } -+ } -+ -+ if (vreg->aging_allowed && vreg->corner[vreg->aging_corner].ceiling_volt -+ > vreg->thread->ctrl->aging_ref_volt) { -+ cpr3_err(vreg, "aging corner %d ceiling voltage = %d > aging ref voltage = %d uV\n", -+ vreg->aging_corner, -+ vreg->corner[vreg->aging_corner].ceiling_volt, -+ vreg->thread->ctrl->aging_ref_volt); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+/** -+ * cpr3_regulator_suspend() - perform common required CPR3 power down steps -+ * before the system enters suspend -+ * @ctrl: Pointer to the CPR3 controller -+ * -+ * Return: 0 on success, errno on failure -+ */ -+int cpr3_regulator_suspend(struct cpr3_controller *ctrl) -+{ -+ int rc; -+ -+ mutex_lock(&ctrl->lock); -+ -+ if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4) { -+ rc = cpr3_ctrl_clear_cpr4_config(ctrl); -+ if (rc) { -+ cpr3_err(ctrl, "failed to clear CPR4 configuration,rc=%d\n", -+ rc); -+ mutex_unlock(&ctrl->lock); -+ return rc; -+ } -+ } -+ -+ cpr3_ctrl_loop_disable(ctrl); -+ -+ rc = cpr3_closed_loop_disable(ctrl); -+ if (rc) -+ cpr3_err(ctrl, "could not disable CPR, rc=%d\n", rc); -+ -+ ctrl->cpr_suspended = true; -+ -+ mutex_unlock(&ctrl->lock); -+ return 0; -+} -+ -+/** -+ * cpr3_regulator_resume() - perform common required CPR3 power up steps after -+ * the system resumes from suspend -+ * @ctrl: Pointer to the CPR3 controller -+ * -+ * Return: 0 on success, errno on failure -+ */ -+int cpr3_regulator_resume(struct cpr3_controller *ctrl) -+{ -+ int rc; -+ -+ mutex_lock(&ctrl->lock); -+ -+ ctrl->cpr_suspended = false; -+ rc = cpr3_regulator_update_ctrl_state(ctrl); -+ if (rc) -+ cpr3_err(ctrl, "could not enable CPR, rc=%d\n", rc); -+ -+ mutex_unlock(&ctrl->lock); -+ return 0; -+} -+ -+/** -+ * cpr3_regulator_validate_controller() - verify the data passed in via the -+ * cpr3_controller data structure -+ * @ctrl: Pointer to the CPR3 controller -+ * -+ * Return: 0 on success, errno on failure -+ */ -+static int cpr3_regulator_validate_controller(struct cpr3_controller *ctrl) -+{ -+ struct cpr3_thread *thread; -+ struct cpr3_regulator *vreg; -+ int i, j, allow_boost_vreg_count = 0; -+ -+ if (!ctrl->vdd_regulator) { -+ cpr3_err(ctrl, "vdd regulator missing\n"); -+ return -EINVAL; -+ } else if (ctrl->sensor_count <= 0 -+ || ctrl->sensor_count > CPR3_MAX_SENSOR_COUNT) { -+ cpr3_err(ctrl, "invalid CPR sensor count=%d\n", -+ ctrl->sensor_count); -+ return -EINVAL; -+ } else if (!ctrl->sensor_owner) { -+ cpr3_err(ctrl, "CPR sensor ownership table missing\n"); -+ return -EINVAL; -+ } -+ -+ if (ctrl->aging_required) { -+ for (i = 0; i < ctrl->aging_sensor_count; i++) { -+ if (ctrl->aging_sensor[i].sensor_id -+ >= ctrl->sensor_count) { -+ cpr3_err(ctrl, "aging_sensor[%d] id=%u is not in the value range 0-%d", -+ i, ctrl->aging_sensor[i].sensor_id, -+ ctrl->sensor_count - 1); -+ return -EINVAL; -+ } -+ } -+ } -+ -+ for (i = 0; i < ctrl->thread_count; i++) { -+ thread = &ctrl->thread[i]; -+ for (j = 0; j < thread->vreg_count; j++) { -+ vreg = &thread->vreg[j]; -+ if (vreg->allow_boost) -+ allow_boost_vreg_count++; -+ } -+ } -+ -+ if (allow_boost_vreg_count > 1) { -+ /* -+ * Boost feature is not allowed to be used for more -+ * than one CPR3 regulator of a CPR3 controller. -+ */ -+ cpr3_err(ctrl, "Boost feature is enabled for more than one regulator\n"); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+/** -+ * cpr3_panic_callback() - panic notification callback function. This function -+ * is invoked when a kernel panic occurs. -+ * @nfb: Notifier block pointer of CPR3 controller -+ * @event: Value passed unmodified to notifier function -+ * @data: Pointer passed unmodified to notifier function -+ * -+ * Return: NOTIFY_OK -+ */ -+static int cpr3_panic_callback(struct notifier_block *nfb, -+ unsigned long event, void *data) -+{ -+ struct cpr3_controller *ctrl = container_of(nfb, -+ struct cpr3_controller, panic_notifier); -+ struct cpr3_panic_regs_info *regs_info = ctrl->panic_regs_info; -+ struct cpr3_reg_info *reg; -+ int i = 0; -+ -+ for (i = 0; i < regs_info->reg_count; i++) { -+ reg = &(regs_info->regs[i]); -+ reg->value = readl_relaxed(reg->virt_addr); -+ pr_err("%s[0x%08x] = 0x%08x\n", reg->name, reg->addr, -+ reg->value); -+ } -+ /* -+ * Barrier to ensure that the information has been updated in the -+ * structure. -+ */ -+ mb(); -+ -+ return NOTIFY_OK; -+} -+ -+/** -+ * cpr3_regulator_register() - register the regulators for a CPR3 controller and -+ * perform CPR hardware initialization -+ * @pdev: Platform device pointer for the CPR3 controller -+ * @ctrl: Pointer to the CPR3 controller -+ * -+ * Return: 0 on success, errno on failure -+ */ -+int cpr3_regulator_register(struct platform_device *pdev, -+ struct cpr3_controller *ctrl) -+{ -+ struct device *dev = &pdev->dev; -+ struct resource *res; -+ int i, j, rc; -+ -+ if (!dev->of_node) { -+ dev_err(dev, "%s: Device tree node is missing\n", __func__); -+ return -EINVAL; -+ } -+ -+ if (!ctrl || !ctrl->name) { -+ dev_err(dev, "%s: CPR controller data is missing\n", __func__); -+ return -EINVAL; -+ } -+ -+ rc = cpr3_regulator_validate_controller(ctrl); -+ if (rc) { -+ cpr3_err(ctrl, "controller validation failed, rc=%d\n", rc); -+ return rc; -+ } -+ -+ mutex_init(&ctrl->lock); -+ -+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cpr_ctrl"); -+ if (!res || !res->start) { -+ cpr3_err(ctrl, "CPR controller address is missing\n"); -+ return -ENXIO; -+ } -+ ctrl->cpr_ctrl_base = devm_ioremap(dev, res->start, resource_size(res)); -+ -+ if (ctrl->aging_possible_mask) { -+ /* -+ * Aging possible register address is required if an aging -+ * possible mask has been specified. -+ */ -+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, -+ "aging_allowed"); -+ if (!res || !res->start) { -+ cpr3_err(ctrl, "CPR aging allowed address is missing\n"); -+ return -ENXIO; -+ } -+ ctrl->aging_possible_reg = devm_ioremap(dev, res->start, -+ resource_size(res)); -+ } -+ -+ ctrl->irq = platform_get_irq_byname(pdev, "cpr"); -+ if (ctrl->irq < 0) { -+ cpr3_err(ctrl, "missing CPR interrupt\n"); -+ return ctrl->irq; -+ } -+ -+ if (ctrl->supports_hw_closed_loop) { -+ if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR3) { -+ ctrl->ceiling_irq = platform_get_irq_byname(pdev, -+ "ceiling"); -+ if (ctrl->ceiling_irq < 0) { -+ cpr3_err(ctrl, "missing ceiling interrupt\n"); -+ return ctrl->ceiling_irq; -+ } -+ } -+ } -+ -+ rc = cpr3_regulator_init_ctrl_data(ctrl); -+ if (rc) { -+ cpr3_err(ctrl, "CPR controller data initialization failed, rc=%d\n", -+ rc); -+ return rc; -+ } -+ -+ for (i = 0; i < ctrl->thread_count; i++) { -+ for (j = 0; j < ctrl->thread[i].vreg_count; j++) { -+ rc = cpr3_regulator_init_vreg_data( -+ &ctrl->thread[i].vreg[j]); -+ if (rc) -+ return rc; -+ cpr3_print_quots(&ctrl->thread[i].vreg[j]); -+ } -+ } -+ -+ /* -+ * Add the maximum possible aging voltage margin until it is possible -+ * to perform an aging measurement. -+ */ -+ if (ctrl->aging_required) -+ cpr3_regulator_set_aging_ref_adjustment(ctrl, INT_MAX); -+ -+ rc = cpr3_regulator_init_ctrl(ctrl); -+ if (rc) { -+ cpr3_err(ctrl, "CPR controller initialization failed, rc=%d\n", -+ rc); -+ return rc; -+ } -+ -+ /* Register regulator devices for all threads. */ -+ for (i = 0; i < ctrl->thread_count; i++) { -+ for (j = 0; j < ctrl->thread[i].vreg_count; j++) { -+ rc = cpr3_regulator_vreg_register( -+ &ctrl->thread[i].vreg[j]); -+ if (rc) { -+ cpr3_err(&ctrl->thread[i].vreg[j], "failed to register regulator, rc=%d\n", -+ rc); -+ goto free_regulators; -+ } -+ } -+ } -+ -+ rc = devm_request_threaded_irq(dev, ctrl->irq, NULL, -+ cpr3_irq_handler, -+ IRQF_ONESHOT | -+ IRQF_TRIGGER_RISING, -+ "cpr3", ctrl); -+ if (rc) { -+ cpr3_err(ctrl, "could not request IRQ %d, rc=%d\n", -+ ctrl->irq, rc); -+ goto free_regulators; -+ } -+ -+ if (ctrl->supports_hw_closed_loop && -+ ctrl->ctrl_type == CPR_CTRL_TYPE_CPR3) { -+ rc = devm_request_threaded_irq(dev, ctrl->ceiling_irq, NULL, -+ cpr3_ceiling_irq_handler, -+ IRQF_ONESHOT | IRQF_TRIGGER_RISING, -+ "cpr3_ceiling", ctrl); -+ if (rc) { -+ cpr3_err(ctrl, "could not request ceiling IRQ %d, rc=%d\n", -+ ctrl->ceiling_irq, rc); -+ goto free_regulators; -+ } -+ } -+ -+ mutex_lock(&cpr3_controller_list_mutex); -+ cpr3_regulator_debugfs_ctrl_add(ctrl); -+ list_add(&ctrl->list, &cpr3_controller_list); -+ mutex_unlock(&cpr3_controller_list_mutex); -+ -+ if (ctrl->panic_regs_info) { -+ /* Register panic notification call back */ -+ ctrl->panic_notifier.notifier_call = cpr3_panic_callback; -+ atomic_notifier_chain_register(&panic_notifier_list, -+ &ctrl->panic_notifier); -+ } -+ -+ return 0; -+ -+free_regulators: -+ for (i = 0; i < ctrl->thread_count; i++) -+ for (j = 0; j < ctrl->thread[i].vreg_count; j++) -+ if (!IS_ERR_OR_NULL(ctrl->thread[i].vreg[j].rdev)) -+ regulator_unregister( -+ ctrl->thread[i].vreg[j].rdev); -+ return rc; -+} -+ -+/** -+ * cpr3_open_loop_regulator_register() - register the regulators for a CPR3 -+ * controller which will always work in Open loop and -+ * won't support close loop. -+ * @pdev: Platform device pointer for the CPR3 controller -+ * @ctrl: Pointer to the CPR3 controller -+ * -+ * Return: 0 on success, errno on failure -+ */ -+int cpr3_open_loop_regulator_register(struct platform_device *pdev, -+ struct cpr3_controller *ctrl) -+{ -+ struct device *dev = &pdev->dev; -+ struct cpr3_regulator *vreg; -+ int i, j, rc; -+ -+ if (!dev->of_node) { -+ dev_err(dev, "%s: Device tree node is missing\n", __func__); -+ return -EINVAL; -+ } -+ -+ if (!ctrl || !ctrl->name) { -+ dev_err(dev, "%s: CPR controller data is missing\n", __func__); -+ return -EINVAL; -+ } -+ -+ if (!ctrl->vdd_regulator) { -+ cpr3_err(ctrl, "vdd regulator missing\n"); -+ return -EINVAL; -+ } -+ -+ mutex_init(&ctrl->lock); -+ -+ rc = cpr3_regulator_init_ctrl_data(ctrl); -+ if (rc) { -+ cpr3_err(ctrl, "CPR controller data initialization failed, rc=%d\n", -+ rc); -+ return rc; -+ } -+ -+ for (i = 0; i < ctrl->thread_count; i++) { -+ for (j = 0; j < ctrl->thread[i].vreg_count; j++) { -+ vreg = &ctrl->thread[i].vreg[j]; -+ vreg->corner[i].last_volt = -+ vreg->corner[i].open_loop_volt; -+ } -+ } -+ -+ /* Register regulator devices for all threads. */ -+ for (i = 0; i < ctrl->thread_count; i++) { -+ for (j = 0; j < ctrl->thread[i].vreg_count; j++) { -+ rc = cpr3_regulator_vreg_register( -+ &ctrl->thread[i].vreg[j]); -+ if (rc) { -+ cpr3_err(&ctrl->thread[i].vreg[j], "failed to register regulator, rc=%d\n", -+ rc); -+ goto free_regulators; -+ } -+ } -+ } -+ -+ mutex_lock(&cpr3_controller_list_mutex); -+ list_add(&ctrl->list, &cpr3_controller_list); -+ mutex_unlock(&cpr3_controller_list_mutex); -+ -+ return 0; -+ -+free_regulators: -+ for (i = 0; i < ctrl->thread_count; i++) -+ for (j = 0; j < ctrl->thread[i].vreg_count; j++) -+ if (!IS_ERR_OR_NULL(ctrl->thread[i].vreg[j].rdev)) -+ regulator_unregister( -+ ctrl->thread[i].vreg[j].rdev); -+ return rc; -+} -+ -+/** -+ * cpr3_regulator_unregister() - unregister the regulators for a CPR3 controller -+ * and perform CPR hardware shutdown -+ * @ctrl: Pointer to the CPR3 controller -+ * -+ * Return: 0 on success, errno on failure -+ */ -+int cpr3_regulator_unregister(struct cpr3_controller *ctrl) -+{ -+ int i, j, rc = 0; -+ -+ mutex_lock(&cpr3_controller_list_mutex); -+ list_del(&ctrl->list); -+ cpr3_regulator_debugfs_ctrl_remove(ctrl); -+ mutex_unlock(&cpr3_controller_list_mutex); -+ -+ if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4) { -+ rc = cpr3_ctrl_clear_cpr4_config(ctrl); -+ if (rc) -+ cpr3_err(ctrl, "failed to clear CPR4 configuration,rc=%d\n", -+ rc); -+ } -+ -+ cpr3_ctrl_loop_disable(ctrl); -+ -+ cpr3_closed_loop_disable(ctrl); -+ -+ if (ctrl->vdd_limit_regulator) { -+ regulator_disable(ctrl->vdd_limit_regulator); -+ } -+ -+ for (i = 0; i < ctrl->thread_count; i++) -+ for (j = 0; j < ctrl->thread[i].vreg_count; j++) -+ regulator_unregister(ctrl->thread[i].vreg[j].rdev); -+ -+ if (ctrl->panic_notifier.notifier_call) -+ atomic_notifier_chain_unregister(&panic_notifier_list, -+ &ctrl->panic_notifier); -+ -+ return 0; -+} -+ -+/** -+ * cpr3_open_loop_regulator_unregister() - unregister the regulators for a CPR3 -+ * open loop controller and perform CPR hardware shutdown -+ * @ctrl: Pointer to the CPR3 controller -+ * -+ * Return: 0 on success, errno on failure -+ */ -+int cpr3_open_loop_regulator_unregister(struct cpr3_controller *ctrl) -+{ -+ int i, j; -+ -+ mutex_lock(&cpr3_controller_list_mutex); -+ list_del(&ctrl->list); -+ mutex_unlock(&cpr3_controller_list_mutex); -+ -+ if (ctrl->vdd_limit_regulator) { -+ regulator_disable(ctrl->vdd_limit_regulator); -+ } -+ -+ for (i = 0; i < ctrl->thread_count; i++) -+ for (j = 0; j < ctrl->thread[i].vreg_count; j++) -+ regulator_unregister(ctrl->thread[i].vreg[j].rdev); -+ -+ if (ctrl->panic_notifier.notifier_call) -+ atomic_notifier_chain_unregister(&panic_notifier_list, -+ &ctrl->panic_notifier); -+ -+ return 0; -+} ---- /dev/null -+++ b/drivers/regulator/cpr3-regulator.h -@@ -0,0 +1,1211 @@ -+/* -+ * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 and -+ * only version 2 as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ */ -+ -+#ifndef __REGULATOR_CPR3_REGULATOR_H__ -+#define __REGULATOR_CPR3_REGULATOR_H__ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+struct cpr3_controller; -+struct cpr3_thread; -+ -+/** -+ * struct cpr3_fuse_param - defines one contiguous segment of a fuse parameter -+ * that is contained within a given row. -+ * @row: Fuse row number -+ * @bit_start: The first bit within the row of the fuse parameter segment -+ * @bit_end: The last bit within the row of the fuse parameter segment -+ * -+ * Each fuse row is 64 bits in length. bit_start and bit_end may take values -+ * from 0 to 63. bit_start must be less than or equal to bit_end. -+ */ -+struct cpr3_fuse_param { -+ unsigned row; -+ unsigned bit_start; -+ unsigned bit_end; -+}; -+ -+/* Each CPR3 sensor has 16 ring oscillators */ -+#define CPR3_RO_COUNT 16 -+ -+/* The maximum number of sensors that can be present on a single CPR loop. */ -+#define CPR3_MAX_SENSOR_COUNT 256 -+ -+/* This constant is used when allocating array printing buffers. */ -+#define MAX_CHARS_PER_INT 10 -+ -+/** -+ * struct cpr4_sdelta - CPR4 controller specific data structure for the sdelta -+ * adjustment table which is used to adjust the VDD supply -+ * voltage automatically based upon the temperature and/or -+ * the number of online CPU cores. -+ * @allow_core_count_adj: Core count adjustments are allowed. -+ * @allow_temp_adj: Temperature based adjustments are allowed. -+ * @max_core_count: Maximum number of cores considered for core count -+ * adjustment logic. -+ * @temp_band_count: Number of temperature bands considered for temperature -+ * based adjustment logic. -+ * @cap_volt: CAP in uV to apply to SDELTA margins with multiple -+ * cpr3-regulators defined for single controller. -+ * @table: SDELTA table with per-online-core and temperature based -+ * adjustments of size (max_core_count * temp_band_count) -+ * Outer: core count -+ * Inner: temperature band -+ * Each element has units of VDD supply steps. Positive -+ * values correspond to a reduction in voltage and negative -+ * value correspond to an increase (this follows the SDELTA -+ * register semantics). -+ * @allow_boost: Voltage boost allowed. -+ * @boost_num_cores: The number of online cores at which the boost voltage -+ * adjustments will be applied -+ * @boost_table: SDELTA table with boost voltage adjustments of size -+ * temp_band_count. Each element has units of VDD supply -+ * steps. Positive values correspond to a reduction in -+ * voltage and negative value correspond to an increase -+ * (this follows the SDELTA register semantics). -+ */ -+struct cpr4_sdelta { -+ bool allow_core_count_adj; -+ bool allow_temp_adj; -+ int max_core_count; -+ int temp_band_count; -+ int cap_volt; -+ int *table; -+ bool allow_boost; -+ int boost_num_cores; -+ int *boost_table; -+}; -+ -+/** -+ * struct cpr3_corner - CPR3 virtual voltage corner data structure -+ * @floor_volt: CPR closed-loop floor voltage in microvolts -+ * @ceiling_volt: CPR closed-loop ceiling voltage in microvolts -+ * @open_loop_volt: CPR open-loop voltage (i.e. initial voltage) in -+ * microvolts -+ * @last_volt: Last known settled CPR closed-loop voltage which is used -+ * when switching to a new corner -+ * @abs_ceiling_volt: The absolute CPR closed-loop ceiling voltage in -+ * microvolts. This is used to limit the ceiling_volt -+ * value when it is increased as a result of aging -+ * adjustment. -+ * @unaged_floor_volt: The CPR closed-loop floor voltage in microvolts before -+ * any aging adjustment is performed -+ * @unaged_ceiling_volt: The CPR closed-loop ceiling voltage in microvolts -+ * before any aging adjustment is performed -+ * @unaged_open_loop_volt: The CPR open-loop voltage (i.e. initial voltage) in -+ * microvolts before any aging adjusment is performed -+ * @system_volt: The system-supply voltage in microvolts or corners or -+ * levels -+ * @mem_acc_volt: The mem-acc-supply voltage in corners -+ * @proc_freq: Processor frequency in Hertz. For CPR rev. 3 and 4 -+ * conrollers, this field is only used by platform specific -+ * CPR3 driver for interpolation. For CPRh-compliant -+ * controllers, this frequency is also utilized by the -+ * clock driver to determine the corner to CPU clock -+ * frequency mappings. -+ * @cpr_fuse_corner: Fused corner index associated with this virtual corner -+ * (only used by platform specific CPR3 driver for -+ * mapping purposes) -+ * @target_quot: Array of target quotient values to use for each ring -+ * oscillator (RO) for this corner. A value of 0 should be -+ * specified as the target quotient for each RO that is -+ * unused by this corner. -+ * @ro_scale: Array of CPR ring oscillator (RO) scaling factors. The -+ * scaling factor for each RO is defined from RO0 to RO15 -+ * with units of QUOT/V. A value of 0 may be specified for -+ * an RO that is unused. -+ * @ro_mask: Bitmap where each of the 16 LSBs indicate if the -+ * corresponding ROs should be masked for this corner -+ * @irq_en: Bitmap of the CPR interrupts to enable for this corner -+ * @aging_derate: The amount to derate the aging voltage adjustment -+ * determined for the reference corner in units of uV/mV. -+ * E.g. a value of 900 would imply that the adjustment for -+ * this corner should be 90% (900/1000) of that for the -+ * reference corner. -+ * @use_open_loop: Boolean indicating that open-loop (i.e CPR disabled) as -+ * opposed to closed-loop operation must be used for this -+ * corner on CPRh controllers. -+ * @sdelta: The CPR4 controller specific data for this corner. This -+ * field is applicable for CPR4 controllers. -+ * -+ * The value of last_volt is initialized inside of the cpr3_regulator_register() -+ * call with the open_loop_volt value. It can later be updated to the settled -+ * VDD supply voltage. The values for unaged_floor_volt, unaged_ceiling_volt, -+ * and unaged_open_loop_volt are initialized inside of cpr3_regulator_register() -+ * if ctrl->aging_required == true. These three values must be pre-initialized -+ * if cpr3_regulator_register() is called with ctrl->aging_required == false and -+ * ctrl->aging_succeeded == true. -+ * -+ * The values of ro_mask and irq_en are initialized inside of the -+ * cpr3_regulator_register() call. -+ */ -+struct cpr3_corner { -+ int floor_volt; -+ int ceiling_volt; -+ int cold_temp_open_loop_volt; -+ int normal_temp_open_loop_volt; -+ int open_loop_volt; -+ int last_volt; -+ int abs_ceiling_volt; -+ int unaged_floor_volt; -+ int unaged_ceiling_volt; -+ int unaged_open_loop_volt; -+ int system_volt; -+ int mem_acc_volt; -+ u32 proc_freq; -+ int cpr_fuse_corner; -+ u32 target_quot[CPR3_RO_COUNT]; -+ u32 ro_scale[CPR3_RO_COUNT]; -+ u32 ro_mask; -+ u32 irq_en; -+ int aging_derate; -+ bool use_open_loop; -+ struct cpr4_sdelta *sdelta; -+}; -+ -+/** -+ * struct cprh_corner_band - CPRh controller specific data structure which -+ * encapsulates the range of corners and the SDELTA -+ * adjustment table to be applied to the corners within -+ * the min and max bounds of the corner band. -+ * @corner: Corner number which defines the corner band boundary -+ * @sdelta: The SDELTA adjustment table which contains core-count -+ * and temp based margin adjustments that are applicable -+ * to the corner band. -+ */ -+struct cprh_corner_band { -+ int corner; -+ struct cpr4_sdelta *sdelta; -+}; -+ -+/** -+ * struct cpr3_fuse_parameters - CPR4 fuse specific data structure which has -+ * the required fuse parameters need for Close Loop CPR -+ * @(*apss_ro_sel_param)[2]: Pointer to RO select fuse details -+ * @(*apss_init_voltage_param)[2]: Pointer to Target voltage fuse details -+ * @(*apss_target_quot_param)[2]: Pointer to Target quot fuse details -+ * @(*apss_quot_offset_param)[2]: Pointer to quot offset fuse details -+ * @cpr_fusing_rev_param: Pointer to CPR revision fuse details -+ * @apss_speed_bin_param: Pointer to Speed bin fuse details -+ * @cpr_boost_fuse_cfg_param: Pointer to Boost fuse cfg details -+ * @apss_boost_fuse_volt_param: Pointer to Boost fuse volt details -+ * @misc_fuse_volt_adj_param: Pointer to Misc fuse volt fuse details -+ */ -+struct cpr3_fuse_parameters { -+ struct cpr3_fuse_param (*apss_ro_sel_param)[2]; -+ struct cpr3_fuse_param (*apss_init_voltage_param)[2]; -+ struct cpr3_fuse_param (*apss_target_quot_param)[2]; -+ struct cpr3_fuse_param (*apss_quot_offset_param)[2]; -+ struct cpr3_fuse_param *cpr_fusing_rev_param; -+ struct cpr3_fuse_param *apss_speed_bin_param; -+ struct cpr3_fuse_param *cpr_boost_fuse_cfg_param; -+ struct cpr3_fuse_param *apss_boost_fuse_volt_param; -+ struct cpr3_fuse_param *misc_fuse_volt_adj_param; -+}; -+ -+struct cpr4_mem_acc_func { -+ void (*set_mem_acc)(struct regulator_dev *); -+ void (*clear_mem_acc)(struct regulator_dev *); -+}; -+ -+/** -+ * struct cpr4_reg_data - CPR4 regulator specific data structure which is -+ * target specific -+ * @cpr_valid_fuse_count: Number of valid fuse corners -+ * @fuse_ref_volt: Pointer to fuse reference voltage -+ * @fuse_step_volt: CPR step voltage available in fuse -+ * @cpr_clk_rate: CPR clock rate -+ * @boost_fuse_ref_volt: Boost fuse reference voltage -+ * @boost_ceiling_volt: Boost ceiling voltage -+ * @boost_floor_volt: Boost floor voltage -+ * @cpr3_fuse_params: Pointer to CPR fuse parameters -+ * @mem_acc_funcs: Pointer to MEM ACC set/clear functions -+ **/ -+struct cpr4_reg_data { -+ u32 cpr_valid_fuse_count; -+ int *fuse_ref_volt; -+ u32 fuse_step_volt; -+ u32 cpr_clk_rate; -+ int boost_fuse_ref_volt; -+ int boost_ceiling_volt; -+ int boost_floor_volt; -+ struct cpr3_fuse_parameters *cpr3_fuse_params; -+ struct cpr4_mem_acc_func *mem_acc_funcs; -+}; -+/** -+ * struct cpr3_reg_data - CPR3 regulator specific data structure which is -+ * target specific -+ * @cpr_valid_fuse_count: Number of valid fuse corners -+ * @(*init_voltage_param)[2]: Pointer to Target voltage fuse details -+ * @fuse_ref_volt: Pointer to fuse reference voltage -+ * @fuse_step_volt: CPR step voltage available in fuse -+ * @cpr_clk_rate: CPR clock rate -+ * @cpr3_fuse_params: Pointer to CPR fuse parameters -+ **/ -+struct cpr3_reg_data { -+ u32 cpr_valid_fuse_count; -+ struct cpr3_fuse_param (*init_voltage_param)[2]; -+ int *fuse_ref_volt; -+ u32 fuse_step_volt; -+ u32 cpr_clk_rate; -+}; -+ -+/** -+ * struct cpr3_regulator - CPR3 logical regulator instance associated with a -+ * given CPR3 hardware thread -+ * @of_node: Device node associated with the device tree child node -+ * of this CPR3 regulator -+ * @thread: Pointer to the CPR3 thread which manages this CPR3 -+ * regulator -+ * @name: Unique name for this CPR3 regulator which is filled -+ * using the device tree regulator-name property -+ * @rdesc: Regulator description for this CPR3 regulator -+ * @rdev: Regulator device pointer for the regulator registered -+ * for this CPR3 regulator -+ * @mem_acc_regulator: Pointer to the optional mem-acc supply regulator used -+ * to manage memory circuitry settings based upon CPR3 -+ * regulator output voltage. -+ * @corner: Array of all corners supported by this CPR3 regulator -+ * @corner_count: The number of elements in the corner array -+ * @corner_band: Array of all corner bands supported by CPRh compatible -+ * controllers -+ * @cpr4_regulator_data Target specific cpr4 regulator data -+ * @cpr3_regulator_data Target specific cpr3 regulator data -+ * @corner_band_count: The number of elements in the corner band array -+ * @platform_fuses: Pointer to platform specific CPR fuse data (only used by -+ * platform specific CPR3 driver) -+ * @speed_bin_fuse: Value read from the speed bin fuse parameter -+ * @speed_bins_supported: The number of speed bins supported by the device tree -+ * configuration for this CPR3 regulator -+ * @cpr_rev_fuse: Value read from the CPR fusing revision fuse parameter -+ * @fuse_combo: Platform specific enum value identifying the specific -+ * combination of fuse values found on a given chip -+ * @fuse_combos_supported: The number of fuse combinations supported by the -+ * device tree configuration for this CPR3 regulator -+ * @fuse_corner_count: Number of corners defined by fuse parameters -+ * @fuse_corner_map: Array of length fuse_corner_count which specifies the -+ * highest corner associated with each fuse corner. Note -+ * that each element must correspond to a valid corner -+ * and that element values must be strictly increasing. -+ * Also, it is acceptable for the lowest fuse corner to map -+ * to a corner other than the lowest. Likewise, it is -+ * acceptable for the highest fuse corner to map to a -+ * corner other than the highest. -+ * @fuse_combo_corner_sum: The sum of the corner counts across all fuse combos -+ * @fuse_combo_offset: The device tree property array offset for the selected -+ * fuse combo -+ * @speed_bin_corner_sum: The sum of the corner counts across all speed bins -+ * This may be specified as 0 if per speed bin parsing -+ * support is not required. -+ * @speed_bin_offset: The device tree property array offset for the selected -+ * speed bin -+ * @fuse_combo_corner_band_sum: The sum of the corner band counts across all -+ * fuse combos -+ * @fuse_combo_corner_band_offset: The device tree property array offset for -+ * the corner band count corresponding to the selected -+ * fuse combo -+ * @speed_bin_corner_band_sum: The sum of the corner band counts across all -+ * speed bins. This may be specified as 0 if per speed bin -+ * parsing support is not required -+ * @speed_bin_corner_band_offset: The device tree property array offset for the -+ * corner band count corresponding to the selected speed -+ * bin -+ * @pd_bypass_mask: Bit mask of power domains associated with this CPR3 -+ * regulator -+ * @dynamic_floor_corner: Index identifying the voltage corner for the CPR3 -+ * regulator whose last_volt value should be used as the -+ * global CPR floor voltage if all of the power domains -+ * associated with this CPR3 regulator are bypassed -+ * @uses_dynamic_floor: Boolean flag indicating that dynamic_floor_corner should -+ * be utilized for the CPR3 regulator -+ * @current_corner: Index identifying the currently selected voltage corner -+ * for the CPR3 regulator or less than 0 if no corner has -+ * been requested -+ * @last_closed_loop_corner: Index identifying the last voltage corner for the -+ * CPR3 regulator which was configured when operating in -+ * CPR closed-loop mode or less than 0 if no corner has -+ * been requested. CPR registers are only written to when -+ * using closed-loop mode. -+ * @aggregated: Boolean flag indicating that this CPR3 regulator -+ * participated in the last aggregation event -+ * @debug_corner: Index identifying voltage corner used for displaying -+ * corner configuration values in debugfs -+ * @vreg_enabled: Boolean defining the enable state of the CPR3 -+ * regulator's regulator within the regulator framework. -+ * @aging_allowed: Boolean defining if CPR aging adjustments are allowed -+ * for this CPR3 regulator given the fuse combo of the -+ * device -+ * @aging_allow_open_loop_adj: Boolean defining if the open-loop voltage of each -+ * corner of this regulator should be adjusted as a result -+ * of an aging measurement. This flag can be set to false -+ * when the open-loop voltage adjustments have been -+ * specified such that they include the maximum possible -+ * aging adjustment. This flag is only used if -+ * aging_allowed == true. -+ * @aging_corner: The corner that should be configured for this regulator -+ * when an aging measurement is performed. -+ * @aging_max_adjust_volt: The maximum aging voltage margin in microvolts that -+ * may be added to the target quotients of this regulator. -+ * A value of 0 may be specified if this regulator does not -+ * require any aging adjustment. -+ * @allow_core_count_adj: Core count adjustments are allowed for this regulator. -+ * @allow_temp_adj: Temperature based adjustments are allowed for this -+ * regulator. -+ * @max_core_count: Maximum number of cores considered for core count -+ * adjustment logic. -+ * @allow_boost: Voltage boost allowed for this regulator. -+ * -+ * This structure contains both configuration and runtime state data. The -+ * elements current_corner, last_closed_loop_corner, aggregated, debug_corner, -+ * and vreg_enabled are state variables. -+ */ -+struct cpr3_regulator { -+ struct device_node *of_node; -+ struct cpr3_thread *thread; -+ const char *name; -+ struct regulator_desc rdesc; -+ struct regulator_dev *rdev; -+ struct regulator *mem_acc_regulator; -+ struct cpr3_corner *corner; -+ int corner_count; -+ struct cprh_corner_band *corner_band; -+ struct cpr4_reg_data *cpr4_regulator_data; -+ struct cpr3_reg_data *cpr3_regulator_data; -+ u32 corner_band_count; -+ -+ void *platform_fuses; -+ int speed_bin_fuse; -+ int speed_bins_supported; -+ int cpr_rev_fuse; -+ int part_type; -+ int part_type_supported; -+ int fuse_combo; -+ int fuse_combos_supported; -+ int fuse_corner_count; -+ int *fuse_corner_map; -+ int fuse_combo_corner_sum; -+ int fuse_combo_offset; -+ int speed_bin_corner_sum; -+ int speed_bin_offset; -+ int fuse_combo_corner_band_sum; -+ int fuse_combo_corner_band_offset; -+ int speed_bin_corner_band_sum; -+ int speed_bin_corner_band_offset; -+ u32 pd_bypass_mask; -+ int dynamic_floor_corner; -+ bool uses_dynamic_floor; -+ -+ int current_corner; -+ int last_closed_loop_corner; -+ bool aggregated; -+ int debug_corner; -+ bool vreg_enabled; -+ -+ bool aging_allowed; -+ bool aging_allow_open_loop_adj; -+ int aging_corner; -+ int aging_max_adjust_volt; -+ -+ bool allow_core_count_adj; -+ bool allow_temp_adj; -+ int max_core_count; -+ bool allow_boost; -+}; -+ -+/** -+ * struct cpr3_thread - CPR3 hardware thread data structure -+ * @thread_id: Hardware thread ID -+ * @of_node: Device node associated with the device tree child node -+ * of this CPR3 thread -+ * @ctrl: Pointer to the CPR3 controller which manages this thread -+ * @vreg: Array of CPR3 regulators handled by the CPR3 thread -+ * @vreg_count: Number of elements in the vreg array -+ * @aggr_corner: CPR corner containing the in process aggregated voltage -+ * and target quotient configurations which will be applied -+ * @last_closed_loop_aggr_corner: CPR corner containing the most recent -+ * configurations which were written into hardware -+ * registers when operating in closed loop mode (i.e. with -+ * CPR enabled) -+ * @consecutive_up: The number of consecutive CPR step up events needed to -+ * to trigger an up interrupt -+ * @consecutive_down: The number of consecutive CPR step down events needed to -+ * to trigger a down interrupt -+ * @up_threshold: The number CPR error steps required to generate an up -+ * event -+ * @down_threshold: The number CPR error steps required to generate a down -+ * event -+ * -+ * This structure contains both configuration and runtime state data. The -+ * elements aggr_corner and last_closed_loop_aggr_corner are state variables. -+ */ -+struct cpr3_thread { -+ u32 thread_id; -+ struct device_node *of_node; -+ struct cpr3_controller *ctrl; -+ struct cpr3_regulator *vreg; -+ int vreg_count; -+ struct cpr3_corner aggr_corner; -+ struct cpr3_corner last_closed_loop_aggr_corner; -+ -+ u32 consecutive_up; -+ u32 consecutive_down; -+ u32 up_threshold; -+ u32 down_threshold; -+}; -+ -+/* Per CPR controller data */ -+/** -+ * enum cpr3_mem_acc_corners - Constants which define the number of mem-acc -+ * regulator corners available in the mem-acc corner map array. -+ * %CPR3_MEM_ACC_LOW_CORNER: Index in mem-acc corner map array mapping to the -+ * mem-acc regulator corner -+ * to be used for low voltage vdd supply -+ * %CPR3_MEM_ACC_HIGH_CORNER: Index in mem-acc corner map array mapping to the -+ * mem-acc regulator corner to be used for high -+ * voltage vdd supply -+ * %CPR3_MEM_ACC_CORNERS: Number of elements in the mem-acc corner map -+ * array -+ */ -+enum cpr3_mem_acc_corners { -+ CPR3_MEM_ACC_LOW_CORNER = 0, -+ CPR3_MEM_ACC_HIGH_CORNER = 1, -+ CPR3_MEM_ACC_CORNERS = 2, -+}; -+ -+/** -+ * enum cpr3_count_mode - CPR3 controller count mode which defines the -+ * method that CPR sensor data is acquired -+ * %CPR3_COUNT_MODE_ALL_AT_ONCE_MIN: Capture all CPR sensor readings -+ * simultaneously and report the minimum -+ * value seen in successive measurements -+ * %CPR3_COUNT_MODE_ALL_AT_ONCE_MAX: Capture all CPR sensor readings -+ * simultaneously and report the maximum -+ * value seen in successive measurements -+ * %CPR3_COUNT_MODE_STAGGERED: Read one sensor at a time in a -+ * sequential fashion -+ * %CPR3_COUNT_MODE_ALL_AT_ONCE_AGE: Capture all CPR aging sensor readings -+ * simultaneously. -+ */ -+enum cpr3_count_mode { -+ CPR3_COUNT_MODE_ALL_AT_ONCE_MIN = 0, -+ CPR3_COUNT_MODE_ALL_AT_ONCE_MAX = 1, -+ CPR3_COUNT_MODE_STAGGERED = 2, -+ CPR3_COUNT_MODE_ALL_AT_ONCE_AGE = 3, -+}; -+ -+/** -+ * enum cpr_controller_type - supported CPR controller hardware types -+ * %CPR_CTRL_TYPE_CPR3: HW has CPR3 controller -+ * %CPR_CTRL_TYPE_CPR4: HW has CPR4 controller -+ */ -+enum cpr_controller_type { -+ CPR_CTRL_TYPE_CPR3, -+ CPR_CTRL_TYPE_CPR4, -+}; -+ -+/** -+ * cpr_setting - supported CPR global settings -+ * %CPR_DEFAULT: default mode from dts will be used -+ * %CPR_DISABLED: ceiling voltage will be used for all the corners -+ * %CPR_OPEN_LOOP_EN: CPR will work in OL -+ * %CPR_CLOSED_LOOP_EN: CPR will work in CL, if supported -+ */ -+enum cpr_setting { -+ CPR_DEFAULT = 0, -+ CPR_DISABLED = 1, -+ CPR_OPEN_LOOP_EN = 2, -+ CPR_CLOSED_LOOP_EN = 3, -+}; -+ -+/** -+ * struct cpr3_aging_sensor_info - CPR3 aging sensor information -+ * @sensor_id The index of the CPR3 sensor to be used in the aging -+ * measurement. -+ * @ro_scale The CPR ring oscillator (RO) scaling factor for the -+ * aging sensor with units of QUOT/V. -+ * @init_quot_diff: The fused quotient difference between aged and un-aged -+ * paths that was measured at manufacturing time. -+ * @measured_quot_diff: The quotient difference measured at runtime. -+ * @bypass_mask: Bit mask of the CPR sensors that must be bypassed during -+ * the aging measurement for this sensor -+ * -+ * This structure contains both configuration and runtime state data. The -+ * element measured_quot_diff is a state variable. -+ */ -+struct cpr3_aging_sensor_info { -+ u32 sensor_id; -+ u32 ro_scale; -+ int init_quot_diff; -+ int measured_quot_diff; -+ u32 bypass_mask[CPR3_MAX_SENSOR_COUNT / 32]; -+}; -+ -+/** -+ * struct cpr3_reg_info - Register information data structure -+ * @name: Register name -+ * @addr: Register physical address -+ * @value: Register content -+ * @virt_addr: Register virtual address -+ * -+ * This data structure is used to dump some critical register contents -+ * when the device crashes due to a kernel panic. -+ */ -+struct cpr3_reg_info { -+ const char *name; -+ u32 addr; -+ u32 value; -+ void __iomem *virt_addr; -+}; -+ -+/** -+ * struct cpr3_panic_regs_info - Data structure to dump critical register -+ * contents. -+ * @reg_count: Number of elements in the regs array -+ * @regs: Array of critical registers information -+ * -+ * This data structure is used to dump critical register contents when -+ * the device crashes due to a kernel panic. -+ */ -+struct cpr3_panic_regs_info { -+ int reg_count; -+ struct cpr3_reg_info *regs; -+}; -+ -+/** -+ * struct cpr3_controller - CPR3 controller data structure -+ * @dev: Device pointer for the CPR3 controller device -+ * @name: Unique name for the CPR3 controller -+ * @ctrl_id: Controller ID corresponding to the VDD supply number -+ * that this CPR3 controller manages. -+ * @cpr_ctrl_base: Virtual address of the CPR3 controller base register -+ * @fuse_base: Virtual address of fuse row 0 -+ * @aging_possible_reg: Virtual address of an optional platform-specific -+ * register that must be ready to determine if it is -+ * possible to perform an aging measurement. -+ * @list: list head used in a global cpr3-regulator list so that -+ * cpr3-regulator structs can be found easily in RAM dumps -+ * @thread: Array of CPR3 threads managed by the CPR3 controller -+ * @thread_count: Number of elements in the thread array -+ * @sensor_owner: Array of thread IDs indicating which thread owns a given -+ * CPR sensor -+ * @sensor_count: The number of CPR sensors found on the CPR loop managed -+ * by this CPR controller. Must be equal to the number of -+ * elements in the sensor_owner array -+ * @soc_revision: Revision number of the SoC. This may be unused by -+ * platforms that do not have different behavior for -+ * different SoC revisions. -+ * @lock: Mutex lock used to ensure mutual exclusion between -+ * all of the threads associated with the controller -+ * @vdd_regulator: Pointer to the VDD supply regulator which this CPR3 -+ * controller manages -+ * @system_regulator: Pointer to the optional system-supply regulator upon -+ * which the VDD supply regulator depends. -+ * @mem_acc_regulator: Pointer to the optional mem-acc supply regulator used -+ * to manage memory circuitry settings based upon the -+ * VDD supply output voltage. -+ * @vdd_limit_regulator: Pointer to the VDD supply limit regulator which is used -+ * for hardware closed-loop in order specify ceiling and -+ * floor voltage limits (platform specific) -+ * @system_supply_max_volt: Voltage in microvolts which corresponds to the -+ * absolute ceiling voltage of the system-supply -+ * @mem_acc_threshold_volt: mem-acc threshold voltage in microvolts -+ * @mem_acc_corner_map: mem-acc regulator corners mapping to low and high -+ * voltage mem-acc settings for the memories powered by -+ * this CPR3 controller and its associated CPR3 regulators -+ * @mem_acc_crossover_volt: Voltage in microvolts corresponding to the voltage -+ * that the VDD supply must be set to while a MEM ACC -+ * switch is in progress. This element must be initialized -+ * for CPRh controllers when a MEM ACC threshold voltage is -+ * defined. -+ * @core_clk: Pointer to the CPR3 controller core clock -+ * @iface_clk: Pointer to the CPR3 interface clock (platform specific) -+ * @bus_clk: Pointer to the CPR3 bus clock (platform specific) -+ * @irq: CPR interrupt number -+ * @irq_affinity_mask: The cpumask for the CPUs which the CPR interrupt should -+ * have affinity for -+ * @cpu_hotplug_notifier: CPU hotplug notifier used to reset IRQ affinity when a -+ * CPU is brought back online -+ * @ceiling_irq: Interrupt number for the interrupt that is triggered -+ * when hardware closed-loop attempts to exceed the ceiling -+ * voltage -+ * @apm: Handle to the array power mux (APM) -+ * @apm_threshold_volt: Voltage in microvolts which defines the threshold -+ * voltage to determine the APM supply selection for -+ * each corner -+ * @apm_crossover_volt: Voltage in microvolts corresponding to the voltage that -+ * the VDD supply must be set to while an APM switch is in -+ * progress. This element must be initialized for CPRh -+ * controllers when an APM threshold voltage is defined -+ * @apm_adj_volt: Minimum difference between APM threshold voltage and -+ * open-loop voltage which allows the APM threshold voltage -+ * to be used as a ceiling -+ * @apm_high_supply: APM supply to configure if VDD voltage is greater than -+ * or equal to the APM threshold voltage -+ * @apm_low_supply: APM supply to configure if the VDD voltage is less than -+ * the APM threshold voltage -+ * @base_volt: Minimum voltage in microvolts supported by the VDD -+ * supply managed by this CPR controller -+ * @corner_switch_delay_time: The delay time in nanoseconds used by the CPR -+ * controller to wait for voltage settling before -+ * acknowledging the OSM block after corner changes -+ * @cpr_clock_rate: CPR reference clock frequency in Hz. -+ * @sensor_time: The time in nanoseconds that each sensor takes to -+ * perform a measurement. -+ * @loop_time: The time in nanoseconds between consecutive CPR -+ * measurements. -+ * @up_down_delay_time: The time to delay in nanoseconds between consecutive CPR -+ * measurements when the last measurement recommended -+ * increasing or decreasing the vdd-supply voltage. -+ * (platform specific) -+ * @idle_clocks: Number of CPR reference clock ticks that the CPR -+ * controller waits in transitional states. -+ * @step_quot_init_min: The default minimum CPR step quotient value. The step -+ * quotient is the number of additional ring oscillator -+ * ticks observed when increasing one step in vdd-supply -+ * output voltage. -+ * @step_quot_init_max: The default maximum CPR step quotient value. -+ * @step_volt: Step size in microvolts between available set points -+ * of the VDD supply -+ * @down_error_step_limit: CPR4 hardware closed-loop down error step limit which -+ * defines the maximum number of VDD supply regulator steps -+ * that the voltage may be reduced as the result of a -+ * single CPR measurement. -+ * @up_error_step_limit: CPR4 hardware closed-loop up error step limit which -+ * defines the maximum number of VDD supply regulator steps -+ * that the voltage may be increased as the result of a -+ * single CPR measurement. -+ * @count_mode: CPR controller count mode -+ * @count_repeat: Number of times to perform consecutive sensor -+ * measurements when using all-at-once count modes. -+ * @proc_clock_throttle: Defines the processor clock frequency throttling -+ * register value to use. This can be used to reduce the -+ * clock frequency when a power domain exits a low power -+ * mode until CPR settles at a new voltage. -+ * (platform specific) -+ * @cpr_allowed_hw: Boolean which indicates if closed-loop CPR operation is -+ * permitted for a given chip based upon hardware fuse -+ * values -+ * @cpr_allowed_sw: Boolean which indicates if closed-loop CPR operation is -+ * permitted based upon software policies -+ * @supports_hw_closed_loop: Boolean which indicates if this CPR3/4 controller -+ * physically supports hardware closed-loop CPR operation -+ * @use_hw_closed_loop: Boolean which indicates that this controller will be -+ * using hardware closed-loop operation in place of -+ * software closed-loop operation. -+ * @ctrl_type: CPR controller type -+ * @saw_use_unit_mV: Boolean which indicates the unit used in SAW PVC -+ * interface is mV. -+ * @aggr_corner: CPR corner containing the most recently aggregated -+ * voltage configurations which are being used currently -+ * @cpr_enabled: Boolean which indicates that the CPR controller is -+ * enabled and operating in closed-loop mode. CPR clocks -+ * have been prepared and enabled whenever this flag is -+ * true. -+ * @last_corner_was_closed_loop: Boolean indicating if the last known corners -+ * were updated during closed loop operation. -+ * @cpr_suspended: Boolean which indicates that CPR has been temporarily -+ * disabled while enterring system suspend. -+ * @debugfs: Pointer to the debugfs directory of this CPR3 controller -+ * @aging_ref_volt: Reference voltage in microvolts to configure when -+ * performing CPR aging measurements. -+ * @aging_vdd_mode: vdd-supply regulator mode to configure before performing -+ * a CPR aging measurement. It should be one of -+ * REGULATOR_MODE_*. -+ * @aging_complete_vdd_mode: vdd-supply regulator mode to configure after -+ * performing a CPR aging measurement. It should be one of -+ * REGULATOR_MODE_*. -+ * @aging_ref_adjust_volt: The reference aging voltage margin in microvolts that -+ * should be added to the target quotients of the -+ * regulators managed by this controller after derating. -+ * @aging_required: Flag which indicates that a CPR aging measurement still -+ * needs to be performed for this CPR3 controller. -+ * @aging_succeeded: Flag which indicates that a CPR aging measurement has -+ * completed successfully. -+ * @aging_failed: Flag which indicates that a CPR aging measurement has -+ * failed to complete successfully. -+ * @aging_sensor: Array of CPR3 aging sensors which are used to perform -+ * aging measurements at a runtime. -+ * @aging_sensor_count: Number of elements in the aging_sensor array -+ * @aging_possible_mask: Optional bitmask used to mask off the -+ * aging_possible_reg register. -+ * @aging_possible_val: Optional value that the masked aging_possible_reg -+ * register must have in order for a CPR aging measurement -+ * to be possible. -+ * @step_quot_fixed: Fixed step quotient value used for target quotient -+ * adjustment if use_dynamic_step_quot is not set. -+ * This parameter is only relevant for CPR4 controllers -+ * when using the per-online-core or per-temperature -+ * adjustments. -+ * @initial_temp_band: Temperature band used for calculation of base-line -+ * target quotients (fused). -+ * @use_dynamic_step_quot: Boolean value which indicates that margin adjustment -+ * of target quotient will be based on the step quotient -+ * calculated dynamically in hardware for each RO. -+ * @allow_core_count_adj: Core count adjustments are allowed for this controller -+ * @allow_temp_adj: Temperature based adjustments are allowed for -+ * this controller -+ * @allow_boost: Voltage boost allowed for this controller. -+ * @temp_band_count: Number of temperature bands used for temperature based -+ * adjustment logic -+ * @temp_points: Array of temperature points in decidegrees Celsius used -+ * to specify the ranges for selected temperature bands. -+ * The array must have (temp_band_count - 1) elements -+ * allocated. -+ * @temp_sensor_id_start: Start ID of temperature sensors used for temperature -+ * based adjustments. -+ * @temp_sensor_id_end: End ID of temperature sensors used for temperature -+ * based adjustments. -+ * @voltage_settling_time: The time in nanoseconds that it takes for the -+ * VDD supply voltage to settle after being increased or -+ * decreased by step_volt microvolts which is used when -+ * SDELTA voltage margin adjustments are applied. -+ * @cpr_global_setting: Global setting for this CPR controller -+ * @panic_regs_info: Array of panic registers information which provides the -+ * list of registers to dump when the device crashes. -+ * @panic_notifier: Notifier block registered to global panic notifier list. -+ * -+ * This structure contains both configuration and runtime state data. The -+ * elements cpr_allowed_sw, use_hw_closed_loop, aggr_corner, cpr_enabled, -+ * last_corner_was_closed_loop, cpr_suspended, aging_ref_adjust_volt, -+ * aging_required, aging_succeeded, and aging_failed are state variables. -+ * -+ * The apm* elements do not need to be initialized if the VDD supply managed by -+ * the CPR3 controller does not utilize an APM. -+ * -+ * The elements step_quot_fixed, initial_temp_band, allow_core_count_adj, -+ * allow_temp_adj and temp* need to be initialized for CPR4 controllers which -+ * are using per-online-core or per-temperature adjustments. -+ */ -+struct cpr3_controller { -+ struct device *dev; -+ const char *name; -+ int ctrl_id; -+ void __iomem *cpr_ctrl_base; -+ void __iomem *fuse_base; -+ void __iomem *aging_possible_reg; -+ struct list_head list; -+ struct cpr3_thread *thread; -+ int thread_count; -+ u8 *sensor_owner; -+ int sensor_count; -+ int soc_revision; -+ struct mutex lock; -+ struct regulator *vdd_regulator; -+ struct regulator *system_regulator; -+ struct regulator *mem_acc_regulator; -+ struct regulator *vdd_limit_regulator; -+ int system_supply_max_volt; -+ int mem_acc_threshold_volt; -+ int mem_acc_corner_map[CPR3_MEM_ACC_CORNERS]; -+ int mem_acc_crossover_volt; -+ struct clk *core_clk; -+ struct clk *iface_clk; -+ struct clk *bus_clk; -+ int irq; -+ struct cpumask irq_affinity_mask; -+ struct notifier_block cpu_hotplug_notifier; -+ int ceiling_irq; -+ struct msm_apm_ctrl_dev *apm; -+ int apm_threshold_volt; -+ int apm_crossover_volt; -+ int apm_adj_volt; -+ enum msm_apm_supply apm_high_supply; -+ enum msm_apm_supply apm_low_supply; -+ int base_volt; -+ u32 corner_switch_delay_time; -+ u32 cpr_clock_rate; -+ u32 sensor_time; -+ u32 loop_time; -+ u32 up_down_delay_time; -+ u32 idle_clocks; -+ u32 step_quot_init_min; -+ u32 step_quot_init_max; -+ int step_volt; -+ u32 down_error_step_limit; -+ u32 up_error_step_limit; -+ enum cpr3_count_mode count_mode; -+ u32 count_repeat; -+ u32 proc_clock_throttle; -+ bool cpr_allowed_hw; -+ bool cpr_allowed_sw; -+ bool supports_hw_closed_loop; -+ bool use_hw_closed_loop; -+ enum cpr_controller_type ctrl_type; -+ bool saw_use_unit_mV; -+ struct cpr3_corner aggr_corner; -+ bool cpr_enabled; -+ bool last_corner_was_closed_loop; -+ bool cpr_suspended; -+ struct dentry *debugfs; -+ -+ int aging_ref_volt; -+ unsigned int aging_vdd_mode; -+ unsigned int aging_complete_vdd_mode; -+ int aging_ref_adjust_volt; -+ bool aging_required; -+ bool aging_succeeded; -+ bool aging_failed; -+ struct cpr3_aging_sensor_info *aging_sensor; -+ int aging_sensor_count; -+ u32 cur_sensor_state; -+ u32 aging_possible_mask; -+ u32 aging_possible_val; -+ -+ u32 step_quot_fixed; -+ u32 initial_temp_band; -+ bool use_dynamic_step_quot; -+ bool allow_core_count_adj; -+ bool allow_temp_adj; -+ bool allow_boost; -+ int temp_band_count; -+ int *temp_points; -+ u32 temp_sensor_id_start; -+ u32 temp_sensor_id_end; -+ u32 voltage_settling_time; -+ enum cpr_setting cpr_global_setting; -+ struct cpr3_panic_regs_info *panic_regs_info; -+ struct notifier_block panic_notifier; -+}; -+ -+/* Used for rounding voltages to the closest physically available set point. */ -+#define CPR3_ROUND(n, d) (DIV_ROUND_UP(n, d) * (d)) -+ -+#define cpr3_err(cpr3_thread, message, ...) \ -+ pr_err("%s: " message, (cpr3_thread)->name, ##__VA_ARGS__) -+#define cpr3_info(cpr3_thread, message, ...) \ -+ pr_info("%s: " message, (cpr3_thread)->name, ##__VA_ARGS__) -+#define cpr3_debug(cpr3_thread, message, ...) \ -+ pr_debug("%s: " message, (cpr3_thread)->name, ##__VA_ARGS__) -+ -+/* -+ * Offset subtracted from voltage corner values passed in from the regulator -+ * framework in order to get internal voltage corner values. This is needed -+ * since the regulator framework treats 0 as an error value at regulator -+ * registration time. -+ */ -+#define CPR3_CORNER_OFFSET 1 -+ -+#ifdef CONFIG_REGULATOR_CPR3 -+ -+int cpr3_regulator_register(struct platform_device *pdev, -+ struct cpr3_controller *ctrl); -+int cpr3_open_loop_regulator_register(struct platform_device *pdev, -+ struct cpr3_controller *ctrl); -+int cpr3_regulator_unregister(struct cpr3_controller *ctrl); -+int cpr3_open_loop_regulator_unregister(struct cpr3_controller *ctrl); -+int cpr3_regulator_suspend(struct cpr3_controller *ctrl); -+int cpr3_regulator_resume(struct cpr3_controller *ctrl); -+ -+int cpr3_allocate_threads(struct cpr3_controller *ctrl, u32 min_thread_id, -+ u32 max_thread_id); -+int cpr3_map_fuse_base(struct cpr3_controller *ctrl, -+ struct platform_device *pdev); -+int cpr3_read_tcsr_setting(struct cpr3_controller *ctrl, -+ struct platform_device *pdev, u8 start, u8 end); -+int cpr3_read_fuse_param(void __iomem *fuse_base_addr, -+ const struct cpr3_fuse_param *param, u64 *param_value); -+int cpr3_convert_open_loop_voltage_fuse(int ref_volt, int step_volt, u32 fuse, -+ int fuse_len); -+u64 cpr3_interpolate(u64 x1, u64 y1, u64 x2, u64 y2, u64 x); -+int cpr3_parse_array_property(struct cpr3_regulator *vreg, -+ const char *prop_name, int tuple_size, u32 *out); -+int cpr3_parse_corner_array_property(struct cpr3_regulator *vreg, -+ const char *prop_name, int tuple_size, u32 *out); -+int cpr3_parse_corner_band_array_property(struct cpr3_regulator *vreg, -+ const char *prop_name, int tuple_size, u32 *out); -+int cpr3_parse_common_corner_data(struct cpr3_regulator *vreg); -+int cpr3_parse_thread_u32(struct cpr3_thread *thread, const char *propname, -+ u32 *out_value, u32 value_min, u32 value_max); -+int cpr3_parse_ctrl_u32(struct cpr3_controller *ctrl, const char *propname, -+ u32 *out_value, u32 value_min, u32 value_max); -+int cpr3_parse_common_thread_data(struct cpr3_thread *thread); -+int cpr3_parse_common_ctrl_data(struct cpr3_controller *ctrl); -+int cpr3_parse_open_loop_common_ctrl_data(struct cpr3_controller *ctrl); -+int cpr3_limit_open_loop_voltages(struct cpr3_regulator *vreg); -+void cpr3_open_loop_voltage_as_ceiling(struct cpr3_regulator *vreg); -+int cpr3_limit_floor_voltages(struct cpr3_regulator *vreg); -+void cpr3_print_quots(struct cpr3_regulator *vreg); -+int cpr3_determine_part_type(struct cpr3_regulator *vreg, int fuse_volt); -+int cpr3_determine_temp_base_open_loop_correction(struct cpr3_regulator *vreg, -+ int *fuse_volt); -+int cpr3_adjust_fused_open_loop_voltages(struct cpr3_regulator *vreg, -+ int *fuse_volt); -+int cpr3_adjust_open_loop_voltages(struct cpr3_regulator *vreg); -+int cpr3_quot_adjustment(int ro_scale, int volt_adjust); -+int cpr3_voltage_adjustment(int ro_scale, int quot_adjust); -+int cpr3_parse_closed_loop_voltage_adjustments(struct cpr3_regulator *vreg, -+ u64 *ro_sel, int *volt_adjust, -+ int *volt_adjust_fuse, int *ro_scale); -+int cpr4_parse_core_count_temp_voltage_adj(struct cpr3_regulator *vreg, -+ bool use_corner_band); -+int cpr3_apm_init(struct cpr3_controller *ctrl); -+int cpr3_mem_acc_init(struct cpr3_regulator *vreg); -+void cprh_adjust_voltages_for_apm(struct cpr3_regulator *vreg); -+void cprh_adjust_voltages_for_mem_acc(struct cpr3_regulator *vreg); -+int cpr3_adjust_target_quotients(struct cpr3_regulator *vreg, -+ int *fuse_volt_adjust); -+int cpr3_handle_temp_open_loop_adjustment(struct cpr3_controller *ctrl, -+ bool is_cold); -+int cpr3_get_cold_temp_threshold(struct cpr3_regulator *vreg, int *cold_temp); -+bool cpr3_can_adjust_cold_temp(struct cpr3_regulator *vreg); -+ -+#else -+ -+static inline int cpr3_regulator_register(struct platform_device *pdev, -+ struct cpr3_controller *ctrl) -+{ -+ return -ENXIO; -+} -+ -+static inline int -+cpr3_open_loop_regulator_register(struct platform_device *pdev, -+ struct cpr3_controller *ctrl); -+{ -+ return -ENXIO; -+} -+ -+static inline int cpr3_regulator_unregister(struct cpr3_controller *ctrl) -+{ -+ return -ENXIO; -+} -+ -+static inline int -+cpr3_open_loop_regulator_unregister(struct cpr3_controller *ctrl) -+{ -+ return -ENXIO; -+} -+ -+static inline int cpr3_regulator_suspend(struct cpr3_controller *ctrl) -+{ -+ return -ENXIO; -+} -+ -+static inline int cpr3_regulator_resume(struct cpr3_controller *ctrl) -+{ -+ return -ENXIO; -+} -+ -+static inline int cpr3_get_thread_name(struct cpr3_thread *thread, -+ struct device_node *thread_node) -+{ -+ return -EPERM; -+} -+ -+static inline int cpr3_allocate_threads(struct cpr3_controller *ctrl, -+ u32 min_thread_id, u32 max_thread_id) -+{ -+ return -EPERM; -+} -+ -+static inline int cpr3_map_fuse_base(struct cpr3_controller *ctrl, -+ struct platform_device *pdev) -+{ -+ return -ENXIO; -+} -+ -+static inline int cpr3_read_tcsr_setting(struct cpr3_controller *ctrl, -+ struct platform_device *pdev, u8 start, u8 end) -+{ -+ return 0; -+} -+ -+static inline int cpr3_read_fuse_param(void __iomem *fuse_base_addr, -+ const struct cpr3_fuse_param *param, u64 *param_value) -+{ -+ return -EPERM; -+} -+ -+static inline int cpr3_convert_open_loop_voltage_fuse(int ref_volt, -+ int step_volt, u32 fuse, int fuse_len) -+{ -+ return -EPERM; -+} -+ -+static inline u64 cpr3_interpolate(u64 x1, u64 y1, u64 x2, u64 y2, u64 x) -+{ -+ return 0; -+} -+ -+static inline int cpr3_parse_array_property(struct cpr3_regulator *vreg, -+ const char *prop_name, int tuple_size, u32 *out) -+{ -+ return -EPERM; -+} -+ -+static inline int cpr3_parse_corner_array_property(struct cpr3_regulator *vreg, -+ const char *prop_name, int tuple_size, u32 *out) -+{ -+ return -EPERM; -+} -+ -+static inline int cpr3_parse_corner_band_array_property( -+ struct cpr3_regulator *vreg, const char *prop_name, -+ int tuple_size, u32 *out) -+{ -+ return -EPERM; -+} -+ -+static inline int cpr3_parse_common_corner_data(struct cpr3_regulator *vreg) -+{ -+ return -EPERM; -+} -+ -+static inline int cpr3_parse_thread_u32(struct cpr3_thread *thread, -+ const char *propname, u32 *out_value, u32 value_min, -+ u32 value_max) -+{ -+ return -EPERM; -+} -+ -+static inline int cpr3_parse_ctrl_u32(struct cpr3_controller *ctrl, -+ const char *propname, u32 *out_value, u32 value_min, -+ u32 value_max) -+{ -+ return -EPERM; -+} -+ -+static inline int cpr3_parse_common_thread_data(struct cpr3_thread *thread) -+{ -+ return -EPERM; -+} -+ -+static inline int cpr3_parse_common_ctrl_data(struct cpr3_controller *ctrl) -+{ -+ return -EPERM; -+} -+ -+static inline int -+cpr3_parse_open_loop_common_ctrl_data(struct cpr3_controller *ctrl) -+{ -+ return -EPERM; -+} -+ -+static inline int cpr3_limit_open_loop_voltages(struct cpr3_regulator *vreg) -+{ -+ return -EPERM; -+} -+ -+static inline void cpr3_open_loop_voltage_as_ceiling( -+ struct cpr3_regulator *vreg) -+{ -+ return; -+} -+ -+static inline int cpr3_limit_floor_voltages(struct cpr3_regulator *vreg) -+{ -+ return -EPERM; -+} -+ -+static inline void cpr3_print_quots(struct cpr3_regulator *vreg) -+{ -+ return; -+} -+ -+static inline int -+cpr3_determine_part_type(struct cpr3_regulator *vreg, int fuse_volt) -+{ -+ return -EPERM; -+} -+ -+static inline int -+cpr3_determine_temp_base_open_loop_correction(struct cpr3_regulator *vreg, -+ int *fuse_volt) -+{ -+ return -EPERM; -+} -+ -+static inline int cpr3_adjust_fused_open_loop_voltages( -+ struct cpr3_regulator *vreg, int *fuse_volt) -+{ -+ return -EPERM; -+} -+ -+static inline int cpr3_adjust_open_loop_voltages(struct cpr3_regulator *vreg) -+{ -+ return -EPERM; -+} -+ -+static inline int cpr3_quot_adjustment(int ro_scale, int volt_adjust) -+{ -+ return 0; -+} -+ -+static inline int cpr3_voltage_adjustment(int ro_scale, int quot_adjust) -+{ -+ return 0; -+} -+ -+static inline int cpr3_parse_closed_loop_voltage_adjustments( -+ struct cpr3_regulator *vreg, u64 *ro_sel, -+ int *volt_adjust, int *volt_adjust_fuse, int *ro_scale) -+{ -+ return 0; -+} -+ -+static inline int cpr4_parse_core_count_temp_voltage_adj( -+ struct cpr3_regulator *vreg, bool use_corner_band) -+{ -+ return 0; -+} -+ -+static inline int cpr3_apm_init(struct cpr3_controller *ctrl) -+{ -+ return 0; -+} -+ -+static inline int cpr3_mem_acc_init(struct cpr3_regulator *vreg) -+{ -+ return 0; -+} -+ -+static inline void cprh_adjust_voltages_for_apm(struct cpr3_regulator *vreg) -+{ -+} -+ -+static inline void cprh_adjust_voltages_for_mem_acc(struct cpr3_regulator *vreg) -+{ -+} -+ -+static inline int cpr3_adjust_target_quotients(struct cpr3_regulator *vreg, -+ int *fuse_volt_adjust) -+{ -+ return 0; -+} -+ -+static inline int -+cpr3_handle_temp_open_loop_adjustment(struct cpr3_controller *ctrl, -+ bool is_cold) -+{ -+ return 0; -+} -+ -+static inline bool -+cpr3_can_adjust_cold_temp(struct cpr3_regulator *vreg) -+{ -+ return false; -+} -+ -+static inline int -+cpr3_get_cold_temp_threshold(struct cpr3_regulator *vreg, int *cold_temp) -+{ -+ return 0; -+} -+#endif /* CONFIG_REGULATOR_CPR3 */ -+ -+#endif /* __REGULATOR_CPR_REGULATOR_H__ */ ---- /dev/null -+++ b/drivers/regulator/cpr3-util.c -@@ -0,0 +1,2750 @@ -+/* -+ * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 and -+ * only 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. -+ */ -+ -+/* -+ * This file contains utility functions to be used by platform specific CPR3 -+ * regulator drivers. -+ */ -+ -+#define pr_fmt(fmt) "%s: " fmt, __func__ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include "cpr3-regulator.h" -+ -+#define BYTES_PER_FUSE_ROW 8 -+#define MAX_FUSE_ROW_BIT 63 -+ -+#define CPR3_CONSECUTIVE_UP_DOWN_MIN 0 -+#define CPR3_CONSECUTIVE_UP_DOWN_MAX 15 -+#define CPR3_UP_DOWN_THRESHOLD_MIN 0 -+#define CPR3_UP_DOWN_THRESHOLD_MAX 31 -+#define CPR3_STEP_QUOT_MIN 0 -+#define CPR3_STEP_QUOT_MAX 63 -+#define CPR3_IDLE_CLOCKS_MIN 0 -+#define CPR3_IDLE_CLOCKS_MAX 31 -+ -+/* This constant has units of uV/mV so 1000 corresponds to 100%. */ -+#define CPR3_AGING_DERATE_UNITY 1000 -+ -+/** -+ * cpr3_allocate_regulators() - allocate and initialize CPR3 regulators for a -+ * given thread based upon device tree data -+ * @thread: Pointer to the CPR3 thread -+ * -+ * This function allocates the thread->vreg array based upon the number of -+ * device tree regulator subnodes. It also initializes generic elements of each -+ * regulator struct such as name, of_node, and thread. -+ * -+ * Return: 0 on success, errno on failure -+ */ -+static int cpr3_allocate_regulators(struct cpr3_thread *thread) -+{ -+ struct device_node *node; -+ int i, rc; -+ -+ thread->vreg_count = 0; -+ -+ for_each_available_child_of_node(thread->of_node, node) { -+ thread->vreg_count++; -+ } -+ -+ thread->vreg = devm_kcalloc(thread->ctrl->dev, thread->vreg_count, -+ sizeof(*thread->vreg), GFP_KERNEL); -+ if (!thread->vreg) -+ return -ENOMEM; -+ -+ i = 0; -+ for_each_available_child_of_node(thread->of_node, node) { -+ thread->vreg[i].of_node = node; -+ thread->vreg[i].thread = thread; -+ -+ rc = of_property_read_string(node, "regulator-name", -+ &thread->vreg[i].name); -+ if (rc) { -+ dev_err(thread->ctrl->dev, "could not find regulator name, rc=%d\n", -+ rc); -+ return rc; -+ } -+ -+ i++; -+ } -+ -+ return 0; -+} -+ -+/** -+ * cpr3_allocate_threads() - allocate and initialize CPR3 threads for a given -+ * controller based upon device tree data -+ * @ctrl: Pointer to the CPR3 controller -+ * @min_thread_id: Minimum allowed hardware thread ID for this controller -+ * @max_thread_id: Maximum allowed hardware thread ID for this controller -+ * -+ * This function allocates the ctrl->thread array based upon the number of -+ * device tree thread subnodes. It also initializes generic elements of each -+ * thread struct such as thread_id, of_node, ctrl, and vreg array. -+ * -+ * Return: 0 on success, errno on failure -+ */ -+int cpr3_allocate_threads(struct cpr3_controller *ctrl, u32 min_thread_id, -+ u32 max_thread_id) -+{ -+ struct device *dev = ctrl->dev; -+ struct device_node *thread_node; -+ int i, j, rc; -+ -+ ctrl->thread_count = 0; -+ -+ for_each_available_child_of_node(dev->of_node, thread_node) { -+ ctrl->thread_count++; -+ } -+ -+ ctrl->thread = devm_kcalloc(dev, ctrl->thread_count, -+ sizeof(*ctrl->thread), GFP_KERNEL); -+ if (!ctrl->thread) -+ return -ENOMEM; -+ -+ i = 0; -+ for_each_available_child_of_node(dev->of_node, thread_node) { -+ ctrl->thread[i].of_node = thread_node; -+ ctrl->thread[i].ctrl = ctrl; -+ -+ rc = of_property_read_u32(thread_node, "qcom,cpr-thread-id", -+ &ctrl->thread[i].thread_id); -+ if (rc) { -+ dev_err(dev, "could not read DT property qcom,cpr-thread-id, rc=%d\n", -+ rc); -+ return rc; -+ } -+ -+ if (ctrl->thread[i].thread_id < min_thread_id || -+ ctrl->thread[i].thread_id > max_thread_id) { -+ dev_err(dev, "invalid thread id = %u; not within [%u, %u]\n", -+ ctrl->thread[i].thread_id, min_thread_id, -+ max_thread_id); -+ return -EINVAL; -+ } -+ -+ /* Verify that the thread ID is unique for all child nodes. */ -+ for (j = 0; j < i; j++) { -+ if (ctrl->thread[j].thread_id -+ == ctrl->thread[i].thread_id) { -+ dev_err(dev, "duplicate thread id = %u found\n", -+ ctrl->thread[i].thread_id); -+ return -EINVAL; -+ } -+ } -+ -+ rc = cpr3_allocate_regulators(&ctrl->thread[i]); -+ if (rc) -+ return rc; -+ -+ i++; -+ } -+ -+ return 0; -+} -+ -+/** -+ * cpr3_map_fuse_base() - ioremap the base address of the fuse region -+ * @ctrl: Pointer to the CPR3 controller -+ * @pdev: Platform device pointer for the CPR3 controller -+ * -+ * Return: 0 on success, errno on failure -+ */ -+int cpr3_map_fuse_base(struct cpr3_controller *ctrl, -+ struct platform_device *pdev) -+{ -+ struct resource *res; -+ -+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "fuse_base"); -+ if (!res || !res->start) { -+ dev_err(&pdev->dev, "fuse base address is missing\n"); -+ return -ENXIO; -+ } -+ -+ ctrl->fuse_base = devm_ioremap(&pdev->dev, res->start, -+ resource_size(res)); -+ -+ return 0; -+} -+ -+/** -+ * cpr3_read_tcsr_setting - reads the CPR setting bits from TCSR register -+ * @ctrl: Pointer to the CPR3 controller -+ * @pdev: Platform device pointer for the CPR3 controller -+ * @start: start bit in TCSR register -+ * @end: end bit in TCSR register -+ * -+ * Return: 0 on success, errno on failure -+ */ -+int cpr3_read_tcsr_setting(struct cpr3_controller *ctrl, -+ struct platform_device *pdev, u8 start, u8 end) -+{ -+ struct resource *res; -+ void __iomem *tcsr_reg; -+ u32 val; -+ -+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, -+ "cpr_tcsr_reg"); -+ if (!res || !res->start) -+ return 0; -+ -+ tcsr_reg = ioremap(res->start, resource_size(res)); -+ if (!tcsr_reg) { -+ dev_err(&pdev->dev, "tcsr ioremap failed\n"); -+ return 0; -+ } -+ -+ val = readl_relaxed(tcsr_reg); -+ val &= GENMASK(end, start); -+ val >>= start; -+ -+ switch (val) { -+ case 1: -+ ctrl->cpr_global_setting = CPR_DISABLED; -+ break; -+ case 2: -+ ctrl->cpr_global_setting = CPR_OPEN_LOOP_EN; -+ break; -+ case 3: -+ ctrl->cpr_global_setting = CPR_CLOSED_LOOP_EN; -+ break; -+ default: -+ ctrl->cpr_global_setting = CPR_DEFAULT; -+ } -+ -+ iounmap(tcsr_reg); -+ -+ return 0; -+} -+ -+/** -+ * cpr3_read_fuse_param() - reads a CPR3 fuse parameter out of eFuses -+ * @fuse_base_addr: Virtual memory address of the eFuse base address -+ * @param: Null terminated array of fuse param segments to read -+ * from -+ * @param_value: Output with value read from the eFuses -+ * -+ * This function reads from each of the parameter segments listed in the param -+ * array and concatenates their values together. Reading stops when an element -+ * is reached which has all 0 struct values. The total number of bits specified -+ * for the fuse parameter across all segments must be less than or equal to 64. -+ * -+ * Return: 0 on success, errno on failure -+ */ -+int cpr3_read_fuse_param(void __iomem *fuse_base_addr, -+ const struct cpr3_fuse_param *param, u64 *param_value) -+{ -+ u64 fuse_val, val; -+ int bits; -+ int bits_total = 0; -+ -+ *param_value = 0; -+ -+ while (param->row || param->bit_start || param->bit_end) { -+ if (param->bit_start > param->bit_end -+ || param->bit_end > MAX_FUSE_ROW_BIT) { -+ pr_err("Invalid fuse parameter segment: row=%u, start=%u, end=%u\n", -+ param->row, param->bit_start, param->bit_end); -+ return -EINVAL; -+ } -+ -+ bits = param->bit_end - param->bit_start + 1; -+ if (bits_total + bits > 64) { -+ pr_err("Invalid fuse parameter segments; total bits = %d\n", -+ bits_total + bits); -+ return -EINVAL; -+ } -+ -+ fuse_val = readq_relaxed(fuse_base_addr -+ + param->row * BYTES_PER_FUSE_ROW); -+ val = (fuse_val >> param->bit_start) & ((1ULL << bits) - 1); -+ *param_value |= val << bits_total; -+ bits_total += bits; -+ -+ param++; -+ } -+ -+ return 0; -+} -+ -+/** -+ * cpr3_convert_open_loop_voltage_fuse() - converts an open loop voltage fuse -+ * value into an absolute voltage with units of microvolts -+ * @ref_volt: Reference voltage in microvolts -+ * @step_volt: The step size in microvolts of the fuse LSB -+ * @fuse: Open loop voltage fuse value -+ * @fuse_len: The bit length of the fuse value -+ * -+ * The MSB of the fuse parameter corresponds to a sign bit. If it is set, then -+ * the lower bits correspond to the number of steps to go down from the -+ * reference voltage. If it is not set, then the lower bits correspond to the -+ * number of steps to go up from the reference voltage. -+ */ -+int cpr3_convert_open_loop_voltage_fuse(int ref_volt, int step_volt, u32 fuse, -+ int fuse_len) -+{ -+ int sign, steps; -+ -+ sign = (fuse & (1 << (fuse_len - 1))) ? -1 : 1; -+ steps = fuse & ((1 << (fuse_len - 1)) - 1); -+ -+ return ref_volt + sign * steps * step_volt; -+} -+ -+/** -+ * cpr3_interpolate() - performs linear interpolation -+ * @x1 Lower known x value -+ * @y1 Lower known y value -+ * @x2 Upper known x value -+ * @y2 Upper known y value -+ * @x Intermediate x value -+ * -+ * Returns y where (x, y) falls on the line between (x1, y1) and (x2, y2). -+ * It is required that x1 < x2, y1 <= y2, and x1 <= x <= x2. If these -+ * conditions are not met, then y2 will be returned. -+ */ -+u64 cpr3_interpolate(u64 x1, u64 y1, u64 x2, u64 y2, u64 x) -+{ -+ u64 temp; -+ -+ if (x1 >= x2 || y1 > y2 || x1 > x || x > x2) -+ return y2; -+ -+ temp = (x2 - x) * (y2 - y1); -+ do_div(temp, (u32)(x2 - x1)); -+ -+ return y2 - temp; -+} -+ -+/** -+ * cpr3_parse_array_property() - fill an array from a portion of the values -+ * specified for a device tree property -+ * @vreg: Pointer to the CPR3 regulator -+ * @prop_name: The name of the device tree property to read from -+ * @tuple_size: The number of elements in each tuple -+ * @out: Output data array which must be of size tuple_size -+ * -+ * cpr3_parse_common_corner_data() must be called for vreg before this function -+ * is called so that fuse combo and speed bin size elements are initialized. -+ * -+ * Three formats are supported for the device tree property: -+ * 1. Length == tuple_size -+ * (reading begins at index 0) -+ * 2. Length == tuple_size * vreg->fuse_combos_supported -+ * (reading begins at index tuple_size * vreg->fuse_combo) -+ * 3. Length == tuple_size * vreg->speed_bins_supported -+ * (reading begins at index tuple_size * vreg->speed_bin_fuse) -+ * -+ * All other property lengths are treated as errors. -+ * -+ * Return: 0 on success, errno on failure -+ */ -+int cpr3_parse_array_property(struct cpr3_regulator *vreg, -+ const char *prop_name, int tuple_size, u32 *out) -+{ -+ struct device_node *node = vreg->of_node; -+ int len = 0; -+ int i, offset, rc; -+ -+ if (!of_find_property(node, prop_name, &len)) { -+ cpr3_err(vreg, "property %s is missing\n", prop_name); -+ return -EINVAL; -+ } -+ -+ if (len == tuple_size * sizeof(u32)) { -+ offset = 0; -+ } else if (len == tuple_size * vreg->fuse_combos_supported -+ * sizeof(u32)) { -+ offset = tuple_size * vreg->fuse_combo; -+ } else if (vreg->speed_bins_supported > 0 && -+ len == tuple_size * vreg->speed_bins_supported * sizeof(u32)) { -+ offset = tuple_size * vreg->speed_bin_fuse; -+ } else { -+ if (vreg->speed_bins_supported > 0) -+ cpr3_err(vreg, "property %s has invalid length=%d, should be %zu, %zu, or %zu\n", -+ prop_name, len, -+ tuple_size * sizeof(u32), -+ tuple_size * vreg->speed_bins_supported -+ * sizeof(u32), -+ tuple_size * vreg->fuse_combos_supported -+ * sizeof(u32)); -+ else -+ cpr3_err(vreg, "property %s has invalid length=%d, should be %zu or %zu\n", -+ prop_name, len, -+ tuple_size * sizeof(u32), -+ tuple_size * vreg->fuse_combos_supported -+ * sizeof(u32)); -+ return -EINVAL; -+ } -+ -+ for (i = 0; i < tuple_size; i++) { -+ rc = of_property_read_u32_index(node, prop_name, offset + i, -+ &out[i]); -+ if (rc) { -+ cpr3_err(vreg, "error reading property %s, rc=%d\n", -+ prop_name, rc); -+ return rc; -+ } -+ } -+ -+ return 0; -+} -+ -+/** -+ * cpr3_parse_corner_array_property() - fill a per-corner array from a portion -+ * of the values specified for a device tree property -+ * @vreg: Pointer to the CPR3 regulator -+ * @prop_name: The name of the device tree property to read from -+ * @tuple_size: The number of elements in each per-corner tuple -+ * @out: Output data array which must be of size: -+ * tuple_size * vreg->corner_count -+ * -+ * cpr3_parse_common_corner_data() must be called for vreg before this function -+ * is called so that fuse combo and speed bin size elements are initialized. -+ * -+ * Three formats are supported for the device tree property: -+ * 1. Length == tuple_size * vreg->corner_count -+ * (reading begins at index 0) -+ * 2. Length == tuple_size * vreg->fuse_combo_corner_sum -+ * (reading begins at index tuple_size * vreg->fuse_combo_offset) -+ * 3. Length == tuple_size * vreg->speed_bin_corner_sum -+ * (reading begins at index tuple_size * vreg->speed_bin_offset) -+ * -+ * All other property lengths are treated as errors. -+ * -+ * Return: 0 on success, errno on failure -+ */ -+int cpr3_parse_corner_array_property(struct cpr3_regulator *vreg, -+ const char *prop_name, int tuple_size, u32 *out) -+{ -+ struct device_node *node = vreg->of_node; -+ int len = 0; -+ int i, offset, rc; -+ -+ if (!of_find_property(node, prop_name, &len)) { -+ cpr3_err(vreg, "property %s is missing\n", prop_name); -+ return -EINVAL; -+ } -+ -+ if (len == tuple_size * vreg->corner_count * sizeof(u32)) { -+ offset = 0; -+ } else if (len == tuple_size * vreg->fuse_combo_corner_sum -+ * sizeof(u32)) { -+ offset = tuple_size * vreg->fuse_combo_offset; -+ } else if (vreg->speed_bin_corner_sum > 0 && -+ len == tuple_size * vreg->speed_bin_corner_sum * sizeof(u32)) { -+ offset = tuple_size * vreg->speed_bin_offset; -+ } else { -+ if (vreg->speed_bin_corner_sum > 0) -+ cpr3_err(vreg, "property %s has invalid length=%d, should be %zu, %zu, or %zu\n", -+ prop_name, len, -+ tuple_size * vreg->corner_count * sizeof(u32), -+ tuple_size * vreg->speed_bin_corner_sum -+ * sizeof(u32), -+ tuple_size * vreg->fuse_combo_corner_sum -+ * sizeof(u32)); -+ else -+ cpr3_err(vreg, "property %s has invalid length=%d, should be %zu or %zu\n", -+ prop_name, len, -+ tuple_size * vreg->corner_count * sizeof(u32), -+ tuple_size * vreg->fuse_combo_corner_sum -+ * sizeof(u32)); -+ return -EINVAL; -+ } -+ -+ for (i = 0; i < tuple_size * vreg->corner_count; i++) { -+ rc = of_property_read_u32_index(node, prop_name, offset + i, -+ &out[i]); -+ if (rc) { -+ cpr3_err(vreg, "error reading property %s, rc=%d\n", -+ prop_name, rc); -+ return rc; -+ } -+ } -+ -+ return 0; -+} -+ -+/** -+ * cpr3_parse_corner_band_array_property() - fill a per-corner band array -+ * from a portion of the values specified for a device tree -+ * property -+ * @vreg: Pointer to the CPR3 regulator -+ * @prop_name: The name of the device tree property to read from -+ * @tuple_size: The number of elements in each per-corner band tuple -+ * @out: Output data array which must be of size: -+ * tuple_size * vreg->corner_band_count -+ * -+ * cpr3_parse_common_corner_data() must be called for vreg before this function -+ * is called so that fuse combo and speed bin size elements are initialized. -+ * In addition, corner band fuse combo and speed bin sum and offset elements -+ * must be initialized prior to executing this function. -+ * -+ * Three formats are supported for the device tree property: -+ * 1. Length == tuple_size * vreg->corner_band_count -+ * (reading begins at index 0) -+ * 2. Length == tuple_size * vreg->fuse_combo_corner_band_sum -+ * (reading begins at index tuple_size * -+ * vreg->fuse_combo_corner_band_offset) -+ * 3. Length == tuple_size * vreg->speed_bin_corner_band_sum -+ * (reading begins at index tuple_size * -+ * vreg->speed_bin_corner_band_offset) -+ * -+ * All other property lengths are treated as errors. -+ * -+ * Return: 0 on success, errno on failure -+ */ -+int cpr3_parse_corner_band_array_property(struct cpr3_regulator *vreg, -+ const char *prop_name, int tuple_size, u32 *out) -+{ -+ struct device_node *node = vreg->of_node; -+ int len = 0; -+ int i, offset, rc; -+ -+ if (!of_find_property(node, prop_name, &len)) { -+ cpr3_err(vreg, "property %s is missing\n", prop_name); -+ return -EINVAL; -+ } -+ -+ if (len == tuple_size * vreg->corner_band_count * sizeof(u32)) { -+ offset = 0; -+ } else if (len == tuple_size * vreg->fuse_combo_corner_band_sum -+ * sizeof(u32)) { -+ offset = tuple_size * vreg->fuse_combo_corner_band_offset; -+ } else if (vreg->speed_bin_corner_band_sum > 0 && -+ len == tuple_size * vreg->speed_bin_corner_band_sum * -+ sizeof(u32)) { -+ offset = tuple_size * vreg->speed_bin_corner_band_offset; -+ } else { -+ if (vreg->speed_bin_corner_band_sum > 0) -+ cpr3_err(vreg, "property %s has invalid length=%d, should be %zu, %zu, or %zu\n", -+ prop_name, len, -+ tuple_size * vreg->corner_band_count * -+ sizeof(u32), -+ tuple_size * vreg->speed_bin_corner_band_sum -+ * sizeof(u32), -+ tuple_size * vreg->fuse_combo_corner_band_sum -+ * sizeof(u32)); -+ else -+ cpr3_err(vreg, "property %s has invalid length=%d, should be %zu or %zu\n", -+ prop_name, len, -+ tuple_size * vreg->corner_band_count * -+ sizeof(u32), -+ tuple_size * vreg->fuse_combo_corner_band_sum -+ * sizeof(u32)); -+ return -EINVAL; -+ } -+ -+ for (i = 0; i < tuple_size * vreg->corner_band_count; i++) { -+ rc = of_property_read_u32_index(node, prop_name, offset + i, -+ &out[i]); -+ if (rc) { -+ cpr3_err(vreg, "error reading property %s, rc=%d\n", -+ prop_name, rc); -+ return rc; -+ } -+ } -+ -+ return 0; -+} -+ -+/** -+ * cpr3_parse_common_corner_data() - parse common CPR3 properties relating to -+ * the corners supported by a CPR3 regulator from device tree -+ * @vreg: Pointer to the CPR3 regulator -+ * -+ * This function reads, validates, and utilizes the following device tree -+ * properties: qcom,cpr-fuse-corners, qcom,cpr-fuse-combos, qcom,cpr-speed-bins, -+ * qcom,cpr-speed-bin-corners, qcom,cpr-corners, qcom,cpr-voltage-ceiling, -+ * qcom,cpr-voltage-floor, qcom,corner-frequencies, -+ * and qcom,cpr-corner-fmax-map. -+ * -+ * It initializes these CPR3 regulator elements: corner, corner_count, -+ * fuse_combos_supported, fuse_corner_map, and speed_bins_supported. It -+ * initializes these elements for each corner: ceiling_volt, floor_volt, -+ * proc_freq, and cpr_fuse_corner. -+ * -+ * It requires that the following CPR3 regulator elements be initialized before -+ * being called: fuse_corner_count, fuse_combo, and speed_bin_fuse. -+ * -+ * Return: 0 on success, errno on failure -+ */ -+int cpr3_parse_common_corner_data(struct cpr3_regulator *vreg) -+{ -+ struct device_node *node = vreg->of_node; -+ struct cpr3_controller *ctrl = vreg->thread->ctrl; -+ u32 max_fuse_combos, fuse_corners, aging_allowed = 0; -+ u32 max_speed_bins = 0; -+ u32 *combo_corners; -+ u32 *speed_bin_corners; -+ u32 *temp; -+ int i, j, rc; -+ -+ rc = of_property_read_u32(node, "qcom,cpr-fuse-corners", &fuse_corners); -+ if (rc) { -+ cpr3_err(vreg, "error reading property qcom,cpr-fuse-corners, rc=%d\n", -+ rc); -+ return rc; -+ } -+ -+ if (vreg->fuse_corner_count != fuse_corners) { -+ cpr3_err(vreg, "device tree config supports %d fuse corners but the hardware has %d fuse corners\n", -+ fuse_corners, vreg->fuse_corner_count); -+ return -EINVAL; -+ } -+ -+ rc = of_property_read_u32(node, "qcom,cpr-fuse-combos", -+ &max_fuse_combos); -+ if (rc) { -+ cpr3_err(vreg, "error reading property qcom,cpr-fuse-combos, rc=%d\n", -+ rc); -+ return rc; -+ } -+ -+ /* -+ * Sanity check against arbitrarily large value to avoid excessive -+ * memory allocation. -+ */ -+ if (max_fuse_combos > 100 || max_fuse_combos == 0) { -+ cpr3_err(vreg, "qcom,cpr-fuse-combos is invalid: %u\n", -+ max_fuse_combos); -+ return -EINVAL; -+ } -+ -+ if (vreg->fuse_combo >= max_fuse_combos) { -+ cpr3_err(vreg, "device tree config supports fuse combos 0-%u but the hardware has combo %d\n", -+ max_fuse_combos - 1, vreg->fuse_combo); -+ BUG_ON(1); -+ return -EINVAL; -+ } -+ -+ vreg->fuse_combos_supported = max_fuse_combos; -+ -+ of_property_read_u32(node, "qcom,cpr-speed-bins", &max_speed_bins); -+ -+ /* -+ * Sanity check against arbitrarily large value to avoid excessive -+ * memory allocation. -+ */ -+ if (max_speed_bins > 100) { -+ cpr3_err(vreg, "qcom,cpr-speed-bins is invalid: %u\n", -+ max_speed_bins); -+ return -EINVAL; -+ } -+ -+ if (max_speed_bins && vreg->speed_bin_fuse >= max_speed_bins) { -+ cpr3_err(vreg, "device tree config supports speed bins 0-%u but the hardware has speed bin %d\n", -+ max_speed_bins - 1, vreg->speed_bin_fuse); -+ BUG(); -+ return -EINVAL; -+ } -+ -+ vreg->speed_bins_supported = max_speed_bins; -+ -+ combo_corners = kcalloc(vreg->fuse_combos_supported, -+ sizeof(*combo_corners), GFP_KERNEL); -+ if (!combo_corners) -+ return -ENOMEM; -+ -+ rc = of_property_read_u32_array(node, "qcom,cpr-corners", combo_corners, -+ vreg->fuse_combos_supported); -+ if (rc == -EOVERFLOW) { -+ /* Single value case */ -+ rc = of_property_read_u32(node, "qcom,cpr-corners", -+ combo_corners); -+ for (i = 1; i < vreg->fuse_combos_supported; i++) -+ combo_corners[i] = combo_corners[0]; -+ } -+ if (rc) { -+ cpr3_err(vreg, "error reading property qcom,cpr-corners, rc=%d\n", -+ rc); -+ kfree(combo_corners); -+ return rc; -+ } -+ -+ vreg->fuse_combo_offset = 0; -+ vreg->fuse_combo_corner_sum = 0; -+ for (i = 0; i < vreg->fuse_combos_supported; i++) { -+ vreg->fuse_combo_corner_sum += combo_corners[i]; -+ if (i < vreg->fuse_combo) -+ vreg->fuse_combo_offset += combo_corners[i]; -+ } -+ -+ vreg->corner_count = combo_corners[vreg->fuse_combo]; -+ -+ kfree(combo_corners); -+ -+ vreg->speed_bin_offset = 0; -+ vreg->speed_bin_corner_sum = 0; -+ if (vreg->speed_bins_supported > 0) { -+ speed_bin_corners = kcalloc(vreg->speed_bins_supported, -+ sizeof(*speed_bin_corners), GFP_KERNEL); -+ if (!speed_bin_corners) -+ return -ENOMEM; -+ -+ rc = of_property_read_u32_array(node, -+ "qcom,cpr-speed-bin-corners", speed_bin_corners, -+ vreg->speed_bins_supported); -+ if (rc) { -+ cpr3_err(vreg, "error reading property qcom,cpr-speed-bin-corners, rc=%d\n", -+ rc); -+ kfree(speed_bin_corners); -+ return rc; -+ } -+ -+ for (i = 0; i < vreg->speed_bins_supported; i++) { -+ vreg->speed_bin_corner_sum += speed_bin_corners[i]; -+ if (i < vreg->speed_bin_fuse) -+ vreg->speed_bin_offset += speed_bin_corners[i]; -+ } -+ -+ if (speed_bin_corners[vreg->speed_bin_fuse] -+ != vreg->corner_count) { -+ cpr3_err(vreg, "qcom,cpr-corners and qcom,cpr-speed-bin-corners conflict on number of corners: %d vs %u\n", -+ vreg->corner_count, -+ speed_bin_corners[vreg->speed_bin_fuse]); -+ kfree(speed_bin_corners); -+ return -EINVAL; -+ } -+ -+ kfree(speed_bin_corners); -+ } -+ -+ vreg->corner = devm_kcalloc(ctrl->dev, vreg->corner_count, -+ sizeof(*vreg->corner), GFP_KERNEL); -+ temp = kcalloc(vreg->corner_count, sizeof(*temp), GFP_KERNEL); -+ if (!vreg->corner || !temp) -+ return -ENOMEM; -+ -+ rc = cpr3_parse_corner_array_property(vreg, "qcom,cpr-voltage-ceiling", -+ 1, temp); -+ if (rc) -+ goto free_temp; -+ for (i = 0; i < vreg->corner_count; i++) { -+ vreg->corner[i].ceiling_volt -+ = CPR3_ROUND(temp[i], ctrl->step_volt); -+ vreg->corner[i].abs_ceiling_volt = vreg->corner[i].ceiling_volt; -+ } -+ -+ rc = cpr3_parse_corner_array_property(vreg, "qcom,cpr-voltage-floor", -+ 1, temp); -+ if (rc) -+ goto free_temp; -+ for (i = 0; i < vreg->corner_count; i++) -+ vreg->corner[i].floor_volt -+ = CPR3_ROUND(temp[i], ctrl->step_volt); -+ -+ /* Validate ceiling and floor values */ -+ for (i = 0; i < vreg->corner_count; i++) { -+ if (vreg->corner[i].floor_volt -+ > vreg->corner[i].ceiling_volt) { -+ cpr3_err(vreg, "CPR floor[%d]=%d > ceiling[%d]=%d uV\n", -+ i, vreg->corner[i].floor_volt, -+ i, vreg->corner[i].ceiling_volt); -+ rc = -EINVAL; -+ goto free_temp; -+ } -+ } -+ -+ /* Load optional system-supply voltages */ -+ if (of_find_property(vreg->of_node, "qcom,system-voltage", NULL)) { -+ rc = cpr3_parse_corner_array_property(vreg, -+ "qcom,system-voltage", 1, temp); -+ if (rc) -+ goto free_temp; -+ for (i = 0; i < vreg->corner_count; i++) -+ vreg->corner[i].system_volt = temp[i]; -+ } -+ -+ rc = cpr3_parse_corner_array_property(vreg, "qcom,corner-frequencies", -+ 1, temp); -+ if (rc) -+ goto free_temp; -+ for (i = 0; i < vreg->corner_count; i++) -+ vreg->corner[i].proc_freq = temp[i]; -+ -+ /* Validate frequencies */ -+ for (i = 1; i < vreg->corner_count; i++) { -+ if (vreg->corner[i].proc_freq -+ < vreg->corner[i - 1].proc_freq) { -+ cpr3_err(vreg, "invalid frequency: freq[%d]=%u < freq[%d]=%u\n", -+ i, vreg->corner[i].proc_freq, i - 1, -+ vreg->corner[i - 1].proc_freq); -+ rc = -EINVAL; -+ goto free_temp; -+ } -+ } -+ -+ vreg->fuse_corner_map = devm_kcalloc(ctrl->dev, vreg->fuse_corner_count, -+ sizeof(*vreg->fuse_corner_map), GFP_KERNEL); -+ if (!vreg->fuse_corner_map) { -+ rc = -ENOMEM; -+ goto free_temp; -+ } -+ -+ rc = cpr3_parse_array_property(vreg, "qcom,cpr-corner-fmax-map", -+ vreg->fuse_corner_count, temp); -+ if (rc) -+ goto free_temp; -+ for (i = 0; i < vreg->fuse_corner_count; i++) { -+ vreg->fuse_corner_map[i] = temp[i] - CPR3_CORNER_OFFSET; -+ if (temp[i] < CPR3_CORNER_OFFSET -+ || temp[i] > vreg->corner_count + CPR3_CORNER_OFFSET) { -+ cpr3_err(vreg, "invalid corner value specified in qcom,cpr-corner-fmax-map: %u\n", -+ temp[i]); -+ rc = -EINVAL; -+ goto free_temp; -+ } else if (i > 0 && temp[i - 1] >= temp[i]) { -+ cpr3_err(vreg, "invalid corner %u less than or equal to previous corner %u\n", -+ temp[i], temp[i - 1]); -+ rc = -EINVAL; -+ goto free_temp; -+ } -+ } -+ if (temp[vreg->fuse_corner_count - 1] != vreg->corner_count) -+ cpr3_debug(vreg, "Note: highest Fmax corner %u in qcom,cpr-corner-fmax-map does not match highest supported corner %d\n", -+ temp[vreg->fuse_corner_count - 1], -+ vreg->corner_count); -+ -+ for (i = 0; i < vreg->corner_count; i++) { -+ for (j = 0; j < vreg->fuse_corner_count; j++) { -+ if (i + CPR3_CORNER_OFFSET <= temp[j]) { -+ vreg->corner[i].cpr_fuse_corner = j; -+ break; -+ } -+ } -+ if (j == vreg->fuse_corner_count) { -+ /* -+ * Handle the case where the highest fuse corner maps -+ * to a corner below the highest corner. -+ */ -+ vreg->corner[i].cpr_fuse_corner -+ = vreg->fuse_corner_count - 1; -+ } -+ } -+ -+ if (of_find_property(vreg->of_node, -+ "qcom,allow-aging-voltage-adjustment", NULL)) { -+ rc = cpr3_parse_array_property(vreg, -+ "qcom,allow-aging-voltage-adjustment", -+ 1, &aging_allowed); -+ if (rc) -+ goto free_temp; -+ -+ vreg->aging_allowed = aging_allowed; -+ } -+ -+ if (of_find_property(vreg->of_node, -+ "qcom,allow-aging-open-loop-voltage-adjustment", NULL)) { -+ rc = cpr3_parse_array_property(vreg, -+ "qcom,allow-aging-open-loop-voltage-adjustment", -+ 1, &aging_allowed); -+ if (rc) -+ goto free_temp; -+ -+ vreg->aging_allow_open_loop_adj = aging_allowed; -+ } -+ -+ if (vreg->aging_allowed) { -+ if (ctrl->aging_ref_volt <= 0) { -+ cpr3_err(ctrl, "qcom,cpr-aging-ref-voltage must be specified\n"); -+ rc = -EINVAL; -+ goto free_temp; -+ } -+ -+ rc = cpr3_parse_array_property(vreg, -+ "qcom,cpr-aging-max-voltage-adjustment", -+ 1, &vreg->aging_max_adjust_volt); -+ if (rc) -+ goto free_temp; -+ -+ rc = cpr3_parse_array_property(vreg, -+ "qcom,cpr-aging-ref-corner", 1, &vreg->aging_corner); -+ if (rc) { -+ goto free_temp; -+ } else if (vreg->aging_corner < CPR3_CORNER_OFFSET -+ || vreg->aging_corner > vreg->corner_count - 1 -+ + CPR3_CORNER_OFFSET) { -+ cpr3_err(vreg, "aging reference corner=%d not in range [%d, %d]\n", -+ vreg->aging_corner, CPR3_CORNER_OFFSET, -+ vreg->corner_count - 1 + CPR3_CORNER_OFFSET); -+ rc = -EINVAL; -+ goto free_temp; -+ } -+ vreg->aging_corner -= CPR3_CORNER_OFFSET; -+ -+ if (of_find_property(vreg->of_node, "qcom,cpr-aging-derate", -+ NULL)) { -+ rc = cpr3_parse_corner_array_property(vreg, -+ "qcom,cpr-aging-derate", 1, temp); -+ if (rc) -+ goto free_temp; -+ -+ for (i = 0; i < vreg->corner_count; i++) -+ vreg->corner[i].aging_derate = temp[i]; -+ } else { -+ for (i = 0; i < vreg->corner_count; i++) -+ vreg->corner[i].aging_derate -+ = CPR3_AGING_DERATE_UNITY; -+ } -+ } -+ -+free_temp: -+ kfree(temp); -+ return rc; -+} -+ -+/** -+ * cpr3_parse_thread_u32() - parse the specified property from the CPR3 thread's -+ * device tree node and verify that it is within the allowed limits -+ * @thread: Pointer to the CPR3 thread -+ * @propname: The name of the device tree property to read -+ * @out_value: The output pointer to fill with the value read -+ * @value_min: The minimum allowed property value -+ * @value_max: The maximum allowed property value -+ * -+ * This function prints a verbose error message if the property is missing or -+ * has a value which is not within the specified range. -+ * -+ * Return: 0 on success, errno on failure -+ */ -+int cpr3_parse_thread_u32(struct cpr3_thread *thread, const char *propname, -+ u32 *out_value, u32 value_min, u32 value_max) -+{ -+ int rc; -+ -+ rc = of_property_read_u32(thread->of_node, propname, out_value); -+ if (rc) { -+ cpr3_err(thread->ctrl, "thread %u error reading property %s, rc=%d\n", -+ thread->thread_id, propname, rc); -+ return rc; -+ } -+ -+ if (*out_value < value_min || *out_value > value_max) { -+ cpr3_err(thread->ctrl, "thread %u %s=%u is invalid; allowed range: [%u, %u]\n", -+ thread->thread_id, propname, *out_value, value_min, -+ value_max); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+/** -+ * cpr3_parse_ctrl_u32() - parse the specified property from the CPR3 -+ * controller's device tree node and verify that it is within the -+ * allowed limits -+ * @ctrl: Pointer to the CPR3 controller -+ * @propname: The name of the device tree property to read -+ * @out_value: The output pointer to fill with the value read -+ * @value_min: The minimum allowed property value -+ * @value_max: The maximum allowed property value -+ * -+ * This function prints a verbose error message if the property is missing or -+ * has a value which is not within the specified range. -+ * -+ * Return: 0 on success, errno on failure -+ */ -+int cpr3_parse_ctrl_u32(struct cpr3_controller *ctrl, const char *propname, -+ u32 *out_value, u32 value_min, u32 value_max) -+{ -+ int rc; -+ -+ rc = of_property_read_u32(ctrl->dev->of_node, propname, out_value); -+ if (rc) { -+ cpr3_err(ctrl, "error reading property %s, rc=%d\n", -+ propname, rc); -+ return rc; -+ } -+ -+ if (*out_value < value_min || *out_value > value_max) { -+ cpr3_err(ctrl, "%s=%u is invalid; allowed range: [%u, %u]\n", -+ propname, *out_value, value_min, value_max); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+/** -+ * cpr3_parse_common_thread_data() - parse common CPR3 thread properties from -+ * device tree -+ * @thread: Pointer to the CPR3 thread -+ * -+ * Return: 0 on success, errno on failure -+ */ -+int cpr3_parse_common_thread_data(struct cpr3_thread *thread) -+{ -+ int rc; -+ -+ rc = cpr3_parse_thread_u32(thread, "qcom,cpr-consecutive-up", -+ &thread->consecutive_up, CPR3_CONSECUTIVE_UP_DOWN_MIN, -+ CPR3_CONSECUTIVE_UP_DOWN_MAX); -+ if (rc) -+ return rc; -+ -+ rc = cpr3_parse_thread_u32(thread, "qcom,cpr-consecutive-down", -+ &thread->consecutive_down, CPR3_CONSECUTIVE_UP_DOWN_MIN, -+ CPR3_CONSECUTIVE_UP_DOWN_MAX); -+ if (rc) -+ return rc; -+ -+ rc = cpr3_parse_thread_u32(thread, "qcom,cpr-up-threshold", -+ &thread->up_threshold, CPR3_UP_DOWN_THRESHOLD_MIN, -+ CPR3_UP_DOWN_THRESHOLD_MAX); -+ if (rc) -+ return rc; -+ -+ rc = cpr3_parse_thread_u32(thread, "qcom,cpr-down-threshold", -+ &thread->down_threshold, CPR3_UP_DOWN_THRESHOLD_MIN, -+ CPR3_UP_DOWN_THRESHOLD_MAX); -+ if (rc) -+ return rc; -+ -+ return rc; -+} -+ -+/** -+ * cpr3_parse_irq_affinity() - parse CPR IRQ affinity information -+ * @ctrl: Pointer to the CPR3 controller -+ * -+ * Return: 0 on success, errno on failure -+ */ -+static int cpr3_parse_irq_affinity(struct cpr3_controller *ctrl) -+{ -+ struct device_node *cpu_node; -+ int i, cpu; -+ int len = 0; -+ -+ if (!of_find_property(ctrl->dev->of_node, "qcom,cpr-interrupt-affinity", -+ &len)) { -+ /* No IRQ affinity required */ -+ return 0; -+ } -+ -+ len /= sizeof(u32); -+ -+ for (i = 0; i < len; i++) { -+ cpu_node = of_parse_phandle(ctrl->dev->of_node, -+ "qcom,cpr-interrupt-affinity", i); -+ if (!cpu_node) { -+ cpr3_err(ctrl, "could not find CPU node %d\n", i); -+ return -EINVAL; -+ } -+ -+ for_each_possible_cpu(cpu) { -+ if (of_get_cpu_node(cpu, NULL) == cpu_node) { -+ cpumask_set_cpu(cpu, &ctrl->irq_affinity_mask); -+ break; -+ } -+ } -+ of_node_put(cpu_node); -+ } -+ -+ return 0; -+} -+ -+static int cpr3_panic_notifier_init(struct cpr3_controller *ctrl) -+{ -+ struct device_node *node = ctrl->dev->of_node; -+ struct cpr3_panic_regs_info *panic_regs_info; -+ struct cpr3_reg_info *regs; -+ int i, reg_count, len, rc = 0; -+ -+ if (!of_find_property(node, "qcom,cpr-panic-reg-addr-list", &len)) { -+ /* panic register address list not specified */ -+ return rc; -+ } -+ -+ reg_count = len / sizeof(u32); -+ if (!reg_count) { -+ cpr3_err(ctrl, "qcom,cpr-panic-reg-addr-list has invalid len = %d\n", -+ len); -+ return -EINVAL; -+ } -+ -+ if (!of_find_property(node, "qcom,cpr-panic-reg-name-list", NULL)) { -+ cpr3_err(ctrl, "property qcom,cpr-panic-reg-name-list not specified\n"); -+ return -EINVAL; -+ } -+ -+ len = of_property_count_strings(node, "qcom,cpr-panic-reg-name-list"); -+ if (reg_count != len) { -+ cpr3_err(ctrl, "qcom,cpr-panic-reg-name-list should have %d strings\n", -+ reg_count); -+ return -EINVAL; -+ } -+ -+ panic_regs_info = devm_kzalloc(ctrl->dev, sizeof(*panic_regs_info), -+ GFP_KERNEL); -+ if (!panic_regs_info) -+ return -ENOMEM; -+ -+ regs = devm_kcalloc(ctrl->dev, reg_count, sizeof(*regs), GFP_KERNEL); -+ if (!regs) -+ return -ENOMEM; -+ -+ for (i = 0; i < reg_count; i++) { -+ rc = of_property_read_string_index(node, -+ "qcom,cpr-panic-reg-name-list", i, -+ &(regs[i].name)); -+ if (rc) { -+ cpr3_err(ctrl, "error reading property qcom,cpr-panic-reg-name-list, rc=%d\n", -+ rc); -+ return rc; -+ } -+ -+ rc = of_property_read_u32_index(node, -+ "qcom,cpr-panic-reg-addr-list", i, -+ &(regs[i].addr)); -+ if (rc) { -+ cpr3_err(ctrl, "error reading property qcom,cpr-panic-reg-addr-list, rc=%d\n", -+ rc); -+ return rc; -+ } -+ regs[i].virt_addr = devm_ioremap(ctrl->dev, regs[i].addr, 0x4); -+ if (!regs[i].virt_addr) { -+ pr_err("Unable to map panic register addr 0x%08x\n", -+ regs[i].addr); -+ return -EINVAL; -+ } -+ regs[i].value = 0xFFFFFFFF; -+ } -+ -+ panic_regs_info->reg_count = reg_count; -+ panic_regs_info->regs = regs; -+ ctrl->panic_regs_info = panic_regs_info; -+ -+ return rc; -+} -+ -+/** -+ * cpr3_parse_common_ctrl_data() - parse common CPR3 controller properties from -+ * device tree -+ * @ctrl: Pointer to the CPR3 controller -+ * -+ * Return: 0 on success, errno on failure -+ */ -+int cpr3_parse_common_ctrl_data(struct cpr3_controller *ctrl) -+{ -+ int rc; -+ -+ rc = cpr3_parse_ctrl_u32(ctrl, "qcom,cpr-sensor-time", -+ &ctrl->sensor_time, 0, UINT_MAX); -+ if (rc) -+ return rc; -+ -+ rc = cpr3_parse_ctrl_u32(ctrl, "qcom,cpr-loop-time", -+ &ctrl->loop_time, 0, UINT_MAX); -+ if (rc) -+ return rc; -+ -+ rc = cpr3_parse_ctrl_u32(ctrl, "qcom,cpr-idle-cycles", -+ &ctrl->idle_clocks, CPR3_IDLE_CLOCKS_MIN, -+ CPR3_IDLE_CLOCKS_MAX); -+ if (rc) -+ return rc; -+ -+ rc = cpr3_parse_ctrl_u32(ctrl, "qcom,cpr-step-quot-init-min", -+ &ctrl->step_quot_init_min, CPR3_STEP_QUOT_MIN, -+ CPR3_STEP_QUOT_MAX); -+ if (rc) -+ return rc; -+ -+ rc = cpr3_parse_ctrl_u32(ctrl, "qcom,cpr-step-quot-init-max", -+ &ctrl->step_quot_init_max, CPR3_STEP_QUOT_MIN, -+ CPR3_STEP_QUOT_MAX); -+ if (rc) -+ return rc; -+ -+ rc = of_property_read_u32(ctrl->dev->of_node, "qcom,voltage-step", -+ &ctrl->step_volt); -+ if (rc) { -+ cpr3_err(ctrl, "error reading property qcom,voltage-step, rc=%d\n", -+ rc); -+ return rc; -+ } -+ if (ctrl->step_volt <= 0) { -+ cpr3_err(ctrl, "qcom,voltage-step=%d is invalid\n", -+ ctrl->step_volt); -+ return -EINVAL; -+ } -+ -+ rc = cpr3_parse_ctrl_u32(ctrl, "qcom,cpr-count-mode", -+ &ctrl->count_mode, CPR3_COUNT_MODE_ALL_AT_ONCE_MIN, -+ CPR3_COUNT_MODE_STAGGERED); -+ if (rc) -+ return rc; -+ -+ /* Count repeat is optional */ -+ ctrl->count_repeat = 0; -+ of_property_read_u32(ctrl->dev->of_node, "qcom,cpr-count-repeat", -+ &ctrl->count_repeat); -+ -+ ctrl->cpr_allowed_sw = -+ of_property_read_bool(ctrl->dev->of_node, "qcom,cpr-enable") || -+ ctrl->cpr_global_setting == CPR_CLOSED_LOOP_EN; -+ -+ rc = cpr3_parse_irq_affinity(ctrl); -+ if (rc) -+ return rc; -+ -+ /* Aging reference voltage is optional */ -+ ctrl->aging_ref_volt = 0; -+ of_property_read_u32(ctrl->dev->of_node, "qcom,cpr-aging-ref-voltage", -+ &ctrl->aging_ref_volt); -+ -+ /* Aging possible bitmask is optional */ -+ ctrl->aging_possible_mask = 0; -+ of_property_read_u32(ctrl->dev->of_node, -+ "qcom,cpr-aging-allowed-reg-mask", -+ &ctrl->aging_possible_mask); -+ -+ if (ctrl->aging_possible_mask) { -+ /* -+ * Aging possible register value required if bitmask is -+ * specified -+ */ -+ rc = cpr3_parse_ctrl_u32(ctrl, -+ "qcom,cpr-aging-allowed-reg-value", -+ &ctrl->aging_possible_val, 0, UINT_MAX); -+ if (rc) -+ return rc; -+ } -+ -+ if (of_find_property(ctrl->dev->of_node, "clock-names", NULL)) { -+ ctrl->core_clk = devm_clk_get(ctrl->dev, "core_clk"); -+ if (IS_ERR(ctrl->core_clk)) { -+ rc = PTR_ERR(ctrl->core_clk); -+ if (rc != -EPROBE_DEFER) -+ cpr3_err(ctrl, "unable request core clock, rc=%d\n", -+ rc); -+ return rc; -+ } -+ } -+ -+ rc = cpr3_panic_notifier_init(ctrl); -+ if (rc) -+ return rc; -+ -+ if (of_find_property(ctrl->dev->of_node, "vdd-supply", NULL)) { -+ ctrl->vdd_regulator = devm_regulator_get(ctrl->dev, "vdd"); -+ if (IS_ERR(ctrl->vdd_regulator)) { -+ rc = PTR_ERR(ctrl->vdd_regulator); -+ if (rc != -EPROBE_DEFER) -+ cpr3_err(ctrl, "unable to request vdd regulator, rc=%d\n", -+ rc); -+ return rc; -+ } -+ } else { -+ cpr3_err(ctrl, "vdd supply is not defined\n"); -+ return -ENODEV; -+ } -+ -+ ctrl->system_regulator = devm_regulator_get_optional(ctrl->dev, -+ "system"); -+ if (IS_ERR(ctrl->system_regulator)) { -+ rc = PTR_ERR(ctrl->system_regulator); -+ if (rc != -EPROBE_DEFER) { -+ rc = 0; -+ ctrl->system_regulator = NULL; -+ } else { -+ return rc; -+ } -+ } -+ -+ ctrl->mem_acc_regulator = devm_regulator_get_optional(ctrl->dev, -+ "mem-acc"); -+ if (IS_ERR(ctrl->mem_acc_regulator)) { -+ rc = PTR_ERR(ctrl->mem_acc_regulator); -+ if (rc != -EPROBE_DEFER) { -+ rc = 0; -+ ctrl->mem_acc_regulator = NULL; -+ } else { -+ return rc; -+ } -+ } -+ -+ return rc; -+} -+ -+/** -+ * cpr3_parse_open_loop_common_ctrl_data() - parse common open loop CPR3 -+ * controller properties from device tree -+ * @ctrl: Pointer to the CPR3 controller -+ * -+ * Return: 0 on success, errno on failure -+ */ -+int cpr3_parse_open_loop_common_ctrl_data(struct cpr3_controller *ctrl) -+{ -+ int rc; -+ -+ rc = of_property_read_u32(ctrl->dev->of_node, "qcom,voltage-step", -+ &ctrl->step_volt); -+ if (rc) { -+ cpr3_err(ctrl, "error reading property qcom,voltage-step, rc=%d\n", -+ rc); -+ return rc; -+ } -+ -+ if (ctrl->step_volt <= 0) { -+ cpr3_err(ctrl, "qcom,voltage-step=%d is invalid\n", -+ ctrl->step_volt); -+ return -EINVAL; -+ } -+ -+ if (of_find_property(ctrl->dev->of_node, "vdd-supply", NULL)) { -+ ctrl->vdd_regulator = devm_regulator_get(ctrl->dev, "vdd"); -+ if (IS_ERR(ctrl->vdd_regulator)) { -+ rc = PTR_ERR(ctrl->vdd_regulator); -+ if (rc != -EPROBE_DEFER) -+ cpr3_err(ctrl, "unable to request vdd regulator, rc=%d\n", -+ rc); -+ return rc; -+ } -+ } else { -+ cpr3_err(ctrl, "vdd supply is not defined\n"); -+ return -ENODEV; -+ } -+ -+ ctrl->system_regulator = devm_regulator_get_optional(ctrl->dev, -+ "system"); -+ if (IS_ERR(ctrl->system_regulator)) { -+ rc = PTR_ERR(ctrl->system_regulator); -+ if (rc != -EPROBE_DEFER) { -+ rc = 0; -+ ctrl->system_regulator = NULL; -+ } else { -+ return rc; -+ } -+ } else { -+ rc = regulator_enable(ctrl->system_regulator); -+ } -+ -+ ctrl->mem_acc_regulator = devm_regulator_get_optional(ctrl->dev, -+ "mem-acc"); -+ if (IS_ERR(ctrl->mem_acc_regulator)) { -+ rc = PTR_ERR(ctrl->mem_acc_regulator); -+ if (rc != -EPROBE_DEFER) { -+ rc = 0; -+ ctrl->mem_acc_regulator = NULL; -+ } else { -+ return rc; -+ } -+ } -+ -+ return rc; -+} -+ -+/** -+ * cpr3_limit_open_loop_voltages() - modify the open-loop voltage of each corner -+ * so that it fits within the floor to ceiling -+ * voltage range of the corner -+ * @vreg: Pointer to the CPR3 regulator -+ * -+ * This function clips the open-loop voltage for each corner so that it is -+ * limited to the floor to ceiling range. It also rounds each open-loop voltage -+ * so that it corresponds to a set point available to the underlying regulator. -+ * -+ * Return: 0 on success, errno on failure -+ */ -+int cpr3_limit_open_loop_voltages(struct cpr3_regulator *vreg) -+{ -+ int i, volt; -+ -+ cpr3_debug(vreg, "open-loop voltages after trimming and rounding:\n"); -+ for (i = 0; i < vreg->corner_count; i++) { -+ volt = CPR3_ROUND(vreg->corner[i].open_loop_volt, -+ vreg->thread->ctrl->step_volt); -+ if (volt < vreg->corner[i].floor_volt) -+ volt = vreg->corner[i].floor_volt; -+ else if (volt > vreg->corner[i].ceiling_volt) -+ volt = vreg->corner[i].ceiling_volt; -+ vreg->corner[i].open_loop_volt = volt; -+ cpr3_debug(vreg, "corner[%2d]: open-loop=%d uV\n", i, volt); -+ } -+ -+ return 0; -+} -+ -+/** -+ * cpr3_open_loop_voltage_as_ceiling() - configures the ceiling voltage for each -+ * corner to equal the open-loop voltage if the relevant device -+ * tree property is found for the CPR3 regulator -+ * @vreg: Pointer to the CPR3 regulator -+ * -+ * This function assumes that the the open-loop voltage for each corner has -+ * already been rounded to the nearest allowed set point and that it falls -+ * within the floor to ceiling range. -+ * -+ * Return: none -+ */ -+void cpr3_open_loop_voltage_as_ceiling(struct cpr3_regulator *vreg) -+{ -+ int i; -+ -+ if (!of_property_read_bool(vreg->of_node, -+ "qcom,cpr-scaled-open-loop-voltage-as-ceiling")) -+ return; -+ -+ for (i = 0; i < vreg->corner_count; i++) -+ vreg->corner[i].ceiling_volt -+ = vreg->corner[i].open_loop_volt; -+} -+ -+/** -+ * cpr3_limit_floor_voltages() - raise the floor voltage of each corner so that -+ * the optional maximum floor to ceiling voltage range specified in -+ * device tree is satisfied -+ * @vreg: Pointer to the CPR3 regulator -+ * -+ * This function also ensures that the open-loop voltage for each corner falls -+ * within the final floor to ceiling voltage range and that floor voltages -+ * increase monotonically. -+ * -+ * Return: 0 on success, errno on failure -+ */ -+int cpr3_limit_floor_voltages(struct cpr3_regulator *vreg) -+{ -+ char *prop = "qcom,cpr-floor-to-ceiling-max-range"; -+ int i, floor_new; -+ u32 *floor_range; -+ int rc = 0; -+ -+ if (!of_find_property(vreg->of_node, prop, NULL)) -+ goto enforce_monotonicity; -+ -+ floor_range = kcalloc(vreg->corner_count, sizeof(*floor_range), -+ GFP_KERNEL); -+ if (!floor_range) -+ return -ENOMEM; -+ -+ rc = cpr3_parse_corner_array_property(vreg, prop, 1, floor_range); -+ if (rc) -+ goto free_floor_adjust; -+ -+ for (i = 0; i < vreg->corner_count; i++) { -+ if ((s32)floor_range[i] >= 0) { -+ floor_new = CPR3_ROUND(vreg->corner[i].ceiling_volt -+ - floor_range[i], -+ vreg->thread->ctrl->step_volt); -+ -+ vreg->corner[i].floor_volt = max(floor_new, -+ vreg->corner[i].floor_volt); -+ if (vreg->corner[i].open_loop_volt -+ < vreg->corner[i].floor_volt) -+ vreg->corner[i].open_loop_volt -+ = vreg->corner[i].floor_volt; -+ } -+ } -+ -+free_floor_adjust: -+ kfree(floor_range); -+ -+enforce_monotonicity: -+ /* Ensure that floor voltages increase monotonically. */ -+ for (i = 1; i < vreg->corner_count; i++) { -+ if (vreg->corner[i].floor_volt -+ < vreg->corner[i - 1].floor_volt) { -+ cpr3_debug(vreg, "corner %d floor voltage=%d uV < corner %d voltage=%d uV; overriding: corner %d voltage=%d\n", -+ i, vreg->corner[i].floor_volt, -+ i - 1, vreg->corner[i - 1].floor_volt, -+ i, vreg->corner[i - 1].floor_volt); -+ vreg->corner[i].floor_volt -+ = vreg->corner[i - 1].floor_volt; -+ -+ if (vreg->corner[i].open_loop_volt -+ < vreg->corner[i].floor_volt) -+ vreg->corner[i].open_loop_volt -+ = vreg->corner[i].floor_volt; -+ if (vreg->corner[i].ceiling_volt -+ < vreg->corner[i].floor_volt) -+ vreg->corner[i].ceiling_volt -+ = vreg->corner[i].floor_volt; -+ } -+ } -+ -+ return rc; -+} -+ -+/** -+ * cpr3_print_quots() - print CPR target quotients into the kernel log for -+ * debugging purposes -+ * @vreg: Pointer to the CPR3 regulator -+ * -+ * Return: none -+ */ -+void cpr3_print_quots(struct cpr3_regulator *vreg) -+{ -+ int i, j, pos; -+ size_t buflen; -+ char *buf; -+ -+ buflen = sizeof(*buf) * CPR3_RO_COUNT * (MAX_CHARS_PER_INT + 2); -+ buf = kzalloc(buflen, GFP_KERNEL); -+ if (!buf) -+ return; -+ -+ for (i = 0; i < vreg->corner_count; i++) { -+ for (j = 0, pos = 0; j < CPR3_RO_COUNT; j++) -+ pos += scnprintf(buf + pos, buflen - pos, " %u", -+ vreg->corner[i].target_quot[j]); -+ cpr3_debug(vreg, "target quots[%2d]:%s\n", i, buf); -+ } -+ -+ kfree(buf); -+} -+ -+/** -+ * cpr3_determine_part_type() - determine the part type (SS/TT/FF). -+ * -+ * qcom,cpr-part-types prop tells the number of part types for which correction -+ * voltages are different. Another prop qcom,cpr-parts-voltage will contain the -+ * open loop fuse voltage which will be compared with this part voltage -+ * and accordingly part type will de determined. -+ * -+ * if qcom,cpr-part-types has value n, then qcom,cpr-parts-voltage will be -+ * array of n - 1 elements which will contain the voltage in increasing order. -+ * This function compares the fused volatge with all these voltage and returns -+ * the first index for which the fused volatge is greater. -+ * -+ * @vreg: Pointer to the CPR3 regulator -+ * @fuse_volt: fused open loop voltage which will be compared with -+ * qcom,cpr-parts-voltage array -+ * -+ * Return: 0 on success, errno on failure -+ */ -+int cpr3_determine_part_type(struct cpr3_regulator *vreg, int fuse_volt) -+{ -+ int i, rc, len; -+ u32 volt; -+ int soc_version_major; -+ char prop_name[100]; -+ const char prop_name_def[] = "qcom,cpr-parts-voltage"; -+ const char prop_name_v2[] = "qcom,cpr-parts-voltage-v2"; -+ -+ soc_version_major = read_ipq_soc_version_major(); -+ BUG_ON(soc_version_major <= 0); -+ -+ if (of_property_read_u32(vreg->of_node, "qcom,cpr-part-types", -+ &vreg->part_type_supported)) -+ return 0; -+ -+ if (soc_version_major > 1) -+ strlcpy(prop_name, prop_name_v2, sizeof(prop_name_v2)); -+ else -+ strlcpy(prop_name, prop_name_def, sizeof(prop_name_def)); -+ -+ if (!of_find_property(vreg->of_node, prop_name, &len)) { -+ cpr3_err(vreg, "property %s is missing\n", prop_name); -+ return -EINVAL; -+ } -+ -+ if (len != (vreg->part_type_supported - 1) * sizeof(u32)) { -+ cpr3_err(vreg, "wrong len in qcom,cpr-parts-voltage\n"); -+ return -EINVAL; -+ } -+ -+ for (i = 0; i < vreg->part_type_supported - 1; i++) { -+ rc = of_property_read_u32_index(vreg->of_node, -+ prop_name, i, &volt); -+ if (rc) { -+ cpr3_err(vreg, "error reading property %s, rc=%d\n", -+ prop_name, rc); -+ return rc; -+ } -+ -+ if (fuse_volt < volt) -+ break; -+ } -+ -+ vreg->part_type = i; -+ return 0; -+} -+ -+int cpr3_determine_temp_base_open_loop_correction(struct cpr3_regulator *vreg, -+ int *fuse_volt) -+{ -+ int i, rc, prev_volt; -+ int *volt_adjust; -+ char prop_str[75]; -+ int soc_version_major = read_ipq_soc_version_major(); -+ -+ BUG_ON(soc_version_major <= 0); -+ -+ if (vreg->part_type_supported) { -+ if (soc_version_major > 1) -+ snprintf(prop_str, sizeof(prop_str), -+ "qcom,cpr-cold-temp-voltage-adjustment-v2-%d", -+ vreg->part_type); -+ else -+ snprintf(prop_str, sizeof(prop_str), -+ "qcom,cpr-cold-temp-voltage-adjustment-%d", -+ vreg->part_type); -+ } else { -+ strlcpy(prop_str, "qcom,cpr-cold-temp-voltage-adjustment", -+ sizeof(prop_str)); -+ } -+ -+ if (!of_find_property(vreg->of_node, prop_str, NULL)) { -+ /* No adjustment required. */ -+ cpr3_info(vreg, "No cold temperature adjustment required.\n"); -+ return 0; -+ } -+ -+ volt_adjust = kcalloc(vreg->fuse_corner_count, sizeof(*volt_adjust), -+ GFP_KERNEL); -+ if (!volt_adjust) -+ return -ENOMEM; -+ -+ rc = cpr3_parse_array_property(vreg, prop_str, -+ vreg->fuse_corner_count, volt_adjust); -+ if (rc) { -+ cpr3_err(vreg, "could not load cold temp voltage adjustments, rc=%d\n", -+ rc); -+ goto done; -+ } -+ -+ for (i = 0; i < vreg->fuse_corner_count; i++) { -+ if (volt_adjust[i]) { -+ prev_volt = fuse_volt[i]; -+ fuse_volt[i] += volt_adjust[i]; -+ cpr3_debug(vreg, -+ "adjusted fuse corner %d open-loop voltage: %d -> %d uV\n", -+ i, prev_volt, fuse_volt[i]); -+ } -+ } -+ -+done: -+ kfree(volt_adjust); -+ return rc; -+} -+ -+/** -+ * cpr3_can_adjust_cold_temp() - Is cold temperature adjustment available -+ * -+ * @vreg: Pointer to the CPR3 regulator -+ * -+ * This function checks the cold temperature threshold is available -+ * -+ * Return: true on cold temperature threshold is available, else false -+ */ -+bool cpr3_can_adjust_cold_temp(struct cpr3_regulator *vreg) -+{ -+ char prop_str[75]; -+ int soc_version_major = read_ipq_soc_version_major(); -+ -+ BUG_ON(soc_version_major <= 0); -+ -+ if (soc_version_major > 1) -+ strlcpy(prop_str, "qcom,cpr-cold-temp-threshold-v2", -+ sizeof(prop_str)); -+ else -+ strlcpy(prop_str, "qcom,cpr-cold-temp-threshold", -+ sizeof(prop_str)); -+ -+ if (!of_find_property(vreg->of_node, prop_str, NULL)) { -+ /* No adjustment required. */ -+ return false; -+ } else -+ return true; -+} -+ -+/** -+ * cpr3_get_cold_temp_threshold() - get cold temperature threshold -+ * -+ * @vreg: Pointer to the CPR3 regulator -+ * @cold_temp: cold temperature read. -+ * -+ * This function reads the cold temperature threshold below which -+ * cold temperature adjustment margins will be applied. -+ * -+ * Return: 0 on success, errno on failure -+ */ -+int cpr3_get_cold_temp_threshold(struct cpr3_regulator *vreg, int *cold_temp) -+{ -+ int rc; -+ u32 temp; -+ char req_prop_str[75], prop_str[75]; -+ int soc_version_major = read_ipq_soc_version_major(); -+ -+ BUG_ON(soc_version_major <= 0); -+ -+ if (vreg->part_type_supported) { -+ if (soc_version_major > 1) -+ snprintf(req_prop_str, sizeof(req_prop_str), -+ "qcom,cpr-cold-temp-voltage-adjustment-v2-%d", -+ vreg->part_type); -+ else -+ snprintf(req_prop_str, sizeof(req_prop_str), -+ "qcom,cpr-cold-temp-voltage-adjustment-%d", -+ vreg->part_type); -+ } else { -+ strlcpy(req_prop_str, "qcom,cpr-cold-temp-voltage-adjustment", -+ sizeof(req_prop_str)); -+ } -+ -+ if (soc_version_major > 1) -+ strlcpy(prop_str, "qcom,cpr-cold-temp-threshold-v2", -+ sizeof(prop_str)); -+ else -+ strlcpy(prop_str, "qcom,cpr-cold-temp-threshold", -+ sizeof(prop_str)); -+ -+ if (!of_find_property(vreg->of_node, req_prop_str, NULL)) { -+ /* No adjustment required. */ -+ cpr3_info(vreg, "Cold temperature adjustment not required.\n"); -+ return 0; -+ } -+ -+ if (!of_find_property(vreg->of_node, prop_str, NULL)) { -+ /* No adjustment required. */ -+ cpr3_err(vreg, "Missing %s required for %s\n", -+ prop_str, req_prop_str); -+ return -EINVAL; -+ } -+ -+ rc = of_property_read_u32(vreg->of_node, prop_str, &temp); -+ if (rc) { -+ cpr3_err(vreg, "error reading property %s, rc=%d\n", -+ prop_str, rc); -+ return rc; -+ } -+ -+ *cold_temp = temp; -+ return 0; -+} -+ -+/** -+ * cpr3_adjust_fused_open_loop_voltages() - adjust the fused open-loop voltages -+ * for each fuse corner according to device tree values -+ * @vreg: Pointer to the CPR3 regulator -+ * @fuse_volt: Pointer to an array of the fused open-loop voltage -+ * values -+ * -+ * Voltage values in fuse_volt are modified in place. -+ * -+ * Return: 0 on success, errno on failure -+ */ -+int cpr3_adjust_fused_open_loop_voltages(struct cpr3_regulator *vreg, -+ int *fuse_volt) -+{ -+ int i, rc, prev_volt; -+ int *volt_adjust; -+ char prop_str[75]; -+ int soc_version_major = read_ipq_soc_version_major(); -+ -+ BUG_ON(soc_version_major <= 0); -+ -+ if (vreg->part_type_supported) { -+ if (soc_version_major > 1) -+ snprintf(prop_str, sizeof(prop_str), -+ "qcom,cpr-open-loop-voltage-fuse-adjustment-v2-%d", -+ vreg->part_type); -+ else -+ snprintf(prop_str, sizeof(prop_str), -+ "qcom,cpr-open-loop-voltage-fuse-adjustment-%d", -+ vreg->part_type); -+ } else { -+ strlcpy(prop_str, "qcom,cpr-open-loop-voltage-fuse-adjustment", -+ sizeof(prop_str)); -+ } -+ -+ if (!of_find_property(vreg->of_node, prop_str, NULL)) { -+ /* No adjustment required. */ -+ return 0; -+ } -+ -+ volt_adjust = kcalloc(vreg->fuse_corner_count, sizeof(*volt_adjust), -+ GFP_KERNEL); -+ if (!volt_adjust) -+ return -ENOMEM; -+ -+ rc = cpr3_parse_array_property(vreg, -+ prop_str, vreg->fuse_corner_count, volt_adjust); -+ if (rc) { -+ cpr3_err(vreg, "could not load open-loop fused voltage adjustments, rc=%d\n", -+ rc); -+ goto done; -+ } -+ -+ for (i = 0; i < vreg->fuse_corner_count; i++) { -+ if (volt_adjust[i]) { -+ prev_volt = fuse_volt[i]; -+ fuse_volt[i] += volt_adjust[i]; -+ cpr3_debug(vreg, "adjusted fuse corner %d open-loop voltage: %d --> %d uV\n", -+ i, prev_volt, fuse_volt[i]); -+ } -+ } -+ -+done: -+ kfree(volt_adjust); -+ return rc; -+} -+ -+/** -+ * cpr3_adjust_open_loop_voltages() - adjust the open-loop voltages for each -+ * corner according to device tree values -+ * @vreg: Pointer to the CPR3 regulator -+ * -+ * Return: 0 on success, errno on failure -+ */ -+int cpr3_adjust_open_loop_voltages(struct cpr3_regulator *vreg) -+{ -+ int i, rc, prev_volt, min_volt; -+ int *volt_adjust, *volt_diff; -+ -+ if (!of_find_property(vreg->of_node, -+ "qcom,cpr-open-loop-voltage-adjustment", NULL)) { -+ /* No adjustment required. */ -+ return 0; -+ } -+ -+ volt_adjust = kcalloc(vreg->corner_count, sizeof(*volt_adjust), -+ GFP_KERNEL); -+ volt_diff = kcalloc(vreg->corner_count, sizeof(*volt_diff), GFP_KERNEL); -+ if (!volt_adjust || !volt_diff) { -+ rc = -ENOMEM; -+ goto done; -+ } -+ -+ rc = cpr3_parse_corner_array_property(vreg, -+ "qcom,cpr-open-loop-voltage-adjustment", 1, volt_adjust); -+ if (rc) { -+ cpr3_err(vreg, "could not load open-loop voltage adjustments, rc=%d\n", -+ rc); -+ goto done; -+ } -+ -+ for (i = 0; i < vreg->corner_count; i++) { -+ if (volt_adjust[i]) { -+ prev_volt = vreg->corner[i].open_loop_volt; -+ vreg->corner[i].open_loop_volt += volt_adjust[i]; -+ cpr3_debug(vreg, "adjusted corner %d open-loop voltage: %d --> %d uV\n", -+ i, prev_volt, vreg->corner[i].open_loop_volt); -+ } -+ } -+ -+ if (of_find_property(vreg->of_node, -+ "qcom,cpr-open-loop-voltage-min-diff", NULL)) { -+ rc = cpr3_parse_corner_array_property(vreg, -+ "qcom,cpr-open-loop-voltage-min-diff", 1, volt_diff); -+ if (rc) { -+ cpr3_err(vreg, "could not load minimum open-loop voltage differences, rc=%d\n", -+ rc); -+ goto done; -+ } -+ } -+ -+ /* -+ * Ensure that open-loop voltages increase monotonically with respect -+ * to configurable minimum allowed differences. -+ */ -+ for (i = 1; i < vreg->corner_count; i++) { -+ min_volt = vreg->corner[i - 1].open_loop_volt + volt_diff[i]; -+ if (vreg->corner[i].open_loop_volt < min_volt) { -+ cpr3_debug(vreg, "adjusted corner %d open-loop voltage=%d uV < corner %d voltage=%d uV + min diff=%d uV; overriding: corner %d voltage=%d\n", -+ i, vreg->corner[i].open_loop_volt, -+ i - 1, vreg->corner[i - 1].open_loop_volt, -+ volt_diff[i], i, min_volt); -+ vreg->corner[i].open_loop_volt = min_volt; -+ } -+ } -+ -+done: -+ kfree(volt_diff); -+ kfree(volt_adjust); -+ return rc; -+} -+ -+/** -+ * cpr3_quot_adjustment() - returns the quotient adjustment value resulting from -+ * the specified voltage adjustment and RO scaling factor -+ * @ro_scale: The CPR ring oscillator (RO) scaling factor with units -+ * of QUOT/V -+ * @volt_adjust: The amount to adjust the voltage by in units of -+ * microvolts. This value may be positive or negative. -+ */ -+int cpr3_quot_adjustment(int ro_scale, int volt_adjust) -+{ -+ unsigned long long temp; -+ int quot_adjust; -+ int sign = 1; -+ -+ if (ro_scale < 0) { -+ sign = -sign; -+ ro_scale = -ro_scale; -+ } -+ -+ if (volt_adjust < 0) { -+ sign = -sign; -+ volt_adjust = -volt_adjust; -+ } -+ -+ temp = (unsigned long long)ro_scale * (unsigned long long)volt_adjust; -+ do_div(temp, 1000000); -+ -+ quot_adjust = temp; -+ quot_adjust *= sign; -+ -+ return quot_adjust; -+} -+ -+/** -+ * cpr3_voltage_adjustment() - returns the voltage adjustment value resulting -+ * from the specified quotient adjustment and RO scaling factor -+ * @ro_scale: The CPR ring oscillator (RO) scaling factor with units -+ * of QUOT/V -+ * @quot_adjust: The amount to adjust the quotient by in units of -+ * QUOT. This value may be positive or negative. -+ */ -+int cpr3_voltage_adjustment(int ro_scale, int quot_adjust) -+{ -+ unsigned long long temp; -+ int volt_adjust; -+ int sign = 1; -+ -+ if (ro_scale < 0) { -+ sign = -sign; -+ ro_scale = -ro_scale; -+ } -+ -+ if (quot_adjust < 0) { -+ sign = -sign; -+ quot_adjust = -quot_adjust; -+ } -+ -+ if (ro_scale == 0) -+ return 0; -+ -+ temp = (unsigned long long)quot_adjust * 1000000; -+ do_div(temp, ro_scale); -+ -+ volt_adjust = temp; -+ volt_adjust *= sign; -+ -+ return volt_adjust; -+} -+ -+/** -+ * cpr3_parse_closed_loop_voltage_adjustments() - load per-fuse-corner and -+ * per-corner closed-loop adjustment values from device tree -+ * @vreg: Pointer to the CPR3 regulator -+ * @ro_sel: Array of ring oscillator values selected for each -+ * fuse corner -+ * @volt_adjust: Pointer to array which will be filled with the -+ * per-corner closed-loop adjustment voltages -+ * @volt_adjust_fuse: Pointer to array which will be filled with the -+ * per-fuse-corner closed-loop adjustment voltages -+ * @ro_scale: Pointer to array which will be filled with the -+ * per-fuse-corner RO scaling factor values with units of -+ * QUOT/V -+ * -+ * Return: 0 on success, errno on failure -+ */ -+int cpr3_parse_closed_loop_voltage_adjustments( -+ struct cpr3_regulator *vreg, u64 *ro_sel, -+ int *volt_adjust, int *volt_adjust_fuse, int *ro_scale) -+{ -+ int i, rc; -+ u32 *ro_all_scale; -+ -+ char volt_adj[] = "qcom,cpr-closed-loop-voltage-adjustment"; -+ char volt_fuse_adj[] = "qcom,cpr-closed-loop-voltage-fuse-adjustment"; -+ char ro_scaling[] = "qcom,cpr-ro-scaling-factor"; -+ -+ if (!of_find_property(vreg->of_node, volt_adj, NULL) -+ && !of_find_property(vreg->of_node, volt_fuse_adj, NULL) -+ && !vreg->aging_allowed) { -+ /* No adjustment required. */ -+ return 0; -+ } else if (!of_find_property(vreg->of_node, ro_scaling, NULL)) { -+ cpr3_err(vreg, "Missing %s required for closed-loop voltage adjustment.\n", -+ ro_scaling); -+ return -EINVAL; -+ } -+ -+ ro_all_scale = kcalloc(vreg->fuse_corner_count * CPR3_RO_COUNT, -+ sizeof(*ro_all_scale), GFP_KERNEL); -+ if (!ro_all_scale) -+ return -ENOMEM; -+ -+ rc = cpr3_parse_array_property(vreg, ro_scaling, -+ vreg->fuse_corner_count * CPR3_RO_COUNT, ro_all_scale); -+ if (rc) { -+ cpr3_err(vreg, "could not load RO scaling factors, rc=%d\n", -+ rc); -+ goto done; -+ } -+ -+ for (i = 0; i < vreg->fuse_corner_count; i++) -+ ro_scale[i] = ro_all_scale[i * CPR3_RO_COUNT + ro_sel[i]]; -+ -+ for (i = 0; i < vreg->corner_count; i++) -+ memcpy(vreg->corner[i].ro_scale, -+ &ro_all_scale[vreg->corner[i].cpr_fuse_corner * CPR3_RO_COUNT], -+ sizeof(*ro_all_scale) * CPR3_RO_COUNT); -+ -+ if (of_find_property(vreg->of_node, volt_fuse_adj, NULL)) { -+ rc = cpr3_parse_array_property(vreg, volt_fuse_adj, -+ vreg->fuse_corner_count, volt_adjust_fuse); -+ if (rc) { -+ cpr3_err(vreg, "could not load closed-loop fused voltage adjustments, rc=%d\n", -+ rc); -+ goto done; -+ } -+ } -+ -+ if (of_find_property(vreg->of_node, volt_adj, NULL)) { -+ rc = cpr3_parse_corner_array_property(vreg, volt_adj, -+ 1, volt_adjust); -+ if (rc) { -+ cpr3_err(vreg, "could not load closed-loop voltage adjustments, rc=%d\n", -+ rc); -+ goto done; -+ } -+ } -+ -+done: -+ kfree(ro_all_scale); -+ return rc; -+} -+ -+/** -+ * cpr3_apm_init() - initialize APM data for a CPR3 controller -+ * @ctrl: Pointer to the CPR3 controller -+ * -+ * This function loads memory array power mux (APM) data from device tree -+ * if it is present and requests a handle to the appropriate APM controller -+ * device. -+ * -+ * Return: 0 on success, errno on failure -+ */ -+int cpr3_apm_init(struct cpr3_controller *ctrl) -+{ -+ struct device_node *node = ctrl->dev->of_node; -+ int rc; -+ -+ if (!of_find_property(node, "qcom,apm-ctrl", NULL)) { -+ /* No APM used */ -+ return 0; -+ } -+ -+ ctrl->apm = msm_apm_ctrl_dev_get(ctrl->dev); -+ if (IS_ERR(ctrl->apm)) { -+ rc = PTR_ERR(ctrl->apm); -+ if (rc != -EPROBE_DEFER) -+ cpr3_err(ctrl, "APM get failed, rc=%d\n", rc); -+ return rc; -+ } -+ -+ rc = of_property_read_u32(node, "qcom,apm-threshold-voltage", -+ &ctrl->apm_threshold_volt); -+ if (rc) { -+ cpr3_err(ctrl, "error reading qcom,apm-threshold-voltage, rc=%d\n", -+ rc); -+ return rc; -+ } -+ ctrl->apm_threshold_volt -+ = CPR3_ROUND(ctrl->apm_threshold_volt, ctrl->step_volt); -+ -+ /* No error check since this is an optional property. */ -+ of_property_read_u32(node, "qcom,apm-hysteresis-voltage", -+ &ctrl->apm_adj_volt); -+ ctrl->apm_adj_volt = CPR3_ROUND(ctrl->apm_adj_volt, ctrl->step_volt); -+ -+ ctrl->apm_high_supply = MSM_APM_SUPPLY_APCC; -+ ctrl->apm_low_supply = MSM_APM_SUPPLY_MX; -+ -+ return 0; -+} -+ -+/** -+ * cpr3_mem_acc_init() - initialize mem-acc regulator data for -+ * a CPR3 regulator -+ * @ctrl: Pointer to the CPR3 controller -+ * -+ * Return: 0 on success, errno on failure -+ */ -+int cpr3_mem_acc_init(struct cpr3_regulator *vreg) -+{ -+ struct cpr3_controller *ctrl = vreg->thread->ctrl; -+ u32 *temp; -+ int i, rc; -+ -+ if (!ctrl->mem_acc_regulator) { -+ cpr3_info(ctrl, "not using memory accelerator regulator\n"); -+ return 0; -+ } -+ -+ temp = kcalloc(vreg->corner_count, sizeof(*temp), GFP_KERNEL); -+ if (!temp) -+ return -ENOMEM; -+ -+ rc = cpr3_parse_corner_array_property(vreg, "qcom,mem-acc-voltage", -+ 1, temp); -+ if (rc) { -+ cpr3_err(ctrl, "could not load mem-acc corners, rc=%d\n", rc); -+ } else { -+ for (i = 0; i < vreg->corner_count; i++) -+ vreg->corner[i].mem_acc_volt = temp[i]; -+ } -+ -+ kfree(temp); -+ return rc; -+} -+ -+/** -+ * cpr4_load_core_and_temp_adj() - parse amount of voltage adjustment for -+ * per-online-core and per-temperature voltage adjustment for a -+ * given corner or corner band from device tree. -+ * @vreg: Pointer to the CPR3 regulator -+ * @num: Corner number or corner band number -+ * @use_corner_band: Boolean indicating if the CPR3 regulator supports -+ * adjustments per corner band -+ * -+ * Return: 0 on success, errno on failure -+ */ -+static int cpr4_load_core_and_temp_adj(struct cpr3_regulator *vreg, -+ int num, bool use_corner_band) -+{ -+ struct cpr3_controller *ctrl = vreg->thread->ctrl; -+ struct cpr4_sdelta *sdelta; -+ int sdelta_size, i, j, pos, rc = 0; -+ char str[75]; -+ size_t buflen; -+ char *buf; -+ -+ sdelta = use_corner_band ? vreg->corner_band[num].sdelta : -+ vreg->corner[num].sdelta; -+ -+ if (!sdelta->allow_core_count_adj && !sdelta->allow_temp_adj) { -+ /* corner doesn't need sdelta table */ -+ sdelta->max_core_count = 0; -+ sdelta->temp_band_count = 0; -+ return rc; -+ } -+ -+ sdelta_size = sdelta->max_core_count * sdelta->temp_band_count; -+ if (use_corner_band) -+ snprintf(str, sizeof(str), -+ "corner_band=%d core_config_count=%d temp_band_count=%d sdelta_size=%d\n", -+ num, sdelta->max_core_count, -+ sdelta->temp_band_count, sdelta_size); -+ else -+ snprintf(str, sizeof(str), -+ "corner=%d core_config_count=%d temp_band_count=%d sdelta_size=%d\n", -+ num, sdelta->max_core_count, -+ sdelta->temp_band_count, sdelta_size); -+ -+ cpr3_debug(vreg, "%s", str); -+ -+ sdelta->table = devm_kcalloc(ctrl->dev, sdelta_size, -+ sizeof(*sdelta->table), GFP_KERNEL); -+ if (!sdelta->table) -+ return -ENOMEM; -+ -+ if (use_corner_band) -+ snprintf(str, sizeof(str), -+ "qcom,cpr-corner-band%d-temp-core-voltage-adjustment", -+ num + CPR3_CORNER_OFFSET); -+ else -+ snprintf(str, sizeof(str), -+ "qcom,cpr-corner%d-temp-core-voltage-adjustment", -+ num + CPR3_CORNER_OFFSET); -+ -+ rc = cpr3_parse_array_property(vreg, str, sdelta_size, -+ sdelta->table); -+ if (rc) { -+ cpr3_err(vreg, "could not load %s, rc=%d\n", str, rc); -+ return rc; -+ } -+ -+ /* -+ * Convert sdelta margins from uV to PMIC steps and apply negation to -+ * follow the SDELTA register semantics. -+ */ -+ for (i = 0; i < sdelta_size; i++) -+ sdelta->table[i] = -(sdelta->table[i] / ctrl->step_volt); -+ -+ buflen = sizeof(*buf) * sdelta_size * (MAX_CHARS_PER_INT + 2); -+ buf = kzalloc(buflen, GFP_KERNEL); -+ if (!buf) -+ return rc; -+ -+ for (i = 0; i < sdelta->max_core_count; i++) { -+ for (j = 0, pos = 0; j < sdelta->temp_band_count; j++) -+ pos += scnprintf(buf + pos, buflen - pos, " %u", -+ sdelta->table[i * sdelta->temp_band_count + j]); -+ cpr3_debug(vreg, "sdelta[%d]:%s\n", i, buf); -+ } -+ -+ kfree(buf); -+ return rc; -+} -+ -+/** -+ * cpr4_parse_core_count_temp_voltage_adj() - parse configuration data for -+ * per-online-core and per-temperature voltage adjustment for -+ * a CPR3 regulator from device tree. -+ * @vreg: Pointer to the CPR3 regulator -+ * @use_corner_band: Boolean indicating if the CPR3 regulator supports -+ * adjustments per corner band -+ * -+ * This function supports parsing of per-online-core and per-temperature -+ * adjustments per corner or per corner band. CPR controllers which support -+ * corner bands apply the same adjustments to all corners within a corner band. -+ * -+ * Return: 0 on success, errno on failure -+ */ -+int cpr4_parse_core_count_temp_voltage_adj( -+ struct cpr3_regulator *vreg, bool use_corner_band) -+{ -+ struct cpr3_controller *ctrl = vreg->thread->ctrl; -+ struct device_node *node = vreg->of_node; -+ struct cpr3_corner *corner; -+ struct cpr4_sdelta *sdelta; -+ int i, sdelta_table_count, rc = 0; -+ int *allow_core_count_adj = NULL, *allow_temp_adj = NULL; -+ char prop_str[75]; -+ -+ if (of_find_property(node, use_corner_band ? -+ "qcom,corner-band-allow-temp-adjustment" -+ : "qcom,corner-allow-temp-adjustment", NULL)) { -+ if (!ctrl->allow_temp_adj) { -+ cpr3_err(ctrl, "Temperature adjustment configurations missing\n"); -+ return -EINVAL; -+ } -+ -+ vreg->allow_temp_adj = true; -+ } -+ -+ if (of_find_property(node, use_corner_band ? -+ "qcom,corner-band-allow-core-count-adjustment" -+ : "qcom,corner-allow-core-count-adjustment", -+ NULL)) { -+ rc = of_property_read_u32(node, "qcom,max-core-count", -+ &vreg->max_core_count); -+ if (rc) { -+ cpr3_err(vreg, "error reading qcom,max-core-count, rc=%d\n", -+ rc); -+ return -EINVAL; -+ } -+ -+ vreg->allow_core_count_adj = true; -+ ctrl->allow_core_count_adj = true; -+ } -+ -+ if (!vreg->allow_temp_adj && !vreg->allow_core_count_adj) { -+ /* -+ * Both per-online-core and temperature based adjustments are -+ * disabled for this regulator. -+ */ -+ return 0; -+ } else if (!vreg->allow_core_count_adj) { -+ /* -+ * Only per-temperature voltage adjusments are allowed. -+ * Keep max core count value as 1 to allocate SDELTA. -+ */ -+ vreg->max_core_count = 1; -+ } -+ -+ if (vreg->allow_core_count_adj) { -+ allow_core_count_adj = kcalloc(vreg->corner_count, -+ sizeof(*allow_core_count_adj), -+ GFP_KERNEL); -+ if (!allow_core_count_adj) -+ return -ENOMEM; -+ -+ snprintf(prop_str, sizeof(prop_str), "%s", use_corner_band ? -+ "qcom,corner-band-allow-core-count-adjustment" : -+ "qcom,corner-allow-core-count-adjustment"); -+ -+ rc = use_corner_band ? -+ cpr3_parse_corner_band_array_property(vreg, prop_str, -+ 1, allow_core_count_adj) : -+ cpr3_parse_corner_array_property(vreg, prop_str, -+ 1, allow_core_count_adj); -+ if (rc) { -+ cpr3_err(vreg, "error reading %s, rc=%d\n", prop_str, -+ rc); -+ goto done; -+ } -+ } -+ -+ if (vreg->allow_temp_adj) { -+ allow_temp_adj = kcalloc(vreg->corner_count, -+ sizeof(*allow_temp_adj), GFP_KERNEL); -+ if (!allow_temp_adj) { -+ rc = -ENOMEM; -+ goto done; -+ } -+ -+ snprintf(prop_str, sizeof(prop_str), "%s", use_corner_band ? -+ "qcom,corner-band-allow-temp-adjustment" : -+ "qcom,corner-allow-temp-adjustment"); -+ -+ rc = use_corner_band ? -+ cpr3_parse_corner_band_array_property(vreg, prop_str, -+ 1, allow_temp_adj) : -+ cpr3_parse_corner_array_property(vreg, prop_str, -+ 1, allow_temp_adj); -+ if (rc) { -+ cpr3_err(vreg, "error reading %s, rc=%d\n", prop_str, -+ rc); -+ goto done; -+ } -+ } -+ -+ sdelta_table_count = use_corner_band ? vreg->corner_band_count : -+ vreg->corner_count; -+ -+ for (i = 0; i < sdelta_table_count; i++) { -+ sdelta = devm_kzalloc(ctrl->dev, sizeof(*corner->sdelta), -+ GFP_KERNEL); -+ if (!sdelta) { -+ rc = -ENOMEM; -+ goto done; -+ } -+ -+ if (allow_core_count_adj) -+ sdelta->allow_core_count_adj = allow_core_count_adj[i]; -+ if (allow_temp_adj) -+ sdelta->allow_temp_adj = allow_temp_adj[i]; -+ sdelta->max_core_count = vreg->max_core_count; -+ sdelta->temp_band_count = ctrl->temp_band_count; -+ -+ if (use_corner_band) -+ vreg->corner_band[i].sdelta = sdelta; -+ else -+ vreg->corner[i].sdelta = sdelta; -+ -+ rc = cpr4_load_core_and_temp_adj(vreg, i, use_corner_band); -+ if (rc) { -+ cpr3_err(vreg, "corner/band %d core and temp adjustment loading failed, rc=%d\n", -+ i, rc); -+ goto done; -+ } -+ } -+ -+done: -+ kfree(allow_core_count_adj); -+ kfree(allow_temp_adj); -+ -+ return rc; -+} -+ -+/** -+ * cprh_adjust_voltages_for_apm() - adjust per-corner floor and ceiling voltages -+ * so that they do not overlap the APM threshold voltage. -+ * @vreg: Pointer to the CPR3 regulator -+ * -+ * The memory array power mux (APM) must be configured for a specific supply -+ * based upon where the VDD voltage lies with respect to the APM threshold -+ * voltage. When using CPR hardware closed-loop, the voltage may vary anywhere -+ * between the floor and ceiling voltage without software notification. -+ * Therefore, it is required that the floor to ceiling range for every corner -+ * not intersect the APM threshold voltage. This function adjusts the floor to -+ * ceiling range for each corner which violates this requirement. -+ * -+ * The following algorithm is applied: -+ * if floor < threshold <= ceiling: -+ * if open_loop >= threshold, then floor = threshold - adj -+ * else ceiling = threshold - step -+ * where: -+ * adj = APM hysteresis voltage established to minimize the number of -+ * corners with artificially increased floor voltages -+ * step = voltage in microvolts of a single step of the VDD supply -+ * -+ * The open-loop voltage is also bounded by the new floor or ceiling value as -+ * needed. -+ * -+ * Return: none -+ */ -+void cprh_adjust_voltages_for_apm(struct cpr3_regulator *vreg) -+{ -+ struct cpr3_controller *ctrl = vreg->thread->ctrl; -+ struct cpr3_corner *corner; -+ int i, adj, threshold, prev_ceiling, prev_floor, prev_open_loop; -+ -+ if (!ctrl->apm_threshold_volt) { -+ /* APM not being used. */ -+ return; -+ } -+ -+ ctrl->apm_threshold_volt = CPR3_ROUND(ctrl->apm_threshold_volt, -+ ctrl->step_volt); -+ ctrl->apm_adj_volt = CPR3_ROUND(ctrl->apm_adj_volt, ctrl->step_volt); -+ -+ threshold = ctrl->apm_threshold_volt; -+ adj = ctrl->apm_adj_volt; -+ -+ for (i = 0; i < vreg->corner_count; i++) { -+ corner = &vreg->corner[i]; -+ -+ if (threshold <= corner->floor_volt -+ || threshold > corner->ceiling_volt) -+ continue; -+ -+ prev_floor = corner->floor_volt; -+ prev_ceiling = corner->ceiling_volt; -+ prev_open_loop = corner->open_loop_volt; -+ -+ if (corner->open_loop_volt >= threshold) { -+ corner->floor_volt = max(corner->floor_volt, -+ threshold - adj); -+ if (corner->open_loop_volt < corner->floor_volt) -+ corner->open_loop_volt = corner->floor_volt; -+ } else { -+ corner->ceiling_volt = threshold - ctrl->step_volt; -+ } -+ -+ if (corner->floor_volt != prev_floor -+ || corner->ceiling_volt != prev_ceiling -+ || corner->open_loop_volt != prev_open_loop) -+ cpr3_debug(vreg, "APM threshold=%d, APM adj=%d changed corner %d voltages; prev: floor=%d, ceiling=%d, open-loop=%d; new: floor=%d, ceiling=%d, open-loop=%d\n", -+ threshold, adj, i, prev_floor, prev_ceiling, -+ prev_open_loop, corner->floor_volt, -+ corner->ceiling_volt, corner->open_loop_volt); -+ } -+} -+ -+/** -+ * cprh_adjust_voltages_for_mem_acc() - adjust per-corner floor and ceiling -+ * voltages so that they do not intersect the MEM ACC threshold -+ * voltage -+ * @vreg: Pointer to the CPR3 regulator -+ * -+ * The following algorithm is applied: -+ * if floor < threshold <= ceiling: -+ * if open_loop >= threshold, then floor = threshold -+ * else ceiling = threshold - step -+ * where: -+ * step = voltage in microvolts of a single step of the VDD supply -+ * -+ * The open-loop voltage is also bounded by the new floor or ceiling value as -+ * needed. -+ * -+ * Return: none -+ */ -+void cprh_adjust_voltages_for_mem_acc(struct cpr3_regulator *vreg) -+{ -+ struct cpr3_controller *ctrl = vreg->thread->ctrl; -+ struct cpr3_corner *corner; -+ int i, threshold, prev_ceiling, prev_floor, prev_open_loop; -+ -+ if (!ctrl->mem_acc_threshold_volt) { -+ /* MEM ACC not being used. */ -+ return; -+ } -+ -+ ctrl->mem_acc_threshold_volt = CPR3_ROUND(ctrl->mem_acc_threshold_volt, -+ ctrl->step_volt); -+ -+ threshold = ctrl->mem_acc_threshold_volt; -+ -+ for (i = 0; i < vreg->corner_count; i++) { -+ corner = &vreg->corner[i]; -+ -+ if (threshold <= corner->floor_volt -+ || threshold > corner->ceiling_volt) -+ continue; -+ -+ prev_floor = corner->floor_volt; -+ prev_ceiling = corner->ceiling_volt; -+ prev_open_loop = corner->open_loop_volt; -+ -+ if (corner->open_loop_volt >= threshold) { -+ corner->floor_volt = max(corner->floor_volt, threshold); -+ if (corner->open_loop_volt < corner->floor_volt) -+ corner->open_loop_volt = corner->floor_volt; -+ } else { -+ corner->ceiling_volt = threshold - ctrl->step_volt; -+ } -+ -+ if (corner->floor_volt != prev_floor -+ || corner->ceiling_volt != prev_ceiling -+ || corner->open_loop_volt != prev_open_loop) -+ cpr3_debug(vreg, "MEM ACC threshold=%d changed corner %d voltages; prev: floor=%d, ceiling=%d, open-loop=%d; new: floor=%d, ceiling=%d, open-loop=%d\n", -+ threshold, i, prev_floor, prev_ceiling, -+ prev_open_loop, corner->floor_volt, -+ corner->ceiling_volt, corner->open_loop_volt); -+ } -+} -+ -+/** -+ * cpr3_apply_closed_loop_offset_voltages() - modify the closed-loop voltage -+ * adjustments by the amounts that are needed for this -+ * fuse combo -+ * @vreg: Pointer to the CPR3 regulator -+ * @volt_adjust: Array of closed-loop voltage adjustment values of length -+ * vreg->corner_count which is further adjusted based upon -+ * offset voltage fuse values. -+ * @fuse_volt_adjust: Fused closed-loop voltage adjustment values of length -+ * vreg->fuse_corner_count. -+ * -+ * Return: 0 on success, errno on failure -+ */ -+static int cpr3_apply_closed_loop_offset_voltages(struct cpr3_regulator *vreg, -+ int *volt_adjust, int *fuse_volt_adjust) -+{ -+ u32 *corner_map; -+ int rc = 0, i; -+ -+ if (!of_find_property(vreg->of_node, -+ "qcom,cpr-fused-closed-loop-voltage-adjustment-map", NULL)) { -+ /* No closed-loop offset required. */ -+ return 0; -+ } -+ -+ corner_map = kcalloc(vreg->corner_count, sizeof(*corner_map), -+ GFP_KERNEL); -+ if (!corner_map) -+ return -ENOMEM; -+ -+ rc = cpr3_parse_corner_array_property(vreg, -+ "qcom,cpr-fused-closed-loop-voltage-adjustment-map", -+ 1, corner_map); -+ if (rc) -+ goto done; -+ -+ for (i = 0; i < vreg->corner_count; i++) { -+ if (corner_map[i] == 0) { -+ continue; -+ } else if (corner_map[i] > vreg->fuse_corner_count) { -+ cpr3_err(vreg, "corner %d mapped to invalid fuse corner: %u\n", -+ i, corner_map[i]); -+ rc = -EINVAL; -+ goto done; -+ } -+ -+ volt_adjust[i] += fuse_volt_adjust[corner_map[i] - 1]; -+ } -+ -+done: -+ kfree(corner_map); -+ return rc; -+} -+ -+/** -+ * cpr3_enforce_inc_quotient_monotonicity() - Ensure that target quotients -+ * increase monotonically from lower to higher corners -+ * @vreg: Pointer to the CPR3 regulator -+ * -+ * Return: 0 on success, errno on failure -+ */ -+static void cpr3_enforce_inc_quotient_monotonicity(struct cpr3_regulator *vreg) -+{ -+ int i, j; -+ -+ for (i = 1; i < vreg->corner_count; i++) { -+ for (j = 0; j < CPR3_RO_COUNT; j++) { -+ if (vreg->corner[i].target_quot[j] -+ && vreg->corner[i].target_quot[j] -+ < vreg->corner[i - 1].target_quot[j]) { -+ cpr3_debug(vreg, "corner %d RO%u target quot=%u < corner %d RO%u target quot=%u; overriding: corner %d RO%u target quot=%u\n", -+ i, j, -+ vreg->corner[i].target_quot[j], -+ i - 1, j, -+ vreg->corner[i - 1].target_quot[j], -+ i, j, -+ vreg->corner[i - 1].target_quot[j]); -+ vreg->corner[i].target_quot[j] -+ = vreg->corner[i - 1].target_quot[j]; -+ } -+ } -+ } -+} -+ -+/** -+ * cpr3_enforce_dec_quotient_monotonicity() - Ensure that target quotients -+ * decrease monotonically from higher to lower corners -+ * @vreg: Pointer to the CPR3 regulator -+ * -+ * Return: 0 on success, errno on failure -+ */ -+static void cpr3_enforce_dec_quotient_monotonicity(struct cpr3_regulator *vreg) -+{ -+ int i, j; -+ -+ for (i = vreg->corner_count - 2; i >= 0; i--) { -+ for (j = 0; j < CPR3_RO_COUNT; j++) { -+ if (vreg->corner[i + 1].target_quot[j] -+ && vreg->corner[i].target_quot[j] -+ > vreg->corner[i + 1].target_quot[j]) { -+ cpr3_debug(vreg, "corner %d RO%u target quot=%u > corner %d RO%u target quot=%u; overriding: corner %d RO%u target quot=%u\n", -+ i, j, -+ vreg->corner[i].target_quot[j], -+ i + 1, j, -+ vreg->corner[i + 1].target_quot[j], -+ i, j, -+ vreg->corner[i + 1].target_quot[j]); -+ vreg->corner[i].target_quot[j] -+ = vreg->corner[i + 1].target_quot[j]; -+ } -+ } -+ } -+} -+ -+/** -+ * _cpr3_adjust_target_quotients() - adjust the target quotients for each -+ * corner of the regulator according to input adjustment and -+ * scaling arrays -+ * @vreg: Pointer to the CPR3 regulator -+ * @volt_adjust: Pointer to an array of closed-loop voltage adjustments -+ * with units of microvolts. The array must have -+ * vreg->corner_count number of elements. -+ * @ro_scale: Pointer to a flattened 2D array of RO scaling factors. -+ * The array must have an inner dimension of CPR3_RO_COUNT -+ * and an outer dimension of vreg->corner_count -+ * @label: Null terminated string providing a label for the type -+ * of adjustment. -+ * -+ * Return: true if any corners received a positive voltage adjustment (> 0), -+ * else false -+ */ -+static bool _cpr3_adjust_target_quotients(struct cpr3_regulator *vreg, -+ const int *volt_adjust, const int *ro_scale, const char *label) -+{ -+ int i, j, quot_adjust; -+ bool is_increasing = false; -+ u32 prev_quot; -+ -+ for (i = 0; i < vreg->corner_count; i++) { -+ for (j = 0; j < CPR3_RO_COUNT; j++) { -+ if (vreg->corner[i].target_quot[j]) { -+ quot_adjust = cpr3_quot_adjustment( -+ ro_scale[i * CPR3_RO_COUNT + j], -+ volt_adjust[i]); -+ if (quot_adjust) { -+ prev_quot = vreg->corner[i]. -+ target_quot[j]; -+ vreg->corner[i].target_quot[j] -+ += quot_adjust; -+ cpr3_debug(vreg, "adjusted corner %d RO%d target quot %s: %u --> %u (%d uV)\n", -+ i, j, label, prev_quot, -+ vreg->corner[i].target_quot[j], -+ volt_adjust[i]); -+ } -+ } -+ } -+ if (volt_adjust[i] > 0) -+ is_increasing = true; -+ } -+ -+ return is_increasing; -+} -+ -+/** -+ * cpr3_adjust_target_quotients() - adjust the target quotients for each -+ * corner according to device tree values and fuse values -+ * @vreg: Pointer to the CPR3 regulator -+ * @fuse_volt_adjust: Fused closed-loop voltage adjustment values of length -+ * vreg->fuse_corner_count. This parameter could be null -+ * pointer when no fused adjustments are needed. -+ * -+ * Return: 0 on success, errno on failure -+ */ -+int cpr3_adjust_target_quotients(struct cpr3_regulator *vreg, -+ int *fuse_volt_adjust) -+{ -+ int i, rc; -+ int *volt_adjust, *ro_scale; -+ bool explicit_adjustment, fused_adjustment, is_increasing; -+ -+ explicit_adjustment = of_find_property(vreg->of_node, -+ "qcom,cpr-closed-loop-voltage-adjustment", NULL); -+ fused_adjustment = of_find_property(vreg->of_node, -+ "qcom,cpr-fused-closed-loop-voltage-adjustment-map", NULL); -+ -+ if (!explicit_adjustment && !fused_adjustment && !vreg->aging_allowed) { -+ /* No adjustment required. */ -+ return 0; -+ } else if (!of_find_property(vreg->of_node, -+ "qcom,cpr-ro-scaling-factor", NULL)) { -+ cpr3_err(vreg, "qcom,cpr-ro-scaling-factor is required for closed-loop voltage adjustment, but is missing\n"); -+ return -EINVAL; -+ } -+ -+ volt_adjust = kcalloc(vreg->corner_count, sizeof(*volt_adjust), -+ GFP_KERNEL); -+ ro_scale = kcalloc(vreg->corner_count * CPR3_RO_COUNT, -+ sizeof(*ro_scale), GFP_KERNEL); -+ if (!volt_adjust || !ro_scale) { -+ rc = -ENOMEM; -+ goto done; -+ } -+ -+ rc = cpr3_parse_corner_array_property(vreg, -+ "qcom,cpr-ro-scaling-factor", CPR3_RO_COUNT, ro_scale); -+ if (rc) { -+ cpr3_err(vreg, "could not load RO scaling factors, rc=%d\n", -+ rc); -+ goto done; -+ } -+ -+ for (i = 0; i < vreg->corner_count; i++) -+ memcpy(vreg->corner[i].ro_scale, &ro_scale[i * CPR3_RO_COUNT], -+ sizeof(*ro_scale) * CPR3_RO_COUNT); -+ -+ if (explicit_adjustment) { -+ rc = cpr3_parse_corner_array_property(vreg, -+ "qcom,cpr-closed-loop-voltage-adjustment", -+ 1, volt_adjust); -+ if (rc) { -+ cpr3_err(vreg, "could not load closed-loop voltage adjustments, rc=%d\n", -+ rc); -+ goto done; -+ } -+ -+ _cpr3_adjust_target_quotients(vreg, volt_adjust, ro_scale, -+ "from DT"); -+ cpr3_enforce_inc_quotient_monotonicity(vreg); -+ } -+ -+ if (fused_adjustment && fuse_volt_adjust) { -+ memset(volt_adjust, 0, -+ sizeof(*volt_adjust) * vreg->corner_count); -+ -+ rc = cpr3_apply_closed_loop_offset_voltages(vreg, volt_adjust, -+ fuse_volt_adjust); -+ if (rc) { -+ cpr3_err(vreg, "could not apply fused closed-loop voltage reductions, rc=%d\n", -+ rc); -+ goto done; -+ } -+ -+ is_increasing = _cpr3_adjust_target_quotients(vreg, volt_adjust, -+ ro_scale, "from fuse"); -+ if (is_increasing) -+ cpr3_enforce_inc_quotient_monotonicity(vreg); -+ else -+ cpr3_enforce_dec_quotient_monotonicity(vreg); -+ } -+ -+done: -+ kfree(volt_adjust); -+ kfree(ro_scale); -+ return rc; -+} ---- /dev/null -+++ b/drivers/regulator/cpr4-apss-regulator.c -@@ -0,0 +1,1819 @@ -+/* -+ * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 and -+ * only 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. -+ */ -+ -+#define pr_fmt(fmt) "%s: " fmt, __func__ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "cpr3-regulator.h" -+ -+#define IPQ807x_APSS_FUSE_CORNERS 4 -+#define IPQ817x_APPS_FUSE_CORNERS 2 -+#define IPQ6018_APSS_FUSE_CORNERS 4 -+#define IPQ9574_APSS_FUSE_CORNERS 4 -+ -+u32 g_valid_fuse_count = IPQ807x_APSS_FUSE_CORNERS; -+ -+/** -+ * struct cpr4_ipq807x_apss_fuses - APSS specific fuse data for IPQ807x -+ * @ro_sel: Ring oscillator select fuse parameter value for each -+ * fuse corner -+ * @init_voltage: Initial (i.e. open-loop) voltage fuse parameter value -+ * for each fuse corner (raw, not converted to a voltage) -+ * @target_quot: CPR target quotient fuse parameter value for each fuse -+ * corner -+ * @quot_offset: CPR target quotient offset fuse parameter value for each -+ * fuse corner (raw, not unpacked) used for target quotient -+ * interpolation -+ * @speed_bin: Application processor speed bin fuse parameter value for -+ * the given chip -+ * @cpr_fusing_rev: CPR fusing revision fuse parameter value -+ * @boost_cfg: CPR boost configuration fuse parameter value -+ * @boost_voltage: CPR boost voltage fuse parameter value (raw, not -+ * converted to a voltage) -+ * -+ * This struct holds the values for all of the fuses read from memory. -+ */ -+struct cpr4_ipq807x_apss_fuses { -+ u64 ro_sel[IPQ807x_APSS_FUSE_CORNERS]; -+ u64 init_voltage[IPQ807x_APSS_FUSE_CORNERS]; -+ u64 target_quot[IPQ807x_APSS_FUSE_CORNERS]; -+ u64 quot_offset[IPQ807x_APSS_FUSE_CORNERS]; -+ u64 speed_bin; -+ u64 cpr_fusing_rev; -+ u64 boost_cfg; -+ u64 boost_voltage; -+ u64 misc; -+}; -+ -+/* -+ * fuse combo = fusing revision + 8 * (speed bin) -+ * where: fusing revision = 0 - 7 and speed bin = 0 - 7 -+ */ -+#define CPR4_IPQ807x_APSS_FUSE_COMBO_COUNT 64 -+ -+/* -+ * Constants which define the name of each fuse corner. -+ */ -+enum cpr4_ipq807x_apss_fuse_corner { -+ CPR4_IPQ807x_APSS_FUSE_CORNER_SVS = 0, -+ CPR4_IPQ807x_APSS_FUSE_CORNER_NOM = 1, -+ CPR4_IPQ807x_APSS_FUSE_CORNER_TURBO = 2, -+ CPR4_IPQ807x_APSS_FUSE_CORNER_STURBO = 3, -+}; -+ -+static const char * const cpr4_ipq807x_apss_fuse_corner_name[] = { -+ [CPR4_IPQ807x_APSS_FUSE_CORNER_SVS] = "SVS", -+ [CPR4_IPQ807x_APSS_FUSE_CORNER_NOM] = "NOM", -+ [CPR4_IPQ807x_APSS_FUSE_CORNER_TURBO] = "TURBO", -+ [CPR4_IPQ807x_APSS_FUSE_CORNER_STURBO] = "STURBO", -+}; -+ -+/* -+ * IPQ807x APSS fuse parameter locations: -+ * -+ * Structs are organized with the following dimensions: -+ * Outer: 0 to 3 for fuse corners from lowest to highest corner -+ * Inner: large enough to hold the longest set of parameter segments which -+ * fully defines a fuse parameter, +1 (for NULL termination). -+ * Each segment corresponds to a contiguous group of bits from a -+ * single fuse row. These segments are concatentated together in -+ * order to form the full fuse parameter value. The segments for -+ * a given parameter may correspond to different fuse rows. -+ */ -+static struct cpr3_fuse_param -+ipq807x_apss_ro_sel_param[IPQ807x_APSS_FUSE_CORNERS][2] = { -+ {{73, 8, 11}, {} }, -+ {{73, 4, 7}, {} }, -+ {{73, 0, 3}, {} }, -+ {{73, 12, 15}, {} }, -+}; -+ -+static struct cpr3_fuse_param -+ipq807x_apss_init_voltage_param[IPQ807x_APSS_FUSE_CORNERS][2] = { -+ {{71, 18, 23}, {} }, -+ {{71, 12, 17}, {} }, -+ {{71, 6, 11}, {} }, -+ {{71, 0, 5}, {} }, -+}; -+ -+static struct cpr3_fuse_param -+ipq807x_apss_target_quot_param[IPQ807x_APSS_FUSE_CORNERS][2] = { -+ {{72, 32, 43}, {} }, -+ {{72, 20, 31}, {} }, -+ {{72, 8, 19}, {} }, -+ {{72, 44, 55}, {} }, -+}; -+ -+static struct cpr3_fuse_param -+ipq807x_apss_quot_offset_param[IPQ807x_APSS_FUSE_CORNERS][2] = { -+ {{} }, -+ {{71, 46, 52}, {} }, -+ {{71, 39, 45}, {} }, -+ {{71, 32, 38}, {} }, -+}; -+ -+static struct cpr3_fuse_param ipq807x_cpr_fusing_rev_param[] = { -+ {71, 53, 55}, -+ {}, -+}; -+ -+static struct cpr3_fuse_param ipq807x_apss_speed_bin_param[] = { -+ {36, 40, 42}, -+ {}, -+}; -+ -+static struct cpr3_fuse_param ipq807x_cpr_boost_fuse_cfg_param[] = { -+ {36, 43, 45}, -+ {}, -+}; -+ -+static struct cpr3_fuse_param ipq807x_apss_boost_fuse_volt_param[] = { -+ {71, 0, 5}, -+ {}, -+}; -+ -+static struct cpr3_fuse_param ipq807x_misc_fuse_volt_adj_param[] = { -+ {36, 54, 54}, -+ {}, -+}; -+ -+static struct cpr3_fuse_parameters ipq807x_fuse_params = { -+ .apss_ro_sel_param = ipq807x_apss_ro_sel_param, -+ .apss_init_voltage_param = ipq807x_apss_init_voltage_param, -+ .apss_target_quot_param = ipq807x_apss_target_quot_param, -+ .apss_quot_offset_param = ipq807x_apss_quot_offset_param, -+ .cpr_fusing_rev_param = ipq807x_cpr_fusing_rev_param, -+ .apss_speed_bin_param = ipq807x_apss_speed_bin_param, -+ .cpr_boost_fuse_cfg_param = ipq807x_cpr_boost_fuse_cfg_param, -+ .apss_boost_fuse_volt_param = ipq807x_apss_boost_fuse_volt_param, -+ .misc_fuse_volt_adj_param = ipq807x_misc_fuse_volt_adj_param -+}; -+ -+/* -+ * The number of possible values for misc fuse is -+ * 2^(#bits defined for misc fuse) -+ */ -+#define IPQ807x_MISC_FUSE_VAL_COUNT BIT(1) -+ -+/* -+ * Open loop voltage fuse reference voltages in microvolts for IPQ807x -+ */ -+static int ipq807x_apss_fuse_ref_volt -+ [IPQ807x_APSS_FUSE_CORNERS] = { -+ 720000, -+ 864000, -+ 992000, -+ 1064000, -+}; -+ -+#define IPQ807x_APSS_FUSE_STEP_VOLT 8000 -+#define IPQ807x_APSS_VOLTAGE_FUSE_SIZE 6 -+#define IPQ807x_APSS_QUOT_OFFSET_SCALE 5 -+ -+#define IPQ807x_APSS_CPR_SENSOR_COUNT 6 -+ -+#define IPQ807x_APSS_CPR_CLOCK_RATE 19200000 -+ -+#define IPQ807x_APSS_MAX_TEMP_POINTS 3 -+#define IPQ807x_APSS_TEMP_SENSOR_ID_START 4 -+#define IPQ807x_APSS_TEMP_SENSOR_ID_END 13 -+/* -+ * Boost voltage fuse reference and ceiling voltages in microvolts for -+ * IPQ807x. -+ */ -+#define IPQ807x_APSS_BOOST_FUSE_REF_VOLT 1140000 -+#define IPQ807x_APSS_BOOST_CEILING_VOLT 1140000 -+#define IPQ807x_APSS_BOOST_FLOOR_VOLT 900000 -+#define MAX_BOOST_CONFIG_FUSE_VALUE 8 -+ -+#define IPQ807x_APSS_CPR_SDELTA_CORE_COUNT 15 -+ -+#define IPQ807x_APSS_CPR_TCSR_START 8 -+#define IPQ807x_APSS_CPR_TCSR_END 9 -+ -+/* -+ * Array of integer values mapped to each of the boost config fuse values to -+ * indicate boost enable/disable status. -+ */ -+static bool boost_fuse[MAX_BOOST_CONFIG_FUSE_VALUE] = {0, 1, 1, 1, 1, 1, 1, 1}; -+ -+/* -+ * IPQ6018 (Few parameters are changed, remaining are same as IPQ807x) -+ */ -+#define IPQ6018_APSS_FUSE_STEP_VOLT 12500 -+#define IPQ6018_APSS_CPR_CLOCK_RATE 24000000 -+ -+static struct cpr3_fuse_param -+ipq6018_apss_ro_sel_param[IPQ6018_APSS_FUSE_CORNERS][2] = { -+ {{75, 8, 11}, {} }, -+ {{75, 4, 7}, {} }, -+ {{75, 0, 3}, {} }, -+ {{75, 12, 15}, {} }, -+}; -+ -+static struct cpr3_fuse_param -+ipq6018_apss_init_voltage_param[IPQ6018_APSS_FUSE_CORNERS][2] = { -+ {{73, 18, 23}, {} }, -+ {{73, 12, 17}, {} }, -+ {{73, 6, 11}, {} }, -+ {{73, 0, 5}, {} }, -+}; -+ -+static struct cpr3_fuse_param -+ipq6018_apss_target_quot_param[IPQ6018_APSS_FUSE_CORNERS][2] = { -+ {{74, 32, 43}, {} }, -+ {{74, 20, 31}, {} }, -+ {{74, 8, 19}, {} }, -+ {{74, 44, 55}, {} }, -+}; -+ -+static struct cpr3_fuse_param -+ipq6018_apss_quot_offset_param[IPQ6018_APSS_FUSE_CORNERS][2] = { -+ {{} }, -+ {{73, 48, 55}, {} }, -+ {{73, 40, 47}, {} }, -+ {{73, 32, 39}, {} }, -+}; -+ -+static struct cpr3_fuse_param ipq6018_cpr_fusing_rev_param[] = { -+ {75, 16, 18}, -+ {}, -+}; -+ -+static struct cpr3_fuse_param ipq6018_apss_speed_bin_param[] = { -+ {36, 40, 42}, -+ {}, -+}; -+ -+static struct cpr3_fuse_param ipq6018_cpr_boost_fuse_cfg_param[] = { -+ {36, 43, 45}, -+ {}, -+}; -+ -+static struct cpr3_fuse_param ipq6018_apss_boost_fuse_volt_param[] = { -+ {73, 0, 5}, -+ {}, -+}; -+ -+static struct cpr3_fuse_param ipq6018_misc_fuse_volt_adj_param[] = { -+ {36, 54, 54}, -+ {}, -+}; -+ -+static struct cpr3_fuse_parameters ipq6018_fuse_params = { -+ .apss_ro_sel_param = ipq6018_apss_ro_sel_param, -+ .apss_init_voltage_param = ipq6018_apss_init_voltage_param, -+ .apss_target_quot_param = ipq6018_apss_target_quot_param, -+ .apss_quot_offset_param = ipq6018_apss_quot_offset_param, -+ .cpr_fusing_rev_param = ipq6018_cpr_fusing_rev_param, -+ .apss_speed_bin_param = ipq6018_apss_speed_bin_param, -+ .cpr_boost_fuse_cfg_param = ipq6018_cpr_boost_fuse_cfg_param, -+ .apss_boost_fuse_volt_param = ipq6018_apss_boost_fuse_volt_param, -+ .misc_fuse_volt_adj_param = ipq6018_misc_fuse_volt_adj_param -+}; -+ -+ -+/* -+ * Boost voltage fuse reference and ceiling voltages in microvolts for -+ * IPQ6018. -+ */ -+#define IPQ6018_APSS_BOOST_FUSE_REF_VOLT 1140000 -+#define IPQ6018_APSS_BOOST_CEILING_VOLT 1140000 -+#define IPQ6018_APSS_BOOST_FLOOR_VOLT 900000 -+ -+/* -+ * Open loop voltage fuse reference voltages in microvolts for IPQ807x -+ */ -+static int ipq6018_apss_fuse_ref_volt -+ [IPQ6018_APSS_FUSE_CORNERS] = { -+ 725000, -+ 862500, -+ 987500, -+ 1062500, -+}; -+ -+/* -+ * IPQ6018 Memory ACC settings on TCSR -+ * -+ * Turbo_L1: write TCSR_MEM_ACC_SW_OVERRIDE_LEGACY_APC0 0x10 -+ * write TCSR_CUSTOM_VDDAPC0_ACC_1 0x1 -+ * Other modes: write TCSR_MEM_ACC_SW_OVERRIDE_LEGACY_APC0 0x0 -+ * write TCSR_CUSTOM_VDDAPC0_ACC_1 0x0 -+ * -+ */ -+#define IPQ6018_APSS_MEM_ACC_TCSR_COUNT 2 -+#define TCSR_MEM_ACC_SW_OVERRIDE_LEGACY_APC0 0x1946178 -+#define TCSR_CUSTOM_VDDAPC0_ACC_1 0x1946124 -+ -+struct mem_acc_tcsr { -+ u32 phy_addr; -+ void __iomem *ioremap_addr; -+ u32 value; -+}; -+ -+static struct mem_acc_tcsr ipq6018_mem_acc_tcsr[IPQ6018_APSS_MEM_ACC_TCSR_COUNT] = { -+ {TCSR_MEM_ACC_SW_OVERRIDE_LEGACY_APC0, NULL, 0x10}, -+ {TCSR_CUSTOM_VDDAPC0_ACC_1, NULL, 0x1}, -+}; -+ -+/* -+ * IPQ9574 (Few parameters are changed, remaining are same as IPQ6018) -+ */ -+#define IPQ9574_APSS_FUSE_STEP_VOLT 10000 -+ -+static struct cpr3_fuse_param -+ipq9574_apss_ro_sel_param[IPQ9574_APSS_FUSE_CORNERS][2] = { -+ {{107, 4, 7}, {} }, -+ {{107, 0, 3}, {} }, -+ {{106, 4, 7}, {} }, -+ {{106, 0, 3}, {} }, -+}; -+ -+static struct cpr3_fuse_param -+ipq9574_apss_init_voltage_param[IPQ9574_APSS_FUSE_CORNERS][2] = { -+ {{104, 24, 29}, {} }, -+ {{104, 18, 23}, {} }, -+ {{104, 12, 17}, {} }, -+ {{104, 6, 11}, {} }, -+}; -+ -+static struct cpr3_fuse_param -+ipq9574_apss_target_quot_param[IPQ9574_APSS_FUSE_CORNERS][2] = { -+ {{106, 32, 43}, {} }, -+ {{106, 20, 31}, {} }, -+ {{106, 8, 19}, {} }, -+ {{106, 44, 55}, {} }, -+}; -+ -+static struct cpr3_fuse_param -+ipq9574_apss_quot_offset_param[IPQ9574_APSS_FUSE_CORNERS][2] = { -+ {{} }, -+ {{105, 48, 55}, {} }, -+ {{105, 40, 47}, {} }, -+ {{105, 32, 39}, {} }, -+}; -+ -+static struct cpr3_fuse_param ipq9574_cpr_fusing_rev_param[] = { -+ {107, 8, 10}, -+ {}, -+}; -+ -+static struct cpr3_fuse_param ipq9574_apss_speed_bin_param[] = { -+ {0, 40, 42}, -+ {}, -+}; -+ -+static struct cpr3_fuse_param ipq9574_cpr_boost_fuse_cfg_param[] = { -+ {0, 43, 45}, -+ {}, -+}; -+ -+static struct cpr3_fuse_param ipq9574_apss_boost_fuse_volt_param[] = { -+ {104, 0, 5}, -+ {}, -+}; -+ -+static struct cpr3_fuse_param ipq9574_misc_fuse_volt_adj_param[] = { -+ {0, 54, 54}, -+ {}, -+}; -+ -+static struct cpr3_fuse_parameters ipq9574_fuse_params = { -+ .apss_ro_sel_param = ipq9574_apss_ro_sel_param, -+ .apss_init_voltage_param = ipq9574_apss_init_voltage_param, -+ .apss_target_quot_param = ipq9574_apss_target_quot_param, -+ .apss_quot_offset_param = ipq9574_apss_quot_offset_param, -+ .cpr_fusing_rev_param = ipq9574_cpr_fusing_rev_param, -+ .apss_speed_bin_param = ipq9574_apss_speed_bin_param, -+ .cpr_boost_fuse_cfg_param = ipq9574_cpr_boost_fuse_cfg_param, -+ .apss_boost_fuse_volt_param = ipq9574_apss_boost_fuse_volt_param, -+ .misc_fuse_volt_adj_param = ipq9574_misc_fuse_volt_adj_param -+}; -+ -+/* -+ * Open loop voltage fuse reference voltages in microvolts for IPQ9574 -+ */ -+static int ipq9574_apss_fuse_ref_volt -+ [IPQ9574_APSS_FUSE_CORNERS] = { -+ 725000, -+ 862500, -+ 987500, -+ 1062500, -+}; -+ -+/** -+ * cpr4_ipq807x_apss_read_fuse_data() - load APSS specific fuse parameter values -+ * @vreg: Pointer to the CPR3 regulator -+ * -+ * This function allocates a cpr4_ipq807x_apss_fuses struct, fills it with -+ * values read out of hardware fuses, and finally copies common fuse values -+ * into the CPR3 regulator struct. -+ * -+ * Return: 0 on success, errno on failure -+ */ -+static int cpr4_ipq807x_apss_read_fuse_data(struct cpr3_regulator *vreg) -+{ -+ void __iomem *base = vreg->thread->ctrl->fuse_base; -+ struct cpr4_ipq807x_apss_fuses *fuse; -+ int i, rc; -+ -+ fuse = devm_kzalloc(vreg->thread->ctrl->dev, sizeof(*fuse), GFP_KERNEL); -+ if (!fuse) -+ return -ENOMEM; -+ -+ rc = cpr3_read_fuse_param(base, vreg->cpr4_regulator_data->cpr3_fuse_params->apss_speed_bin_param, -+ &fuse->speed_bin); -+ if (rc) { -+ cpr3_err(vreg, "Unable to read speed bin fuse, rc=%d\n", rc); -+ return rc; -+ } -+ cpr3_info(vreg, "speed bin = %llu\n", fuse->speed_bin); -+ -+ rc = cpr3_read_fuse_param(base, vreg->cpr4_regulator_data->cpr3_fuse_params->cpr_fusing_rev_param, -+ &fuse->cpr_fusing_rev); -+ if (rc) { -+ cpr3_err(vreg, "Unable to read CPR fusing revision fuse, rc=%d\n", -+ rc); -+ return rc; -+ } -+ cpr3_info(vreg, "CPR fusing revision = %llu\n", fuse->cpr_fusing_rev); -+ -+ rc = cpr3_read_fuse_param(base, vreg->cpr4_regulator_data->cpr3_fuse_params->misc_fuse_volt_adj_param, -+ &fuse->misc); -+ if (rc) { -+ cpr3_err(vreg, "Unable to read misc voltage adjustment fuse, rc=%d\n", -+ rc); -+ return rc; -+ } -+ cpr3_info(vreg, "CPR misc fuse value = %llu\n", fuse->misc); -+ if (fuse->misc >= IPQ807x_MISC_FUSE_VAL_COUNT) { -+ cpr3_err(vreg, "CPR misc fuse value = %llu, should be < %lu\n", -+ fuse->misc, IPQ807x_MISC_FUSE_VAL_COUNT); -+ return -EINVAL; -+ } -+ -+ for (i = 0; i < g_valid_fuse_count; i++) { -+ rc = cpr3_read_fuse_param(base, -+ vreg->cpr4_regulator_data->cpr3_fuse_params->apss_init_voltage_param[i], -+ &fuse->init_voltage[i]); -+ if (rc) { -+ cpr3_err(vreg, "Unable to read fuse-corner %d initial voltage fuse, rc=%d\n", -+ i, rc); -+ return rc; -+ } -+ -+ rc = cpr3_read_fuse_param(base, -+ vreg->cpr4_regulator_data->cpr3_fuse_params->apss_target_quot_param[i], -+ &fuse->target_quot[i]); -+ if (rc) { -+ cpr3_err(vreg, "Unable to read fuse-corner %d target quotient fuse, rc=%d\n", -+ i, rc); -+ return rc; -+ } -+ -+ rc = cpr3_read_fuse_param(base, -+ vreg->cpr4_regulator_data->cpr3_fuse_params->apss_ro_sel_param[i], -+ &fuse->ro_sel[i]); -+ if (rc) { -+ cpr3_err(vreg, "Unable to read fuse-corner %d RO select fuse, rc=%d\n", -+ i, rc); -+ return rc; -+ } -+ -+ rc = cpr3_read_fuse_param(base, -+ vreg->cpr4_regulator_data->cpr3_fuse_params->apss_quot_offset_param[i], -+ &fuse->quot_offset[i]); -+ if (rc) { -+ cpr3_err(vreg, "Unable to read fuse-corner %d quotient offset fuse, rc=%d\n", -+ i, rc); -+ return rc; -+ } -+ } -+ -+ rc = cpr3_read_fuse_param(base, vreg->cpr4_regulator_data->cpr3_fuse_params->cpr_boost_fuse_cfg_param, -+ &fuse->boost_cfg); -+ if (rc) { -+ cpr3_err(vreg, "Unable to read CPR boost config fuse, rc=%d\n", -+ rc); -+ return rc; -+ } -+ cpr3_info(vreg, "Voltage boost fuse config = %llu boost = %s\n", -+ fuse->boost_cfg, boost_fuse[fuse->boost_cfg] -+ ? "enable" : "disable"); -+ -+ rc = cpr3_read_fuse_param(base, -+ vreg->cpr4_regulator_data->cpr3_fuse_params->apss_boost_fuse_volt_param, -+ &fuse->boost_voltage); -+ if (rc) { -+ cpr3_err(vreg, "failed to read boost fuse voltage, rc=%d\n", -+ rc); -+ return rc; -+ } -+ -+ vreg->fuse_combo = fuse->cpr_fusing_rev + 8 * fuse->speed_bin; -+ if (vreg->fuse_combo >= CPR4_IPQ807x_APSS_FUSE_COMBO_COUNT) { -+ cpr3_err(vreg, "invalid CPR fuse combo = %d found\n", -+ vreg->fuse_combo); -+ return -EINVAL; -+ } -+ -+ vreg->speed_bin_fuse = fuse->speed_bin; -+ vreg->cpr_rev_fuse = fuse->cpr_fusing_rev; -+ vreg->fuse_corner_count = g_valid_fuse_count; -+ vreg->platform_fuses = fuse; -+ -+ return 0; -+} -+ -+/** -+ * cpr4_apss_parse_corner_data() - parse APSS corner data from device tree -+ * properties of the CPR3 regulator's device node -+ * @vreg: Pointer to the CPR3 regulator -+ * -+ * Return: 0 on success, errno on failure -+ */ -+static int cpr4_apss_parse_corner_data(struct cpr3_regulator *vreg) -+{ -+ struct device_node *node = vreg->of_node; -+ struct cpr4_ipq807x_apss_fuses *fuse = vreg->platform_fuses; -+ u32 *temp = NULL; -+ int i, rc; -+ -+ rc = cpr3_parse_common_corner_data(vreg); -+ if (rc) { -+ cpr3_err(vreg, "error reading corner data, rc=%d\n", rc); -+ return rc; -+ } -+ -+ /* If fuse has incorrect RO Select values and dtsi has "qcom,cpr-ro-sel" -+ * entry with RO select values other than zero, then dtsi values will -+ * be used. -+ */ -+ if (of_find_property(node, "qcom,cpr-ro-sel", NULL)) { -+ temp = kcalloc(vreg->fuse_corner_count, sizeof(*temp), -+ GFP_KERNEL); -+ if (!temp) -+ return -ENOMEM; -+ -+ rc = cpr3_parse_array_property(vreg, "qcom,cpr-ro-sel", -+ vreg->fuse_corner_count, temp); -+ if (rc) -+ goto done; -+ -+ for (i = 0; i < vreg->fuse_corner_count; i++) { -+ if (temp[i] != 0) -+ fuse->ro_sel[i] = temp[i]; -+ } -+ } -+done: -+ kfree(temp); -+ return rc; -+} -+ -+/** -+ * cpr4_apss_parse_misc_fuse_voltage_adjustments() - fill an array from a -+ * portion of the voltage adjustments specified based on -+ * miscellaneous fuse bits. -+ * @vreg: Pointer to the CPR3 regulator -+ * @volt_adjust: Voltage adjustment output data array which must be -+ * of size vreg->corner_count -+ * -+ * cpr3_parse_common_corner_data() must be called for vreg before this function -+ * is called so that speed bin size elements are initialized. -+ * -+ * Two formats are supported for the device tree property: -+ * 1. Length == tuple_list_size * vreg->corner_count -+ * (reading begins at index 0) -+ * 2. Length == tuple_list_size * vreg->speed_bin_corner_sum -+ * (reading begins at index tuple_list_size * vreg->speed_bin_offset) -+ * -+ * Here, tuple_list_size is the number of possible values for misc fuse. -+ * All other property lengths are treated as errors. -+ * -+ * Return: 0 on success, errno on failure -+ */ -+static int cpr4_apss_parse_misc_fuse_voltage_adjustments( -+ struct cpr3_regulator *vreg, u32 *volt_adjust) -+{ -+ struct device_node *node = vreg->of_node; -+ struct cpr4_ipq807x_apss_fuses *fuse = vreg->platform_fuses; -+ int tuple_list_size = IPQ807x_MISC_FUSE_VAL_COUNT; -+ int i, offset, rc, len = 0; -+ const char *prop_name = "qcom,cpr-misc-fuse-voltage-adjustment"; -+ -+ if (!of_find_property(node, prop_name, &len)) { -+ cpr3_err(vreg, "property %s is missing\n", prop_name); -+ return -EINVAL; -+ } -+ -+ if (len == tuple_list_size * vreg->corner_count * sizeof(u32)) { -+ offset = 0; -+ } else if (vreg->speed_bin_corner_sum > 0 && -+ len == tuple_list_size * vreg->speed_bin_corner_sum -+ * sizeof(u32)) { -+ offset = tuple_list_size * vreg->speed_bin_offset -+ + fuse->misc * vreg->corner_count; -+ } else { -+ if (vreg->speed_bin_corner_sum > 0) -+ cpr3_err(vreg, "property %s has invalid length=%d, should be %zu or %zu\n", -+ prop_name, len, -+ tuple_list_size * vreg->corner_count -+ * sizeof(u32), -+ tuple_list_size * vreg->speed_bin_corner_sum -+ * sizeof(u32)); -+ else -+ cpr3_err(vreg, "property %s has invalid length=%d, should be %zu\n", -+ prop_name, len, -+ tuple_list_size * vreg->corner_count -+ * sizeof(u32)); -+ return -EINVAL; -+ } -+ -+ for (i = 0; i < vreg->corner_count; i++) { -+ rc = of_property_read_u32_index(node, prop_name, offset + i, -+ &volt_adjust[i]); -+ if (rc) { -+ cpr3_err(vreg, "error reading property %s, rc=%d\n", -+ prop_name, rc); -+ return rc; -+ } -+ } -+ -+ return 0; -+} -+ -+/** -+ * cpr4_ipq807x_apss_calculate_open_loop_voltages() - calculate the open-loop -+ * voltage for each corner of a CPR3 regulator -+ * @vreg: Pointer to the CPR3 regulator -+ * -+ * If open-loop voltage interpolation is allowed in device tree, then -+ * this function calculates the open-loop voltage for a given corner using -+ * linear interpolation. This interpolation is performed using the processor -+ * frequencies of the lower and higher Fmax corners along with their fused -+ * open-loop voltages. -+ * -+ * If open-loop voltage interpolation is not allowed, then this function uses -+ * the Fmax fused open-loop voltage for all of the corners associated with a -+ * given fuse corner. -+ * -+ * Return: 0 on success, errno on failure -+ */ -+static int cpr4_ipq807x_apss_calculate_open_loop_voltages( -+ struct cpr3_regulator *vreg) -+{ -+ struct device_node *node = vreg->of_node; -+ struct cpr4_ipq807x_apss_fuses *fuse = vreg->platform_fuses; -+ struct cpr3_controller *ctrl = vreg->thread->ctrl; -+ int i, j, rc = 0; -+ bool allow_interpolation; -+ u64 freq_low, volt_low, freq_high, volt_high; -+ int *fuse_volt, *misc_adj_volt; -+ int *fmax_corner; -+ -+ fuse_volt = kcalloc(vreg->fuse_corner_count, sizeof(*fuse_volt), -+ GFP_KERNEL); -+ fmax_corner = kcalloc(vreg->fuse_corner_count, sizeof(*fmax_corner), -+ GFP_KERNEL); -+ if (!fuse_volt || !fmax_corner) { -+ rc = -ENOMEM; -+ goto done; -+ } -+ -+ for (i = 0; i < vreg->fuse_corner_count; i++) { -+ if (ctrl->cpr_global_setting == CPR_DISABLED) -+ fuse_volt[i] = vreg->cpr4_regulator_data->fuse_ref_volt[i]; -+ else -+ fuse_volt[i] = cpr3_convert_open_loop_voltage_fuse( -+ vreg->cpr4_regulator_data->fuse_ref_volt[i], -+ vreg->cpr4_regulator_data->fuse_step_volt, -+ fuse->init_voltage[i], -+ IPQ807x_APSS_VOLTAGE_FUSE_SIZE); -+ -+ /* Log fused open-loop voltage values for debugging purposes. */ -+ cpr3_info(vreg, "fused %8s: open-loop=%7d uV\n", -+ cpr4_ipq807x_apss_fuse_corner_name[i], -+ fuse_volt[i]); -+ } -+ -+ rc = cpr3_determine_part_type(vreg, -+ fuse_volt[vreg->fuse_corner_count - 1]); -+ if (rc) { -+ cpr3_err(vreg, "fused part type detection failed failed, rc=%d\n", -+ rc); -+ goto done; -+ } -+ -+ rc = cpr3_adjust_fused_open_loop_voltages(vreg, fuse_volt); -+ if (rc) { -+ cpr3_err(vreg, "fused open-loop voltage adjustment failed, rc=%d\n", -+ rc); -+ goto done; -+ } -+ -+ allow_interpolation = of_property_read_bool(node, -+ "qcom,allow-voltage-interpolation"); -+ -+ for (i = 1; i < vreg->fuse_corner_count; i++) { -+ if (fuse_volt[i] < fuse_volt[i - 1]) { -+ cpr3_info(vreg, "fuse corner %d voltage=%d uV < fuse corner %d voltage=%d uV; overriding: fuse corner %d voltage=%d\n", -+ i, fuse_volt[i], i - 1, fuse_volt[i - 1], -+ i, fuse_volt[i - 1]); -+ fuse_volt[i] = fuse_volt[i - 1]; -+ } -+ } -+ -+ if (!allow_interpolation) { -+ /* Use fused open-loop voltage for lower frequencies. */ -+ for (i = 0; i < vreg->corner_count; i++) -+ vreg->corner[i].open_loop_volt -+ = fuse_volt[vreg->corner[i].cpr_fuse_corner]; -+ goto done; -+ } -+ -+ /* Determine highest corner mapped to each fuse corner */ -+ j = vreg->fuse_corner_count - 1; -+ for (i = vreg->corner_count - 1; i >= 0; i--) { -+ if (vreg->corner[i].cpr_fuse_corner == j) { -+ fmax_corner[j] = i; -+ j--; -+ } -+ } -+ if (j >= 0) { -+ cpr3_err(vreg, "invalid fuse corner mapping\n"); -+ rc = -EINVAL; -+ goto done; -+ } -+ -+ /* -+ * Interpolation is not possible for corners mapped to the lowest fuse -+ * corner so use the fuse corner value directly. -+ */ -+ for (i = 0; i <= fmax_corner[0]; i++) -+ vreg->corner[i].open_loop_volt = fuse_volt[0]; -+ -+ /* Interpolate voltages for the higher fuse corners. */ -+ for (i = 1; i < vreg->fuse_corner_count; i++) { -+ freq_low = vreg->corner[fmax_corner[i - 1]].proc_freq; -+ volt_low = fuse_volt[i - 1]; -+ freq_high = vreg->corner[fmax_corner[i]].proc_freq; -+ volt_high = fuse_volt[i]; -+ -+ for (j = fmax_corner[i - 1] + 1; j <= fmax_corner[i]; j++) -+ vreg->corner[j].open_loop_volt = cpr3_interpolate( -+ freq_low, volt_low, freq_high, volt_high, -+ vreg->corner[j].proc_freq); -+ } -+ -+done: -+ if (rc == 0) { -+ cpr3_debug(vreg, "unadjusted per-corner open-loop voltages:\n"); -+ for (i = 0; i < vreg->corner_count; i++) -+ cpr3_debug(vreg, "open-loop[%2d] = %d uV\n", i, -+ vreg->corner[i].open_loop_volt); -+ -+ rc = cpr3_adjust_open_loop_voltages(vreg); -+ if (rc) -+ cpr3_err(vreg, "open-loop voltage adjustment failed, rc=%d\n", -+ rc); -+ -+ if (of_find_property(node, -+ "qcom,cpr-misc-fuse-voltage-adjustment", -+ NULL)) { -+ misc_adj_volt = kcalloc(vreg->corner_count, -+ sizeof(*misc_adj_volt), GFP_KERNEL); -+ if (!misc_adj_volt) { -+ rc = -ENOMEM; -+ goto _exit; -+ } -+ -+ rc = cpr4_apss_parse_misc_fuse_voltage_adjustments(vreg, -+ misc_adj_volt); -+ if (rc) { -+ cpr3_err(vreg, "qcom,cpr-misc-fuse-voltage-adjustment reading failed, rc=%d\n", -+ rc); -+ kfree(misc_adj_volt); -+ goto _exit; -+ } -+ -+ for (i = 0; i < vreg->corner_count; i++) -+ vreg->corner[i].open_loop_volt -+ += misc_adj_volt[i]; -+ kfree(misc_adj_volt); -+ } -+ } -+ -+_exit: -+ kfree(fuse_volt); -+ kfree(fmax_corner); -+ return rc; -+} -+ -+/** -+ * cpr4_ipq807x_apss_set_no_interpolation_quotients() - use the fused target -+ * quotient values for lower frequencies. -+ * @vreg: Pointer to the CPR3 regulator -+ * @volt_adjust: Pointer to array of per-corner closed-loop adjustment -+ * voltages -+ * @volt_adjust_fuse: Pointer to array of per-fuse-corner closed-loop -+ * adjustment voltages -+ * @ro_scale: Pointer to array of per-fuse-corner RO scaling factor -+ * values with units of QUOT/V -+ * -+ * Return: 0 on success, errno on failure -+ */ -+static int cpr4_ipq807x_apss_set_no_interpolation_quotients( -+ struct cpr3_regulator *vreg, int *volt_adjust, -+ int *volt_adjust_fuse, int *ro_scale) -+{ -+ struct cpr4_ipq807x_apss_fuses *fuse = vreg->platform_fuses; -+ u32 quot, ro; -+ int quot_adjust; -+ int i, fuse_corner; -+ -+ for (i = 0; i < vreg->corner_count; i++) { -+ fuse_corner = vreg->corner[i].cpr_fuse_corner; -+ quot = fuse->target_quot[fuse_corner]; -+ quot_adjust = cpr3_quot_adjustment(ro_scale[fuse_corner], -+ volt_adjust_fuse[fuse_corner] + -+ volt_adjust[i]); -+ ro = fuse->ro_sel[fuse_corner]; -+ vreg->corner[i].target_quot[ro] = quot + quot_adjust; -+ cpr3_debug(vreg, "corner=%d RO=%u target quot=%u\n", -+ i, ro, quot); -+ -+ if (quot_adjust) -+ cpr3_debug(vreg, "adjusted corner %d RO%u target quot: %u --> %u (%d uV)\n", -+ i, ro, quot, vreg->corner[i].target_quot[ro], -+ volt_adjust_fuse[fuse_corner] + -+ volt_adjust[i]); -+ } -+ -+ return 0; -+} -+ -+/** -+ * cpr4_ipq807x_apss_calculate_target_quotients() - calculate the CPR target -+ * quotient for each corner of a CPR3 regulator -+ * @vreg: Pointer to the CPR3 regulator -+ * -+ * If target quotient interpolation is allowed in device tree, then this -+ * function calculates the target quotient for a given corner using linear -+ * interpolation. This interpolation is performed using the processor -+ * frequencies of the lower and higher Fmax corners along with the fused -+ * target quotient and quotient offset of the higher Fmax corner. -+ * -+ * If target quotient interpolation is not allowed, then this function uses -+ * the Fmax fused target quotient for all of the corners associated with a -+ * given fuse corner. -+ * -+ * Return: 0 on success, errno on failure -+ */ -+static int cpr4_ipq807x_apss_calculate_target_quotients( -+ struct cpr3_regulator *vreg) -+{ -+ struct cpr4_ipq807x_apss_fuses *fuse = vreg->platform_fuses; -+ int rc; -+ bool allow_interpolation; -+ u64 freq_low, freq_high, prev_quot; -+ u64 *quot_low; -+ u64 *quot_high; -+ u32 quot, ro; -+ int i, j, fuse_corner, quot_adjust; -+ int *fmax_corner; -+ int *volt_adjust, *volt_adjust_fuse, *ro_scale; -+ int *voltage_adj_misc; -+ -+ /* Log fused quotient values for debugging purposes. */ -+ for (i = CPR4_IPQ807x_APSS_FUSE_CORNER_SVS; -+ i < vreg->fuse_corner_count; i++) -+ cpr3_info(vreg, "fused %8s: quot[%2llu]=%4llu, quot_offset[%2llu]=%4llu\n", -+ cpr4_ipq807x_apss_fuse_corner_name[i], -+ fuse->ro_sel[i], fuse->target_quot[i], -+ fuse->ro_sel[i], fuse->quot_offset[i] * -+ IPQ807x_APSS_QUOT_OFFSET_SCALE); -+ -+ allow_interpolation = of_property_read_bool(vreg->of_node, -+ "qcom,allow-quotient-interpolation"); -+ -+ volt_adjust = kcalloc(vreg->corner_count, sizeof(*volt_adjust), -+ GFP_KERNEL); -+ volt_adjust_fuse = kcalloc(vreg->fuse_corner_count, -+ sizeof(*volt_adjust_fuse), GFP_KERNEL); -+ ro_scale = kcalloc(vreg->fuse_corner_count, sizeof(*ro_scale), -+ GFP_KERNEL); -+ fmax_corner = kcalloc(vreg->fuse_corner_count, sizeof(*fmax_corner), -+ GFP_KERNEL); -+ quot_low = kcalloc(vreg->fuse_corner_count, sizeof(*quot_low), -+ GFP_KERNEL); -+ quot_high = kcalloc(vreg->fuse_corner_count, sizeof(*quot_high), -+ GFP_KERNEL); -+ if (!volt_adjust || !volt_adjust_fuse || !ro_scale || -+ !fmax_corner || !quot_low || !quot_high) { -+ rc = -ENOMEM; -+ goto done; -+ } -+ -+ rc = cpr3_parse_closed_loop_voltage_adjustments(vreg, &fuse->ro_sel[0], -+ volt_adjust, volt_adjust_fuse, ro_scale); -+ if (rc) { -+ cpr3_err(vreg, "could not load closed-loop voltage adjustments, rc=%d\n", -+ rc); -+ goto done; -+ } -+ -+ if (of_find_property(vreg->of_node, -+ "qcom,cpr-misc-fuse-voltage-adjustment", NULL)) { -+ voltage_adj_misc = kcalloc(vreg->corner_count, -+ sizeof(*voltage_adj_misc), GFP_KERNEL); -+ if (!voltage_adj_misc) { -+ rc = -ENOMEM; -+ goto done; -+ } -+ -+ rc = cpr4_apss_parse_misc_fuse_voltage_adjustments(vreg, -+ voltage_adj_misc); -+ if (rc) { -+ cpr3_err(vreg, "qcom,cpr-misc-fuse-voltage-adjustment reading failed, rc=%d\n", -+ rc); -+ kfree(voltage_adj_misc); -+ goto done; -+ } -+ -+ for (i = 0; i < vreg->corner_count; i++) -+ volt_adjust[i] += voltage_adj_misc[i]; -+ -+ kfree(voltage_adj_misc); -+ } -+ -+ if (!allow_interpolation) { -+ /* Use fused target quotients for lower frequencies. */ -+ return cpr4_ipq807x_apss_set_no_interpolation_quotients( -+ vreg, volt_adjust, volt_adjust_fuse, ro_scale); -+ } -+ -+ /* Determine highest corner mapped to each fuse corner */ -+ j = vreg->fuse_corner_count - 1; -+ for (i = vreg->corner_count - 1; i >= 0; i--) { -+ if (vreg->corner[i].cpr_fuse_corner == j) { -+ fmax_corner[j] = i; -+ j--; -+ } -+ } -+ if (j >= 0) { -+ cpr3_err(vreg, "invalid fuse corner mapping\n"); -+ rc = -EINVAL; -+ goto done; -+ } -+ -+ /* -+ * Interpolation is not possible for corners mapped to the lowest fuse -+ * corner so use the fuse corner value directly. -+ */ -+ i = CPR4_IPQ807x_APSS_FUSE_CORNER_SVS; -+ quot_adjust = cpr3_quot_adjustment(ro_scale[i], volt_adjust_fuse[i]); -+ quot = fuse->target_quot[i] + quot_adjust; -+ quot_high[i] = quot_low[i] = quot; -+ ro = fuse->ro_sel[i]; -+ if (quot_adjust) -+ cpr3_debug(vreg, "adjusted fuse corner %d RO%u target quot: %llu --> %u (%d uV)\n", -+ i, ro, fuse->target_quot[i], quot, volt_adjust_fuse[i]); -+ -+ for (i = 0; i <= fmax_corner[CPR4_IPQ807x_APSS_FUSE_CORNER_SVS]; -+ i++) -+ vreg->corner[i].target_quot[ro] = quot; -+ -+ for (i = CPR4_IPQ807x_APSS_FUSE_CORNER_NOM; -+ i < vreg->fuse_corner_count; i++) { -+ quot_high[i] = fuse->target_quot[i]; -+ if (fuse->ro_sel[i] == fuse->ro_sel[i - 1]) -+ quot_low[i] = quot_high[i - 1]; -+ else -+ quot_low[i] = quot_high[i] -+ - fuse->quot_offset[i] -+ * IPQ807x_APSS_QUOT_OFFSET_SCALE; -+ if (quot_high[i] < quot_low[i]) { -+ cpr3_debug(vreg, "quot_high[%d]=%llu < quot_low[%d]=%llu; overriding: quot_high[%d]=%llu\n", -+ i, quot_high[i], i, quot_low[i], -+ i, quot_low[i]); -+ quot_high[i] = quot_low[i]; -+ } -+ } -+ -+ /* Perform per-fuse-corner target quotient adjustment */ -+ for (i = 1; i < vreg->fuse_corner_count; i++) { -+ quot_adjust = cpr3_quot_adjustment(ro_scale[i], -+ volt_adjust_fuse[i]); -+ if (quot_adjust) { -+ prev_quot = quot_high[i]; -+ quot_high[i] += quot_adjust; -+ cpr3_debug(vreg, "adjusted fuse corner %d RO%llu target quot: %llu --> %llu (%d uV)\n", -+ i, fuse->ro_sel[i], prev_quot, quot_high[i], -+ volt_adjust_fuse[i]); -+ } -+ -+ if (fuse->ro_sel[i] == fuse->ro_sel[i - 1]) -+ quot_low[i] = quot_high[i - 1]; -+ else -+ quot_low[i] += cpr3_quot_adjustment(ro_scale[i], -+ volt_adjust_fuse[i - 1]); -+ -+ if (quot_high[i] < quot_low[i]) { -+ cpr3_debug(vreg, "quot_high[%d]=%llu < quot_low[%d]=%llu after adjustment; overriding: quot_high[%d]=%llu\n", -+ i, quot_high[i], i, quot_low[i], -+ i, quot_low[i]); -+ quot_high[i] = quot_low[i]; -+ } -+ } -+ -+ /* Interpolate voltages for the higher fuse corners. */ -+ for (i = 1; i < vreg->fuse_corner_count; i++) { -+ freq_low = vreg->corner[fmax_corner[i - 1]].proc_freq; -+ freq_high = vreg->corner[fmax_corner[i]].proc_freq; -+ -+ ro = fuse->ro_sel[i]; -+ for (j = fmax_corner[i - 1] + 1; j <= fmax_corner[i]; j++) -+ vreg->corner[j].target_quot[ro] = cpr3_interpolate( -+ freq_low, quot_low[i], freq_high, quot_high[i], -+ vreg->corner[j].proc_freq); -+ } -+ -+ /* Perform per-corner target quotient adjustment */ -+ for (i = 0; i < vreg->corner_count; i++) { -+ fuse_corner = vreg->corner[i].cpr_fuse_corner; -+ ro = fuse->ro_sel[fuse_corner]; -+ quot_adjust = cpr3_quot_adjustment(ro_scale[fuse_corner], -+ volt_adjust[i]); -+ if (quot_adjust) { -+ prev_quot = vreg->corner[i].target_quot[ro]; -+ vreg->corner[i].target_quot[ro] += quot_adjust; -+ cpr3_debug(vreg, "adjusted corner %d RO%u target quot: %llu --> %u (%d uV)\n", -+ i, ro, prev_quot, -+ vreg->corner[i].target_quot[ro], -+ volt_adjust[i]); -+ } -+ } -+ -+ /* Ensure that target quotients increase monotonically */ -+ for (i = 1; i < vreg->corner_count; i++) { -+ ro = fuse->ro_sel[vreg->corner[i].cpr_fuse_corner]; -+ if (fuse->ro_sel[vreg->corner[i - 1].cpr_fuse_corner] == ro -+ && vreg->corner[i].target_quot[ro] -+ < vreg->corner[i - 1].target_quot[ro]) { -+ cpr3_debug(vreg, "adjusted corner %d RO%u target quot=%u < adjusted corner %d RO%u target quot=%u; overriding: corner %d RO%u target quot=%u\n", -+ i, ro, vreg->corner[i].target_quot[ro], -+ i - 1, ro, vreg->corner[i - 1].target_quot[ro], -+ i, ro, vreg->corner[i - 1].target_quot[ro]); -+ vreg->corner[i].target_quot[ro] -+ = vreg->corner[i - 1].target_quot[ro]; -+ } -+ } -+ -+done: -+ kfree(volt_adjust); -+ kfree(volt_adjust_fuse); -+ kfree(ro_scale); -+ kfree(fmax_corner); -+ kfree(quot_low); -+ kfree(quot_high); -+ return rc; -+} -+ -+/** -+ * cpr4_apss_print_settings() - print out APSS CPR configuration settings into -+ * the kernel log for debugging purposes -+ * @vreg: Pointer to the CPR3 regulator -+ */ -+static void cpr4_apss_print_settings(struct cpr3_regulator *vreg) -+{ -+ struct cpr3_corner *corner; -+ int i; -+ -+ cpr3_debug(vreg, "Corner: Frequency (Hz), Fuse Corner, Floor (uV), Open-Loop (uV), Ceiling (uV)\n"); -+ for (i = 0; i < vreg->corner_count; i++) { -+ corner = &vreg->corner[i]; -+ cpr3_debug(vreg, "%3d: %10u, %2d, %7d, %7d, %7d\n", -+ i, corner->proc_freq, corner->cpr_fuse_corner, -+ corner->floor_volt, corner->open_loop_volt, -+ corner->ceiling_volt); -+ } -+ -+ if (vreg->thread->ctrl->apm) -+ cpr3_debug(vreg, "APM threshold = %d uV, APM adjust = %d uV\n", -+ vreg->thread->ctrl->apm_threshold_volt, -+ vreg->thread->ctrl->apm_adj_volt); -+} -+ -+/** -+ * cpr4_apss_init_thread() - perform steps necessary to initialize the -+ * configuration data for a CPR3 thread -+ * @thread: Pointer to the CPR3 thread -+ * -+ * Return: 0 on success, errno on failure -+ */ -+static int cpr4_apss_init_thread(struct cpr3_thread *thread) -+{ -+ int rc; -+ -+ rc = cpr3_parse_common_thread_data(thread); -+ if (rc) { -+ cpr3_err(thread->ctrl, "thread %u unable to read CPR thread data from device tree, rc=%d\n", -+ thread->thread_id, rc); -+ return rc; -+ } -+ -+ return 0; -+} -+ -+/** -+ * cpr4_apss_parse_temp_adj_properties() - parse temperature based -+ * adjustment properties from device tree. -+ * @ctrl: Pointer to the CPR3 controller -+ * -+ * Return: 0 on success, errno on failure -+ */ -+static int cpr4_apss_parse_temp_adj_properties(struct cpr3_controller *ctrl) -+{ -+ struct device_node *of_node = ctrl->dev->of_node; -+ int rc, i, len, temp_point_count; -+ -+ if (!of_find_property(of_node, "qcom,cpr-temp-point-map", &len)) { -+ /* -+ * Temperature based adjustments are not defined. Single -+ * temperature band is still valid for per-online-core -+ * adjustments. -+ */ -+ ctrl->temp_band_count = 1; -+ return 0; -+ } -+ -+ temp_point_count = len / sizeof(u32); -+ if (temp_point_count <= 0 || -+ temp_point_count > IPQ807x_APSS_MAX_TEMP_POINTS) { -+ cpr3_err(ctrl, "invalid number of temperature points %d > %d (max)\n", -+ temp_point_count, IPQ807x_APSS_MAX_TEMP_POINTS); -+ return -EINVAL; -+ } -+ -+ ctrl->temp_points = devm_kcalloc(ctrl->dev, temp_point_count, -+ sizeof(*ctrl->temp_points), GFP_KERNEL); -+ if (!ctrl->temp_points) -+ return -ENOMEM; -+ -+ rc = of_property_read_u32_array(of_node, "qcom,cpr-temp-point-map", -+ ctrl->temp_points, temp_point_count); -+ if (rc) { -+ cpr3_err(ctrl, "error reading property qcom,cpr-temp-point-map, rc=%d\n", -+ rc); -+ return rc; -+ } -+ -+ for (i = 0; i < temp_point_count; i++) -+ cpr3_debug(ctrl, "Temperature Point %d=%d\n", i, -+ ctrl->temp_points[i]); -+ -+ /* -+ * If t1, t2, and t3 are the temperature points, then the temperature -+ * bands are: (-inf, t1], (t1, t2], (t2, t3], and (t3, inf). -+ */ -+ ctrl->temp_band_count = temp_point_count + 1; -+ cpr3_debug(ctrl, "Number of temp bands =%d\n", ctrl->temp_band_count); -+ -+ rc = of_property_read_u32(of_node, "qcom,cpr-initial-temp-band", -+ &ctrl->initial_temp_band); -+ if (rc) { -+ cpr3_err(ctrl, "error reading qcom,cpr-initial-temp-band, rc=%d\n", -+ rc); -+ return rc; -+ } -+ -+ if (ctrl->initial_temp_band >= ctrl->temp_band_count) { -+ cpr3_err(ctrl, "Initial temperature band value %d should be in range [0 - %d]\n", -+ ctrl->initial_temp_band, ctrl->temp_band_count - 1); -+ return -EINVAL; -+ } -+ -+ ctrl->temp_sensor_id_start = IPQ807x_APSS_TEMP_SENSOR_ID_START; -+ ctrl->temp_sensor_id_end = IPQ807x_APSS_TEMP_SENSOR_ID_END; -+ ctrl->allow_temp_adj = true; -+ return rc; -+} -+ -+/** -+ * cpr4_apss_parse_boost_properties() - parse configuration data for boost -+ * voltage adjustment for CPR3 regulator from device tree. -+ * @vreg: Pointer to the CPR3 regulator -+ * -+ * Return: 0 on success, errno on failure -+ */ -+static int cpr4_apss_parse_boost_properties(struct cpr3_regulator *vreg) -+{ -+ struct cpr3_controller *ctrl = vreg->thread->ctrl; -+ struct cpr4_ipq807x_apss_fuses *fuse = vreg->platform_fuses; -+ struct cpr3_corner *corner; -+ int i, boost_voltage, final_boost_volt, rc = 0; -+ int *boost_table = NULL, *boost_temp_adj = NULL; -+ int boost_voltage_adjust = 0, boost_num_cores = 0; -+ u32 boost_allowed = 0; -+ -+ if (!boost_fuse[fuse->boost_cfg]) -+ /* Voltage boost is disabled in fuse */ -+ return 0; -+ -+ if (of_find_property(vreg->of_node, "qcom,allow-boost", NULL)) { -+ rc = cpr3_parse_array_property(vreg, "qcom,allow-boost", 1, -+ &boost_allowed); -+ if (rc) -+ return rc; -+ } -+ -+ if (!boost_allowed) { -+ /* Voltage boost is not enabled for this regulator */ -+ return 0; -+ } -+ -+ boost_voltage = cpr3_convert_open_loop_voltage_fuse( -+ vreg->cpr4_regulator_data->boost_fuse_ref_volt, -+ vreg->cpr4_regulator_data->fuse_step_volt, -+ fuse->boost_voltage, -+ IPQ807x_APSS_VOLTAGE_FUSE_SIZE); -+ -+ /* Log boost voltage value for debugging purposes. */ -+ cpr3_info(vreg, "Boost open-loop=%7d uV\n", boost_voltage); -+ -+ if (of_find_property(vreg->of_node, -+ "qcom,cpr-boost-voltage-fuse-adjustment", NULL)) { -+ rc = cpr3_parse_array_property(vreg, -+ "qcom,cpr-boost-voltage-fuse-adjustment", -+ 1, &boost_voltage_adjust); -+ if (rc) { -+ cpr3_err(vreg, "qcom,cpr-boost-voltage-fuse-adjustment reading failed, rc=%d\n", -+ rc); -+ return rc; -+ } -+ -+ boost_voltage += boost_voltage_adjust; -+ /* Log boost voltage value for debugging purposes. */ -+ cpr3_info(vreg, "Adjusted boost open-loop=%7d uV\n", -+ boost_voltage); -+ } -+ -+ /* Limit boost voltage value between ceiling and floor voltage limits */ -+ boost_voltage = min(boost_voltage, vreg->cpr4_regulator_data->boost_ceiling_volt); -+ boost_voltage = max(boost_voltage, vreg->cpr4_regulator_data->boost_floor_volt); -+ -+ /* -+ * The boost feature can only be used for the highest voltage corner. -+ * Also, keep core-count adjustments disabled when the boost feature -+ * is enabled. -+ */ -+ corner = &vreg->corner[vreg->corner_count - 1]; -+ if (!corner->sdelta) { -+ /* -+ * If core-count/temp adjustments are not defined, the cpr4 -+ * sdelta for this corner will not be allocated. Allocate it -+ * here for boost configuration. -+ */ -+ corner->sdelta = devm_kzalloc(ctrl->dev, -+ sizeof(*corner->sdelta), GFP_KERNEL); -+ if (!corner->sdelta) -+ return -ENOMEM; -+ } -+ corner->sdelta->temp_band_count = ctrl->temp_band_count; -+ -+ rc = of_property_read_u32(vreg->of_node, "qcom,cpr-num-boost-cores", -+ &boost_num_cores); -+ if (rc) { -+ cpr3_err(vreg, "qcom,cpr-num-boost-cores reading failed, rc=%d\n", -+ rc); -+ return rc; -+ } -+ -+ if (boost_num_cores <= 0 || -+ boost_num_cores > IPQ807x_APSS_CPR_SDELTA_CORE_COUNT) { -+ cpr3_err(vreg, "Invalid boost number of cores = %d\n", -+ boost_num_cores); -+ return -EINVAL; -+ } -+ corner->sdelta->boost_num_cores = boost_num_cores; -+ -+ boost_table = devm_kcalloc(ctrl->dev, corner->sdelta->temp_band_count, -+ sizeof(*boost_table), GFP_KERNEL); -+ if (!boost_table) -+ return -ENOMEM; -+ -+ if (of_find_property(vreg->of_node, -+ "qcom,cpr-boost-temp-adjustment", NULL)) { -+ boost_temp_adj = kcalloc(corner->sdelta->temp_band_count, -+ sizeof(*boost_temp_adj), GFP_KERNEL); -+ if (!boost_temp_adj) -+ return -ENOMEM; -+ -+ rc = cpr3_parse_array_property(vreg, -+ "qcom,cpr-boost-temp-adjustment", -+ corner->sdelta->temp_band_count, -+ boost_temp_adj); -+ if (rc) { -+ cpr3_err(vreg, "qcom,cpr-boost-temp-adjustment reading failed, rc=%d\n", -+ rc); -+ goto done; -+ } -+ } -+ -+ for (i = 0; i < corner->sdelta->temp_band_count; i++) { -+ /* Apply static adjustments to boost voltage */ -+ final_boost_volt = boost_voltage + (boost_temp_adj == NULL -+ ? 0 : boost_temp_adj[i]); -+ /* -+ * Limit final adjusted boost voltage value between ceiling -+ * and floor voltage limits -+ */ -+ final_boost_volt = min(final_boost_volt, -+ vreg->cpr4_regulator_data->boost_ceiling_volt); -+ final_boost_volt = max(final_boost_volt, -+ vreg->cpr4_regulator_data->boost_floor_volt); -+ -+ boost_table[i] = (corner->open_loop_volt - final_boost_volt) -+ / ctrl->step_volt; -+ cpr3_debug(vreg, "Adjusted boost voltage margin for temp band %d = %d steps\n", -+ i, boost_table[i]); -+ } -+ -+ corner->ceiling_volt = vreg->cpr4_regulator_data->boost_ceiling_volt; -+ corner->sdelta->boost_table = boost_table; -+ corner->sdelta->allow_boost = true; -+ corner->sdelta->allow_core_count_adj = false; -+ vreg->allow_boost = true; -+ ctrl->allow_boost = true; -+done: -+ kfree(boost_temp_adj); -+ return rc; -+} -+ -+/** -+ * cpr4_apss_init_regulator() - perform all steps necessary to initialize the -+ * configuration data for a CPR3 regulator -+ * @vreg: Pointer to the CPR3 regulator -+ * -+ * Return: 0 on success, errno on failure -+ */ -+static int cpr4_apss_init_regulator(struct cpr3_regulator *vreg) -+{ -+ struct cpr4_ipq807x_apss_fuses *fuse; -+ int rc; -+ -+ rc = cpr4_ipq807x_apss_read_fuse_data(vreg); -+ if (rc) { -+ cpr3_err(vreg, "unable to read CPR fuse data, rc=%d\n", rc); -+ return rc; -+ } -+ -+ fuse = vreg->platform_fuses; -+ -+ rc = cpr4_apss_parse_corner_data(vreg); -+ if (rc) { -+ cpr3_err(vreg, "unable to read CPR corner data from device tree, rc=%d\n", -+ rc); -+ return rc; -+ } -+ -+ rc = cpr3_mem_acc_init(vreg); -+ if (rc) { -+ if (rc != -EPROBE_DEFER) -+ cpr3_err(vreg, "unable to initialize mem-acc regulator settings, rc=%d\n", -+ rc); -+ return rc; -+ } -+ -+ rc = cpr4_ipq807x_apss_calculate_open_loop_voltages(vreg); -+ if (rc) { -+ cpr3_err(vreg, "unable to calculate open-loop voltages, rc=%d\n", -+ rc); -+ return rc; -+ } -+ -+ rc = cpr3_limit_open_loop_voltages(vreg); -+ if (rc) { -+ cpr3_err(vreg, "unable to limit open-loop voltages, rc=%d\n", -+ rc); -+ return rc; -+ } -+ -+ cpr3_open_loop_voltage_as_ceiling(vreg); -+ -+ rc = cpr3_limit_floor_voltages(vreg); -+ if (rc) { -+ cpr3_err(vreg, "unable to limit floor voltages, rc=%d\n", rc); -+ return rc; -+ } -+ -+ rc = cpr4_ipq807x_apss_calculate_target_quotients(vreg); -+ if (rc) { -+ cpr3_err(vreg, "unable to calculate target quotients, rc=%d\n", -+ rc); -+ return rc; -+ } -+ -+ rc = cpr4_parse_core_count_temp_voltage_adj(vreg, false); -+ if (rc) { -+ cpr3_err(vreg, "unable to parse temperature and core count voltage adjustments, rc=%d\n", -+ rc); -+ return rc; -+ } -+ -+ if (vreg->allow_core_count_adj && (vreg->max_core_count <= 0 -+ || vreg->max_core_count > -+ IPQ807x_APSS_CPR_SDELTA_CORE_COUNT)) { -+ cpr3_err(vreg, "qcom,max-core-count has invalid value = %d\n", -+ vreg->max_core_count); -+ return -EINVAL; -+ } -+ -+ rc = cpr4_apss_parse_boost_properties(vreg); -+ if (rc) { -+ cpr3_err(vreg, "unable to parse boost adjustments, rc=%d\n", -+ rc); -+ return rc; -+ } -+ -+ cpr4_apss_print_settings(vreg); -+ -+ return rc; -+} -+ -+/** -+ * cpr4_apss_init_controller() - perform APSS CPR4 controller specific -+ * initializations -+ * @ctrl: Pointer to the CPR3 controller -+ * -+ * Return: 0 on success, errno on failure -+ */ -+static int cpr4_apss_init_controller(struct cpr3_controller *ctrl) -+{ -+ int rc; -+ -+ rc = cpr3_parse_common_ctrl_data(ctrl); -+ if (rc) { -+ if (rc != -EPROBE_DEFER) -+ cpr3_err(ctrl, "unable to parse common controller data, rc=%d\n", -+ rc); -+ return rc; -+ } -+ -+ rc = of_property_read_u32(ctrl->dev->of_node, -+ "qcom,cpr-down-error-step-limit", -+ &ctrl->down_error_step_limit); -+ if (rc) { -+ cpr3_err(ctrl, "error reading qcom,cpr-down-error-step-limit, rc=%d\n", -+ rc); -+ return rc; -+ } -+ -+ rc = of_property_read_u32(ctrl->dev->of_node, -+ "qcom,cpr-up-error-step-limit", -+ &ctrl->up_error_step_limit); -+ if (rc) { -+ cpr3_err(ctrl, "error reading qcom,cpr-up-error-step-limit, rc=%d\n", -+ rc); -+ return rc; -+ } -+ -+ /* -+ * Use fixed step quotient if specified otherwise use dynamic -+ * calculated per RO step quotient -+ */ -+ of_property_read_u32(ctrl->dev->of_node, "qcom,cpr-step-quot-fixed", -+ &ctrl->step_quot_fixed); -+ ctrl->use_dynamic_step_quot = ctrl->step_quot_fixed ? false : true; -+ -+ ctrl->saw_use_unit_mV = of_property_read_bool(ctrl->dev->of_node, -+ "qcom,cpr-saw-use-unit-mV"); -+ -+ of_property_read_u32(ctrl->dev->of_node, -+ "qcom,cpr-voltage-settling-time", -+ &ctrl->voltage_settling_time); -+ -+ if (of_find_property(ctrl->dev->of_node, "vdd-limit-supply", NULL)) { -+ ctrl->vdd_limit_regulator = -+ devm_regulator_get(ctrl->dev, "vdd-limit"); -+ if (IS_ERR(ctrl->vdd_limit_regulator)) { -+ rc = PTR_ERR(ctrl->vdd_limit_regulator); -+ if (rc != -EPROBE_DEFER) -+ cpr3_err(ctrl, "unable to request vdd-limit regulator, rc=%d\n", -+ rc); -+ return rc; -+ } -+ } -+ -+ rc = cpr3_apm_init(ctrl); -+ if (rc) { -+ if (rc != -EPROBE_DEFER) -+ cpr3_err(ctrl, "unable to initialize APM settings, rc=%d\n", -+ rc); -+ return rc; -+ } -+ -+ rc = cpr4_apss_parse_temp_adj_properties(ctrl); -+ if (rc) { -+ cpr3_err(ctrl, "unable to parse temperature adjustment properties, rc=%d\n", -+ rc); -+ return rc; -+ } -+ -+ ctrl->sensor_count = IPQ807x_APSS_CPR_SENSOR_COUNT; -+ -+ /* -+ * APSS only has one thread (0) per controller so the zeroed -+ * array does not need further modification. -+ */ -+ ctrl->sensor_owner = devm_kcalloc(ctrl->dev, ctrl->sensor_count, -+ sizeof(*ctrl->sensor_owner), GFP_KERNEL); -+ if (!ctrl->sensor_owner) -+ return -ENOMEM; -+ -+ ctrl->ctrl_type = CPR_CTRL_TYPE_CPR4; -+ ctrl->supports_hw_closed_loop = false; -+ ctrl->use_hw_closed_loop = of_property_read_bool(ctrl->dev->of_node, -+ "qcom,cpr-hw-closed-loop"); -+ return 0; -+} -+ -+static int cpr4_apss_regulator_suspend(struct platform_device *pdev, -+ pm_message_t state) -+{ -+ struct cpr3_controller *ctrl = platform_get_drvdata(pdev); -+ -+ return cpr3_regulator_suspend(ctrl); -+} -+ -+static int cpr4_apss_regulator_resume(struct platform_device *pdev) -+{ -+ struct cpr3_controller *ctrl = platform_get_drvdata(pdev); -+ -+ return cpr3_regulator_resume(ctrl); -+} -+ -+static void ipq6018_set_mem_acc(struct regulator_dev *rdev) -+{ -+ struct cpr3_regulator *vreg = rdev_get_drvdata(rdev); -+ -+ ipq6018_mem_acc_tcsr[0].ioremap_addr = -+ ioremap(ipq6018_mem_acc_tcsr[0].phy_addr, 0x4); -+ ipq6018_mem_acc_tcsr[1].ioremap_addr = -+ ioremap(ipq6018_mem_acc_tcsr[1].phy_addr, 0x4); -+ -+ if ((ipq6018_mem_acc_tcsr[0].ioremap_addr != NULL) && -+ (ipq6018_mem_acc_tcsr[1].ioremap_addr != NULL) && -+ (vreg->current_corner == (vreg->corner_count - CPR3_CORNER_OFFSET))) { -+ -+ writel_relaxed(ipq6018_mem_acc_tcsr[0].value, -+ ipq6018_mem_acc_tcsr[0].ioremap_addr); -+ writel_relaxed(ipq6018_mem_acc_tcsr[1].value, -+ ipq6018_mem_acc_tcsr[1].ioremap_addr); -+ } -+} -+ -+static void ipq6018_clr_mem_acc(struct regulator_dev *rdev) -+{ -+ struct cpr3_regulator *vreg = rdev_get_drvdata(rdev); -+ -+ if ((ipq6018_mem_acc_tcsr[0].ioremap_addr != NULL) && -+ (ipq6018_mem_acc_tcsr[1].ioremap_addr != NULL) && -+ (vreg->current_corner != vreg->corner_count - CPR3_CORNER_OFFSET)) { -+ writel_relaxed(0x0, ipq6018_mem_acc_tcsr[0].ioremap_addr); -+ writel_relaxed(0x0, ipq6018_mem_acc_tcsr[1].ioremap_addr); -+ } -+ -+ iounmap(ipq6018_mem_acc_tcsr[0].ioremap_addr); -+ iounmap(ipq6018_mem_acc_tcsr[1].ioremap_addr); -+} -+ -+static struct cpr4_mem_acc_func ipq6018_mem_acc_funcs = { -+ .set_mem_acc = ipq6018_set_mem_acc, -+ .clear_mem_acc = ipq6018_clr_mem_acc -+}; -+ -+static const struct cpr4_reg_data ipq807x_cpr_apss = { -+ .cpr_valid_fuse_count = IPQ807x_APSS_FUSE_CORNERS, -+ .fuse_ref_volt = ipq807x_apss_fuse_ref_volt, -+ .fuse_step_volt = IPQ807x_APSS_FUSE_STEP_VOLT, -+ .cpr_clk_rate = IPQ807x_APSS_CPR_CLOCK_RATE, -+ .boost_fuse_ref_volt= IPQ807x_APSS_BOOST_FUSE_REF_VOLT, -+ .boost_ceiling_volt= IPQ807x_APSS_BOOST_CEILING_VOLT, -+ .boost_floor_volt= IPQ807x_APSS_BOOST_FLOOR_VOLT, -+ .cpr3_fuse_params = &ipq807x_fuse_params, -+ .mem_acc_funcs = NULL, -+}; -+ -+static const struct cpr4_reg_data ipq817x_cpr_apss = { -+ .cpr_valid_fuse_count = IPQ817x_APPS_FUSE_CORNERS, -+ .fuse_ref_volt = ipq807x_apss_fuse_ref_volt, -+ .fuse_step_volt = IPQ807x_APSS_FUSE_STEP_VOLT, -+ .cpr_clk_rate = IPQ807x_APSS_CPR_CLOCK_RATE, -+ .boost_fuse_ref_volt= IPQ807x_APSS_BOOST_FUSE_REF_VOLT, -+ .boost_ceiling_volt= IPQ807x_APSS_BOOST_CEILING_VOLT, -+ .boost_floor_volt= IPQ807x_APSS_BOOST_FLOOR_VOLT, -+ .cpr3_fuse_params = &ipq807x_fuse_params, -+ .mem_acc_funcs = NULL, -+}; -+ -+static const struct cpr4_reg_data ipq6018_cpr_apss = { -+ .cpr_valid_fuse_count = IPQ6018_APSS_FUSE_CORNERS, -+ .fuse_ref_volt = ipq6018_apss_fuse_ref_volt, -+ .fuse_step_volt = IPQ6018_APSS_FUSE_STEP_VOLT, -+ .cpr_clk_rate = IPQ6018_APSS_CPR_CLOCK_RATE, -+ .boost_fuse_ref_volt = IPQ6018_APSS_BOOST_FUSE_REF_VOLT, -+ .boost_ceiling_volt = IPQ6018_APSS_BOOST_CEILING_VOLT, -+ .boost_floor_volt = IPQ6018_APSS_BOOST_FLOOR_VOLT, -+ .cpr3_fuse_params = &ipq6018_fuse_params, -+ .mem_acc_funcs = &ipq6018_mem_acc_funcs, -+}; -+ -+static const struct cpr4_reg_data ipq9574_cpr_apss = { -+ .cpr_valid_fuse_count = IPQ9574_APSS_FUSE_CORNERS, -+ .fuse_ref_volt = ipq9574_apss_fuse_ref_volt, -+ .fuse_step_volt = IPQ9574_APSS_FUSE_STEP_VOLT, -+ .cpr_clk_rate = IPQ6018_APSS_CPR_CLOCK_RATE, -+ .boost_fuse_ref_volt = IPQ6018_APSS_BOOST_FUSE_REF_VOLT, -+ .boost_ceiling_volt = IPQ6018_APSS_BOOST_CEILING_VOLT, -+ .boost_floor_volt = IPQ6018_APSS_BOOST_FLOOR_VOLT, -+ .cpr3_fuse_params = &ipq9574_fuse_params, -+ .mem_acc_funcs = NULL, -+}; -+ -+static struct of_device_id cpr4_regulator_match_table[] = { -+ { -+ .compatible = "qcom,cpr4-ipq807x-apss-regulator", -+ .data = &ipq807x_cpr_apss -+ }, -+ { -+ .compatible = "qcom,cpr4-ipq817x-apss-regulator", -+ .data = &ipq817x_cpr_apss -+ }, -+ { -+ .compatible = "qcom,cpr4-ipq6018-apss-regulator", -+ .data = &ipq6018_cpr_apss -+ }, -+ { -+ .compatible = "qcom,cpr4-ipq9574-apss-regulator", -+ .data = &ipq9574_cpr_apss -+ }, -+ {} -+}; -+ -+static int cpr4_apss_regulator_probe(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ struct cpr3_controller *ctrl; -+ const struct of_device_id *match; -+ struct cpr4_reg_data *cpr_data; -+ int i, rc; -+ -+ if (!dev->of_node) { -+ dev_err(dev, "Device tree node is missing\n"); -+ return -EINVAL; -+ } -+ -+ ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL); -+ if (!ctrl) -+ return -ENOMEM; -+ -+ match = of_match_device(cpr4_regulator_match_table, &pdev->dev); -+ if (!match) -+ return -ENODEV; -+ -+ cpr_data = (struct cpr4_reg_data *)match->data; -+ g_valid_fuse_count = cpr_data->cpr_valid_fuse_count; -+ dev_info(dev, "CPR valid fuse count: %d\n", g_valid_fuse_count); -+ ctrl->cpr_clock_rate = cpr_data->cpr_clk_rate; -+ -+ ctrl->dev = dev; -+ /* Set to false later if anything precludes CPR operation. */ -+ ctrl->cpr_allowed_hw = true; -+ -+ rc = of_property_read_string(dev->of_node, "qcom,cpr-ctrl-name", -+ &ctrl->name); -+ if (rc) { -+ cpr3_err(ctrl, "unable to read qcom,cpr-ctrl-name, rc=%d\n", -+ rc); -+ return rc; -+ } -+ -+ rc = cpr3_map_fuse_base(ctrl, pdev); -+ if (rc) { -+ cpr3_err(ctrl, "could not map fuse base address\n"); -+ return rc; -+ } -+ -+ rc = cpr3_read_tcsr_setting(ctrl, pdev, IPQ807x_APSS_CPR_TCSR_START, -+ IPQ807x_APSS_CPR_TCSR_END); -+ if (rc) { -+ cpr3_err(ctrl, "could not read CPR tcsr setting\n"); -+ return rc; -+ } -+ -+ rc = cpr3_allocate_threads(ctrl, 0, 0); -+ if (rc) { -+ cpr3_err(ctrl, "failed to allocate CPR thread array, rc=%d\n", -+ rc); -+ return rc; -+ } -+ -+ if (ctrl->thread_count != 1) { -+ cpr3_err(ctrl, "expected 1 thread but found %d\n", -+ ctrl->thread_count); -+ return -EINVAL; -+ } -+ -+ rc = cpr4_apss_init_controller(ctrl); -+ if (rc) { -+ if (rc != -EPROBE_DEFER) -+ cpr3_err(ctrl, "failed to initialize CPR controller parameters, rc=%d\n", -+ rc); -+ return rc; -+ } -+ -+ rc = cpr4_apss_init_thread(&ctrl->thread[0]); -+ if (rc) { -+ cpr3_err(ctrl, "thread initialization failed, rc=%d\n", rc); -+ return rc; -+ } -+ -+ for (i = 0; i < ctrl->thread[0].vreg_count; i++) { -+ ctrl->thread[0].vreg[i].cpr4_regulator_data = cpr_data; -+ rc = cpr4_apss_init_regulator(&ctrl->thread[0].vreg[i]); -+ if (rc) { -+ cpr3_err(&ctrl->thread[0].vreg[i], "regulator initialization failed, rc=%d\n", -+ rc); -+ return rc; -+ } -+ } -+ -+ platform_set_drvdata(pdev, ctrl); -+ -+ return cpr3_regulator_register(pdev, ctrl); -+} -+ -+static int cpr4_apss_regulator_remove(struct platform_device *pdev) -+{ -+ struct cpr3_controller *ctrl = platform_get_drvdata(pdev); -+ -+ return cpr3_regulator_unregister(ctrl); -+} -+ -+static struct platform_driver cpr4_apss_regulator_driver = { -+ .driver = { -+ .name = "qcom,cpr4-apss-regulator", -+ .of_match_table = cpr4_regulator_match_table, -+ .owner = THIS_MODULE, -+ }, -+ .probe = cpr4_apss_regulator_probe, -+ .remove = cpr4_apss_regulator_remove, -+ .suspend = cpr4_apss_regulator_suspend, -+ .resume = cpr4_apss_regulator_resume, -+}; -+ -+static int cpr4_regulator_init(void) -+{ -+ return platform_driver_register(&cpr4_apss_regulator_driver); -+} -+ -+static void cpr4_regulator_exit(void) -+{ -+ platform_driver_unregister(&cpr4_apss_regulator_driver); -+} -+ -+MODULE_DESCRIPTION("CPR4 APSS regulator driver"); -+MODULE_LICENSE("GPL v2"); -+ -+arch_initcall(cpr4_regulator_init); -+module_exit(cpr4_regulator_exit); ---- /dev/null -+++ b/include/soc/qcom/socinfo.h -@@ -0,0 +1,463 @@ -+/* Copyright (c) 2009-2014, 2016, 2020, The Linux Foundation. All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 and -+ * only version 2 as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ */ -+ -+#ifndef _ARCH_ARM_MACH_MSM_SOCINFO_H_ -+#define _ARCH_ARM_MACH_MSM_SOCINFO_H_ -+ -+#include -+ -+#define CPU_IPQ8074 323 -+#define CPU_IPQ8072 342 -+#define CPU_IPQ8076 343 -+#define CPU_IPQ8078 344 -+#define CPU_IPQ8070 375 -+#define CPU_IPQ8071 376 -+ -+#define CPU_IPQ8072A 389 -+#define CPU_IPQ8074A 390 -+#define CPU_IPQ8076A 391 -+#define CPU_IPQ8078A 392 -+#define CPU_IPQ8070A 395 -+#define CPU_IPQ8071A 396 -+ -+#define CPU_IPQ8172 397 -+#define CPU_IPQ8173 398 -+#define CPU_IPQ8174 399 -+ -+#define CPU_IPQ6018 402 -+#define CPU_IPQ6028 403 -+#define CPU_IPQ6000 421 -+#define CPU_IPQ6010 422 -+#define CPU_IPQ6005 453 -+ -+#define CPU_IPQ5010 446 -+#define CPU_IPQ5018 447 -+#define CPU_IPQ5028 448 -+#define CPU_IPQ5000 503 -+#define CPU_IPQ0509 504 -+#define CPU_IPQ0518 505 -+ -+#define CPU_IPQ9514 510 -+#define CPU_IPQ9554 512 -+#define CPU_IPQ9570 513 -+#define CPU_IPQ9574 514 -+#define CPU_IPQ9550 511 -+#define CPU_IPQ9510 521 -+ -+static inline int read_ipq_soc_version_major(void) -+{ -+ const int *prop; -+ prop = of_get_property(of_find_node_by_path("/"), "soc_version_major", -+ NULL); -+ -+ if (!prop) -+ return -EINVAL; -+ -+ return le32_to_cpu(*prop); -+} -+ -+static inline int read_ipq_cpu_type(void) -+{ -+ const int *prop; -+ prop = of_get_property(of_find_node_by_path("/"), "cpu_type", NULL); -+ /* -+ * Return Default CPU type if "cpu_type" property is not found in DTSI -+ */ -+ if (!prop) -+ return CPU_IPQ8074; -+ -+ return le32_to_cpu(*prop); -+} -+ -+static inline int cpu_is_ipq8070(void) -+{ -+#ifdef CONFIG_ARCH_QCOM -+ return read_ipq_cpu_type() == CPU_IPQ8070; -+#else -+ return 0; -+#endif -+} -+ -+static inline int cpu_is_ipq8071(void) -+{ -+#ifdef CONFIG_ARCH_QCOM -+ return read_ipq_cpu_type() == CPU_IPQ8071; -+#else -+ return 0; -+#endif -+} -+ -+static inline int cpu_is_ipq8072(void) -+{ -+#ifdef CONFIG_ARCH_QCOM -+ return read_ipq_cpu_type() == CPU_IPQ8072; -+#else -+ return 0; -+#endif -+} -+ -+static inline int cpu_is_ipq8074(void) -+{ -+#ifdef CONFIG_ARCH_QCOM -+ return read_ipq_cpu_type() == CPU_IPQ8074; -+#else -+ return 0; -+#endif -+} -+ -+static inline int cpu_is_ipq8076(void) -+{ -+#ifdef CONFIG_ARCH_QCOM -+ return read_ipq_cpu_type() == CPU_IPQ8076; -+#else -+ return 0; -+#endif -+} -+ -+static inline int cpu_is_ipq8078(void) -+{ -+#ifdef CONFIG_ARCH_QCOM -+ return read_ipq_cpu_type() == CPU_IPQ8078; -+#else -+ return 0; -+#endif -+} -+ -+static inline int cpu_is_ipq8072a(void) -+{ -+#ifdef CONFIG_ARCH_QCOM -+ return read_ipq_cpu_type() == CPU_IPQ8072A; -+#else -+ return 0; -+#endif -+} -+ -+static inline int cpu_is_ipq8074a(void) -+{ -+#ifdef CONFIG_ARCH_QCOM -+ return read_ipq_cpu_type() == CPU_IPQ8074A; -+#else -+ return 0; -+#endif -+} -+ -+static inline int cpu_is_ipq8076a(void) -+{ -+#ifdef CONFIG_ARCH_QCOM -+ return read_ipq_cpu_type() == CPU_IPQ8076A; -+#else -+ return 0; -+#endif -+} -+ -+static inline int cpu_is_ipq8078a(void) -+{ -+#ifdef CONFIG_ARCH_QCOM -+ return read_ipq_cpu_type() == CPU_IPQ8078A; -+#else -+ return 0; -+#endif -+} -+ -+static inline int cpu_is_ipq8070a(void) -+{ -+#ifdef CONFIG_ARCH_QCOM -+ return read_ipq_cpu_type() == CPU_IPQ8070A; -+#else -+ return 0; -+#endif -+} -+ -+static inline int cpu_is_ipq8071a(void) -+{ -+#ifdef CONFIG_ARCH_QCOM -+ return read_ipq_cpu_type() == CPU_IPQ8071A; -+#else -+ return 0; -+#endif -+} -+ -+static inline int cpu_is_ipq8172(void) -+{ -+#ifdef CONFIG_ARCH_QCOM -+ return read_ipq_cpu_type() == CPU_IPQ8172; -+#else -+ return 0; -+#endif -+} -+ -+static inline int cpu_is_ipq8173(void) -+{ -+#ifdef CONFIG_ARCH_QCOM -+ return read_ipq_cpu_type() == CPU_IPQ8173; -+#else -+ return 0; -+#endif -+} -+ -+static inline int cpu_is_ipq8174(void) -+{ -+#ifdef CONFIG_ARCH_QCOM -+ return read_ipq_cpu_type() == CPU_IPQ8174; -+#else -+ return 0; -+#endif -+} -+ -+static inline int cpu_is_ipq6018(void) -+{ -+#ifdef CONFIG_ARCH_QCOM -+ return read_ipq_cpu_type() == CPU_IPQ6018; -+#else -+ return 0; -+#endif -+} -+ -+static inline int cpu_is_ipq6028(void) -+{ -+#ifdef CONFIG_ARCH_QCOM -+ return read_ipq_cpu_type() == CPU_IPQ6028; -+#else -+ return 0; -+#endif -+} -+ -+static inline int cpu_is_ipq6000(void) -+{ -+#ifdef CONFIG_ARCH_QCOM -+ return read_ipq_cpu_type() == CPU_IPQ6000; -+#else -+ return 0; -+#endif -+} -+ -+static inline int cpu_is_ipq6010(void) -+{ -+#ifdef CONFIG_ARCH_QCOM -+ return read_ipq_cpu_type() == CPU_IPQ6010; -+#else -+ return 0; -+#endif -+} -+ -+static inline int cpu_is_ipq6005(void) -+{ -+#ifdef CONFIG_ARCH_QCOM -+ return read_ipq_cpu_type() == CPU_IPQ6005; -+#else -+ return 0; -+#endif -+} -+ -+static inline int cpu_is_ipq5010(void) -+{ -+#ifdef CONFIG_ARCH_QCOM -+ return read_ipq_cpu_type() == CPU_IPQ5010; -+#else -+ return 0; -+#endif -+} -+ -+static inline int cpu_is_ipq5018(void) -+{ -+#ifdef CONFIG_ARCH_QCOM -+ return read_ipq_cpu_type() == CPU_IPQ5018; -+#else -+ return 0; -+#endif -+} -+ -+static inline int cpu_is_ipq5028(void) -+{ -+#ifdef CONFIG_ARCH_QCOM -+ return read_ipq_cpu_type() == CPU_IPQ5028; -+#else -+ return 0; -+#endif -+} -+ -+static inline int cpu_is_ipq5000(void) -+{ -+#ifdef CONFIG_ARCH_QCOM -+ return read_ipq_cpu_type() == CPU_IPQ5000; -+#else -+ return 0; -+#endif -+} -+ -+static inline int cpu_is_ipq0509(void) -+{ -+#ifdef CONFIG_ARCH_QCOM -+ return read_ipq_cpu_type() == CPU_IPQ0509; -+#else -+ return 0; -+#endif -+} -+ -+static inline int cpu_is_ipq0518(void) -+{ -+#ifdef CONFIG_ARCH_QCOM -+ return read_ipq_cpu_type() == CPU_IPQ0518; -+#else -+ return 0; -+#endif -+} -+ -+static inline int cpu_is_ipq9514(void) -+{ -+#ifdef CONFIG_ARCH_QCOM -+ return read_ipq_cpu_type() == CPU_IPQ9514; -+#else -+ return 0; -+#endif -+} -+ -+static inline int cpu_is_ipq9554(void) -+{ -+#ifdef CONFIG_ARCH_QCOM -+ return read_ipq_cpu_type() == CPU_IPQ9554; -+#else -+ return 0; -+#endif -+} -+ -+static inline int cpu_is_ipq9570(void) -+{ -+#ifdef CONFIG_ARCH_QCOM -+ return read_ipq_cpu_type() == CPU_IPQ9570; -+#else -+ return 0; -+#endif -+} -+ -+static inline int cpu_is_ipq9574(void) -+{ -+#ifdef CONFIG_ARCH_QCOM -+ return read_ipq_cpu_type() == CPU_IPQ9574; -+#else -+ return 0; -+#endif -+} -+ -+static inline int cpu_is_ipq9550(void) -+{ -+#ifdef CONFIG_ARCH_QCOM -+ return read_ipq_cpu_type() == CPU_IPQ9550; -+#else -+ return 0; -+#endif -+} -+ -+static inline int cpu_is_ipq9510(void) -+{ -+#ifdef CONFIG_ARCH_QCOM -+ return read_ipq_cpu_type() == CPU_IPQ9510; -+#else -+ return 0; -+#endif -+} -+ -+static inline int cpu_is_ipq807x(void) -+{ -+#ifdef CONFIG_ARCH_QCOM -+ return cpu_is_ipq8072() || cpu_is_ipq8074() || -+ cpu_is_ipq8076() || cpu_is_ipq8078() || -+ cpu_is_ipq8070() || cpu_is_ipq8071() || -+ cpu_is_ipq8072a() || cpu_is_ipq8074a() || -+ cpu_is_ipq8076a() || cpu_is_ipq8078a() || -+ cpu_is_ipq8070a() || cpu_is_ipq8071a() || -+ cpu_is_ipq8172() || cpu_is_ipq8173() || -+ cpu_is_ipq8174(); -+#else -+ return 0; -+#endif -+} -+ -+static inline int cpu_is_ipq60xx(void) -+{ -+#ifdef CONFIG_ARCH_QCOM -+ return cpu_is_ipq6018() || cpu_is_ipq6028() || -+ cpu_is_ipq6000() || cpu_is_ipq6010() || -+ cpu_is_ipq6005(); -+#else -+ return 0; -+#endif -+} -+ -+static inline int cpu_is_ipq50xx(void) -+{ -+#ifdef CONFIG_ARCH_QCOM -+ return cpu_is_ipq5010() || cpu_is_ipq5018() || -+ cpu_is_ipq5028() || cpu_is_ipq5000() || -+ cpu_is_ipq0509() || cpu_is_ipq0518(); -+#else -+ return 0; -+#endif -+} -+ -+static inline int cpu_is_ipq95xx(void) -+{ -+#ifdef CONFIG_ARCH_QCOM -+ return cpu_is_ipq9514() || cpu_is_ipq9554() || -+ cpu_is_ipq9570() || cpu_is_ipq9574() || -+ cpu_is_ipq9550() || cpu_is_ipq9510(); -+#else -+ return 0; -+#endif -+} -+ -+static inline int cpu_is_nss_crypto_enabled(void) -+{ -+#ifdef CONFIG_ARCH_QCOM -+ return cpu_is_ipq807x() || cpu_is_ipq60xx() || -+ cpu_is_ipq50xx() || cpu_is_ipq9570() || -+ cpu_is_ipq9550() || cpu_is_ipq9574() || -+ cpu_is_ipq9554(); -+#else -+ return 0; -+#endif -+} -+ -+static inline int cpu_is_internal_wifi_enabled(void) -+{ -+#ifdef CONFIG_ARCH_QCOM -+ return cpu_is_ipq807x() || cpu_is_ipq60xx() || -+ cpu_is_ipq50xx() || cpu_is_ipq9514() || -+ cpu_is_ipq9554() || cpu_is_ipq9574(); -+#else -+ return 0; -+#endif -+} -+ -+static inline int cpu_is_uniphy1_enabled(void) -+{ -+#ifdef CONFIG_ARCH_QCOM -+ return cpu_is_ipq807x() || cpu_is_ipq60xx() || -+ cpu_is_ipq9554() || cpu_is_ipq9570() || -+ cpu_is_ipq9574() || cpu_is_ipq9550(); -+#else -+ return 0; -+#endif -+} -+ -+static inline int cpu_is_uniphy2_enabled(void) -+{ -+#ifdef CONFIG_ARCH_QCOM -+ return cpu_is_ipq807x() || cpu_is_ipq9570() || -+ cpu_is_ipq9574(); -+#else -+ return 0; -+#endif -+} -+ -+#endif /* _ARCH_ARM_MACH_MSM_SOCINFO_H_ */ diff --git a/target/linux/ipq60xx/patches-5.15/0138-arm64-dts-qcom-ipq6018-add-usb3-DT-description.patch b/target/linux/ipq60xx/patches-5.15/0138-arm64-dts-qcom-ipq6018-add-usb3-DT-description.patch deleted file mode 100644 index cfb6288bb..000000000 --- a/target/linux/ipq60xx/patches-5.15/0138-arm64-dts-qcom-ipq6018-add-usb3-DT-description.patch +++ /dev/null @@ -1,110 +0,0 @@ -From 20bb9e3dd2e4896f1bbaecd952b48bdc3200fc97 Mon Sep 17 00:00:00 2001 -From: Kathiravan T -Date: Tue, 31 Aug 2021 08:57:32 +0300 -Subject: [PATCH] arm64: dts: qcom: ipq6018: add usb3 DT description - -Based on downstream codeaurora code. - -Tested (USB2 only) on IPQ6010 based hardware. - -Signed-off-by: Kathiravan T -Signed-off-by: Baruch Siach -[bjorn: Changed dwc3 node name to usb, per binding] -Signed-off-by: Bjorn Andersson -Link: https://lore.kernel.org/r/ebc2d340d566fa2d43127e253d5b8b134a87a78e.1630389452.git.baruch@tkos.co.il ---- - arch/arm64/boot/dts/qcom/ipq6018.dtsi | 83 +++++++++++++++++++++++++++ - 1 file changed, 83 insertions(+) - ---- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi -@@ -664,6 +664,89 @@ - }; - }; - -+ ssphy_0: ssphy@78000 { -+ compatible = "qcom,ipq6018-qmp-usb3-phy"; -+ reg = <0x0 0x78000 0x0 0x1C4>; -+ #address-cells = <2>; -+ #size-cells = <2>; -+ #clock-cells = <1>; -+ ranges; -+ -+ clocks = <&gcc GCC_USB0_AUX_CLK>, -+ <&gcc GCC_USB0_PHY_CFG_AHB_CLK>, <&xo>; -+ clock-names = "aux", "cfg_ahb", "ref"; -+ -+ resets = <&gcc GCC_USB0_PHY_BCR>, -+ <&gcc GCC_USB3PHY_0_PHY_BCR>; -+ reset-names = "phy","common"; -+ status = "disabled"; -+ -+ usb0_ssphy: lane@78200 { -+ reg = <0x0 0x00078200 0x0 0x130>, /* Tx */ -+ <0x0 0x00078400 0x0 0x200>, /* Rx */ -+ <0x0 0x00078800 0x0 0x1F8>, /* PCS */ -+ <0x0 0x00078600 0x0 0x044>; /* PCS misc */ -+ #phy-cells = <0>; -+ clocks = <&gcc GCC_USB0_PIPE_CLK>; -+ clock-names = "pipe0"; -+ clock-output-names = "gcc_usb0_pipe_clk_src"; -+ }; -+ }; -+ -+ qusb_phy_0: qusb@79000 { -+ compatible = "qcom,ipq6018-qusb2-phy"; -+ reg = <0x0 0x079000 0x0 0x180>; -+ #phy-cells = <0>; -+ -+ clocks = <&gcc GCC_USB0_PHY_CFG_AHB_CLK>, -+ <&xo>; -+ clock-names = "cfg_ahb", "ref"; -+ -+ resets = <&gcc GCC_QUSB2_0_PHY_BCR>; -+ status = "disabled"; -+ }; -+ -+ usb3: usb3@8A00000 { -+ compatible = "qcom,ipq6018-dwc3", "qcom,dwc3"; -+ reg = <0x0 0x8AF8800 0x0 0x400>; -+ #address-cells = <2>; -+ #size-cells = <2>; -+ ranges; -+ -+ clocks = <&gcc GCC_SYS_NOC_USB0_AXI_CLK>, -+ <&gcc GCC_USB0_MASTER_CLK>, -+ <&gcc GCC_USB0_SLEEP_CLK>, -+ <&gcc GCC_USB0_MOCK_UTMI_CLK>; -+ clock-names = "sys_noc_axi", -+ "master", -+ "sleep", -+ "mock_utmi"; -+ -+ assigned-clocks = <&gcc GCC_SYS_NOC_USB0_AXI_CLK>, -+ <&gcc GCC_USB0_MASTER_CLK>, -+ <&gcc GCC_USB0_MOCK_UTMI_CLK>; -+ assigned-clock-rates = <133330000>, -+ <133330000>, -+ <20000000>; -+ -+ resets = <&gcc GCC_USB0_BCR>; -+ status = "disabled"; -+ -+ dwc_0: usb@8A00000 { -+ compatible = "snps,dwc3"; -+ reg = <0x0 0x8A00000 0x0 0xcd00>; -+ interrupts = ; -+ phys = <&qusb_phy_0>, <&usb0_ssphy>; -+ phy-names = "usb2-phy", "usb3-phy"; -+ tx-fifo-resize; -+ snps,is-utmi-l1-suspend; -+ snps,hird-threshold = /bits/ 8 <0x0>; -+ snps,dis_u2_susphy_quirk; -+ snps,dis_u3_susphy_quirk; -+ snps,ref-clock-period-ns = <0x32>; -+ dr_mode = "host"; -+ }; -+ }; - }; - - wcss: wcss-smp2p { diff --git a/target/linux/ipq60xx/patches-5.15/0140-arm64-dts-qcom-ipq6018-Remove-unused-qcom_config-pipe-trust-reg.patch b/target/linux/ipq60xx/patches-5.15/0140-arm64-dts-qcom-ipq6018-Remove-unused-qcom_config-pipe-trust-reg.patch deleted file mode 100644 index 1f5256a1c..000000000 --- a/target/linux/ipq60xx/patches-5.15/0140-arm64-dts-qcom-ipq6018-Remove-unused-qcom_config-pipe-trust-reg.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 62b177fcdfdfda69f3a0cb740f8b3ac24f95e8c1 Mon Sep 17 00:00:00 2001 -From: Bhupesh Sharma -Date: Wed, 13 Oct 2021 16:25:23 +0530 -Subject: [PATCH] arm64: dts: qcom: ipq6018: Remove unused - 'qcom,config-pipe-trust-reg' property - -'qcom,config-pipe-trust-reg' property doesn't seem to be -used by the qcom, bam_dma driver, so remove the same -from 'ipq6018' dts. - -This is a preparatory patch for subsequent patch in -this series which converts the qcom_bam_dma device-tree -binding into YAML format. - -Without this change, 'make dtbs_check' leads to the following -error: - $ arch/arm64/boot/dts/qcom/ipq6018-cp01-c1.dt.yaml: - dma-controller@704000: 'qcom,config-pipe-trust-reg' does not match - any of the regexes: 'pinctrl-[0-9]+' - -Fix the same. - -Cc: Thara Gopinath -Cc: Bjorn Andersson -Cc: Rob Herring -Signed-off-by: Bhupesh Sharma -Signed-off-by: Bjorn Andersson -Link: https://lore.kernel.org/r/20211013105541.68045-3-bhupesh.sharma@linaro.org ---- - arch/arm64/boot/dts/qcom/ipq6018.dtsi | 1 - - 1 file changed, 1 deletion(-) - ---- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi -@@ -195,7 +195,6 @@ - #dma-cells = <1>; - qcom,ee = <1>; - qcom,controlled-remotely; -- qcom,config-pipe-trust-reg = <0>; - }; - - crypto: crypto@73a000 { diff --git a/target/linux/ipq60xx/patches-5.15/0141-arm64-dts-qcom-ipq6018-Remove-unused-iface_clk-property.patch b/target/linux/ipq60xx/patches-5.15/0141-arm64-dts-qcom-ipq6018-Remove-unused-iface_clk-property.patch deleted file mode 100644 index 2d328d86b..000000000 --- a/target/linux/ipq60xx/patches-5.15/0141-arm64-dts-qcom-ipq6018-Remove-unused-iface_clk-property.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 82f07cbd408993551bd3e4cf51da1bb822f61f26 Mon Sep 17 00:00:00 2001 -From: Bhupesh Sharma -Date: Wed, 13 Oct 2021 16:25:24 +0530 -Subject: [PATCH] arm64: dts: qcom: ipq6018: Remove unused 'iface_clk' property - from dma-controller node - -'iface_clk' clock is not used by the -qcom, bam_dma driver, so remove the same from 'ipq6018' dts. - -This is a preparatory patch for subsequent patch in -this series which converts the qcom_bam_dma device-tree -binding into YAML format. - -Without this change, 'make dtbs_check' leads to the following -error: - $ arch/arm64/boot/dts/qcom/ipq6018-cp01-c1.dt.yaml: - dma-controller@7984000: clock-names: ['iface_clk', 'bam_clk'] - is too long - -Fix the same. - -Cc: Thara Gopinath -Cc: Bjorn Andersson -Cc: Rob Herring -Signed-off-by: Bhupesh Sharma -Signed-off-by: Bjorn Andersson -Link: https://lore.kernel.org/r/20211013105541.68045-4-bhupesh.sharma@linaro.org ---- - arch/arm64/boot/dts/qcom/ipq6018.dtsi | 5 ++--- - 1 file changed, 2 insertions(+), 3 deletions(-) - ---- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi -@@ -341,9 +341,8 @@ - compatible = "qcom,bam-v1.7.0"; - reg = <0x0 0x07984000 0x0 0x1a000>; - interrupts = ; -- clocks = <&gcc GCC_QPIC_CLK>, -- <&gcc GCC_QPIC_AHB_CLK>; -- clock-names = "iface_clk", "bam_clk"; -+ clocks = <&gcc GCC_QPIC_AHB_CLK>; -+ clock-names = "bam_clk"; - #dma-cells = <1>; - qcom,ee = <0>; - status = "disabled"; diff --git a/target/linux/ipq60xx/patches-5.15/0142-arm64-dts-qcom-ipq6018-add-pcie-max-link-speed.patch b/target/linux/ipq60xx/patches-5.15/0142-arm64-dts-qcom-ipq6018-add-pcie-max-link-speed.patch deleted file mode 100644 index 4fecc77e1..000000000 --- a/target/linux/ipq60xx/patches-5.15/0142-arm64-dts-qcom-ipq6018-add-pcie-max-link-speed.patch +++ /dev/null @@ -1,26 +0,0 @@ -From e3e8a472429923d1c430bf388e9e3df1d9cc63a7 Mon Sep 17 00:00:00 2001 -From: Baruch Siach -Date: Mon, 27 Dec 2021 08:46:03 +0200 -Subject: [PATCH] arm64: dts: qcom: ipq6018: add pcie max-link-speed - -Add the generic 'max-link-speed' property to describe the IPQ6018 PCIe -link generation limit. This allows the generic dwc code to configure the -link speed correctly. - -Signed-off-by: Baruch Siach -Signed-off-by: Bjorn Andersson -Link: https://lore.kernel.org/r/fcf41277cf8529437374a5c10b2b1fcad30cd7c2.1640587131.git.baruch@tkos.co.il ---- - arch/arm64/boot/dts/qcom/ipq6018.dtsi | 1 + - 1 file changed, 1 insertion(+) - ---- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi -@@ -420,6 +420,7 @@ - linux,pci-domain = <0>; - bus-range = <0x00 0xff>; - num-lanes = <1>; -+ max-link-speed = <3>; - #address-cells = <3>; - #size-cells = <2>; - diff --git a/target/linux/ipq60xx/patches-5.15/0143-arm64-dts-qcom-ipq6018-fix-usb-reference-period.patch b/target/linux/ipq60xx/patches-5.15/0143-arm64-dts-qcom-ipq6018-fix-usb-reference-period.patch deleted file mode 100644 index 5f015ed1e..000000000 --- a/target/linux/ipq60xx/patches-5.15/0143-arm64-dts-qcom-ipq6018-fix-usb-reference-period.patch +++ /dev/null @@ -1,29 +0,0 @@ -From d1c10ab1494f09eb12fa6e58fc78bb28d44922ae Mon Sep 17 00:00:00 2001 -From: Baruch Siach -Date: Thu, 20 Jan 2022 20:43:41 +0200 -Subject: [PATCH] arm64: dts: qcom: ipq6018: fix usb reference period - -Reference clock period for rate of 24MHz is 41ns (0x29). - -Link: https://lore.kernel.org/r/1965fc315525b8ab26cf9f71f939c24d@codeaurora.org -Link: https://lore.kernel.org/r/a1932eba-564c-fe32-f220-53aa75250105@seco.com -Fixes: 20bb9e3dd2e4 ("arm64: dts: qcom: ipq6018: add usb3 DT description") -Reported-by: Kathiravan T -Signed-off-by: Baruch Siach -Signed-off-by: Bjorn Andersson -Link: https://lore.kernel.org/r/4f4df55cf44cd0fd7d773aca171d4f48662fb1a5.1642704221.git.baruch@tkos.co.il ---- - arch/arm64/boot/dts/qcom/ipq6018.dtsi | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi -@@ -742,7 +742,7 @@ - snps,hird-threshold = /bits/ 8 <0x0>; - snps,dis_u2_susphy_quirk; - snps,dis_u3_susphy_quirk; -- snps,ref-clock-period-ns = <0x32>; -+ snps,ref-clock-period-ns = <0x29>; - dr_mode = "host"; - }; - }; diff --git a/target/linux/ipq60xx/patches-5.15/0144-arm64-dts-ipq6018-Use-reference-clock-to-set-dwc3-period.patch b/target/linux/ipq60xx/patches-5.15/0144-arm64-dts-ipq6018-Use-reference-clock-to-set-dwc3-period.patch deleted file mode 100644 index ea7829d22..000000000 --- a/target/linux/ipq60xx/patches-5.15/0144-arm64-dts-ipq6018-Use-reference-clock-to-set-dwc3-period.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 5726079cd4860c190722445e01e1007e40a9ccb4 Mon Sep 17 00:00:00 2001 -From: Sean Anderson -Date: Thu, 27 Jan 2022 15:06:36 -0500 -Subject: [PATCH] arm64: dts: ipq6018: Use reference clock to set dwc3 period - -Instead of manually setting snps,ref-clock-period-ns, we can let the -driver calculate it automatically from the "ref" clock. I haven't -reviewed this board's schematics, so please let me know if this is the -wrong 24MHz clock to use. - -Signed-off-by: Sean Anderson -Link: https://lore.kernel.org/r/20220127200636.1456175-8-sean.anderson@seco.com -Signed-off-by: Greg Kroah-Hartman ---- - arch/arm64/boot/dts/qcom/ipq6018.dtsi | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - ---- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi -@@ -737,12 +737,13 @@ - interrupts = ; - phys = <&qusb_phy_0>, <&usb0_ssphy>; - phy-names = "usb2-phy", "usb3-phy"; -+ clocks = <&xo>; -+ clock-names = "ref"; - tx-fifo-resize; - snps,is-utmi-l1-suspend; - snps,hird-threshold = /bits/ 8 <0x0>; - snps,dis_u2_susphy_quirk; - snps,dis_u3_susphy_quirk; -- snps,ref-clock-period-ns = <0x29>; - dr_mode = "host"; - }; - }; diff --git a/target/linux/ipq60xx/patches-5.15/0145-arm64-dts-qcom-ipq6018-enable-the-GICv2m-supporte.patch b/target/linux/ipq60xx/patches-5.15/0145-arm64-dts-qcom-ipq6018-enable-the-GICv2m-supporte.patch deleted file mode 100644 index 90dacf749..000000000 --- a/target/linux/ipq60xx/patches-5.15/0145-arm64-dts-qcom-ipq6018-enable-the-GICv2m-supporte.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 3d44861d006b18649306cbade242c865e9068b6e Mon Sep 17 00:00:00 2001 -From: Kathiravan T -Date: Tue, 8 Feb 2022 21:05:25 +0530 -Subject: [PATCH] arm64: dts: qcom: ipq6018: enable the GICv2m support - -GIC used in the IPQ6018 SoCs has one instance of the GICv2m extension, -which supports upto 32 MSI interrupts. Lets add support for the same. - -Signed-off-by: Kathiravan T -Signed-off-by: Bjorn Andersson -Link: https://lore.kernel.org/r/1644334525-11577-3-git-send-email-quic_kathirav@quicinc.com ---- - arch/arm64/boot/dts/qcom/ipq6018.dtsi | 9 +++++++++ - 1 file changed, 9 insertions(+) - ---- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi -@@ -368,6 +368,8 @@ - - intc: interrupt-controller@b000000 { - compatible = "qcom,msm-qgic2"; -+ #address-cells = <2>; -+ #size-cells = <2>; - interrupt-controller; - #interrupt-cells = <0x3>; - reg = <0x0 0x0b000000 0x0 0x1000>, /*GICD*/ -@@ -375,6 +377,13 @@ - <0x0 0x0b001000 0x0 0x1000>, /*GICH*/ - <0x0 0x0b004000 0x0 0x1000>; /*GICV*/ - interrupts = ; -+ ranges = <0 0 0 0xb00a000 0 0xffd>; -+ -+ v2m@0 { -+ compatible = "arm,gic-v2m-frame"; -+ msi-controller; -+ reg = <0x0 0x0 0x0 0xffd>; -+ }; - }; - - pcie_phy: phy@84000 { diff --git a/target/linux/ipq60xx/patches-5.15/0146-arm64-dts-qcom-ipq6018-drop-the-clock-frequency-property.patch b/target/linux/ipq60xx/patches-5.15/0146-arm64-dts-qcom-ipq6018-drop-the-clock-frequency-property.patch deleted file mode 100644 index 082a42fe5..000000000 --- a/target/linux/ipq60xx/patches-5.15/0146-arm64-dts-qcom-ipq6018-drop-the-clock-frequency-property.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 01b8c4aff332ecc13fbafc16550e621ba969c167 Mon Sep 17 00:00:00 2001 -From: Kathiravan T -Date: Wed, 2 Feb 2022 22:05:09 +0530 -Subject: [PATCH] arm64: dts: qcom: ipq6018: drop the clock-frequency property - -clock-frequency for IPQ6018 SoCs should be 24MHz, not 19.2MHz. Rather -than correcting it, drop the property itself since its already -configured by the bootloader. - -Signed-off-by: Kathiravan T -Signed-off-by: Bjorn Andersson -Link: https://lore.kernel.org/r/1643819709-5410-3-git-send-email-quic_kathirav@quicinc.com ---- - arch/arm64/boot/dts/qcom/ipq6018.dtsi | 1 - - 1 file changed, 1 deletion(-) - ---- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi -@@ -523,7 +523,6 @@ - ranges; - compatible = "arm,armv7-timer-mem"; - reg = <0x0 0x0b120000 0x0 0x1000>; -- clock-frequency = <19200000>; - - frame@b120000 { - frame-number = <0>; diff --git a/target/linux/ipq60xx/patches-5.15/0147-arm64-dts-qcom-align-dmas-in-I2C-SPI-UART-with-DT-schema.patch b/target/linux/ipq60xx/patches-5.15/0147-arm64-dts-qcom-align-dmas-in-I2C-SPI-UART-with-DT-schema.patch deleted file mode 100644 index cd37ec549..000000000 --- a/target/linux/ipq60xx/patches-5.15/0147-arm64-dts-qcom-align-dmas-in-I2C-SPI-UART-with-DT-schema.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 0e1b27f4f69e86b8b62ba5bedb78936341433247 Mon Sep 17 00:00:00 2001 -From: Krzysztof Kozlowski -Date: Tue, 5 Apr 2022 08:34:43 +0200 -Subject: [PATCH] arm64: dts: qcom: align dmas in I2C/SPI/UART with DT schema - -The DT schema expects dma channels in tx-rx order. No functional -change. - -Signed-off-by: Krzysztof Kozlowski -Signed-off-by: Bjorn Andersson -Link: https://lore.kernel.org/r/20220405063451.12011-2-krzysztof.kozlowski@linaro.org ---- - arch/arm64/boot/dts/qcom/ipq6018.dtsi | 8 +++---- - 1 files changed, 3 insertions(+), 5 deletions(-) - ---- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi -@@ -317,8 +317,8 @@ - <&gcc GCC_BLSP1_QUP2_I2C_APPS_CLK>; - clock-names = "iface", "core"; - clock-frequency = <400000>; -- dmas = <&blsp_dma 15>, <&blsp_dma 14>; -- dma-names = "rx", "tx"; -+ dmas = <&blsp_dma 14>, <&blsp_dma 15>; -+ dma-names = "tx", "rx"; - status = "disabled"; - }; - -@@ -332,8 +332,8 @@ - <&gcc GCC_BLSP1_QUP3_I2C_APPS_CLK>; - clock-names = "iface", "core"; - clock-frequency = <400000>; -- dmas = <&blsp_dma 17>, <&blsp_dma 16>; -- dma-names = "rx", "tx"; -+ dmas = <&blsp_dma 16>, <&blsp_dma 17>; -+ dma-names = "tx", "rx"; - status = "disabled"; - }; - diff --git a/target/linux/ipq60xx/patches-5.15/0148-arm64-dts-qcom-align-clocks-in-I2C-SPI-with-DT-schema.patch b/target/linux/ipq60xx/patches-5.15/0148-arm64-dts-qcom-align-clocks-in-I2C-SPI-with-DT-schema.patch deleted file mode 100644 index 2b297d70f..000000000 --- a/target/linux/ipq60xx/patches-5.15/0148-arm64-dts-qcom-align-clocks-in-I2C-SPI-with-DT-schema.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 2374b99e19ac7f2beca2d4e62ebb96803db0e66b Mon Sep 17 00:00:00 2001 -From: Krzysztof Kozlowski -Date: Tue, 5 Apr 2022 08:34:44 +0200 -Subject: [PATCH] arm64: dts: qcom: align clocks in I2C/SPI with DT schema - -The DT schema expects clocks core-iface order. No functional change. - -Signed-off-by: Krzysztof Kozlowski -Signed-off-by: Bjorn Andersson -Link: https://lore.kernel.org/r/20220405063451.12011-3-krzysztof.kozlowski@linaro.org ---- - arch/arm64/boot/dts/qcom/ipq6018.dtsi | 12 ++--- - 1 files changed, 6 insertions(+), 6 deletions(-) - ---- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi -@@ -313,9 +313,9 @@ - #size-cells = <0>; - reg = <0x0 0x078b6000 0x0 0x600>; - interrupts = ; -- clocks = <&gcc GCC_BLSP1_AHB_CLK>, -- <&gcc GCC_BLSP1_QUP2_I2C_APPS_CLK>; -- clock-names = "iface", "core"; -+ clocks = <&gcc GCC_BLSP1_QUP2_I2C_APPS_CLK>, -+ <&gcc GCC_BLSP1_AHB_CLK>; -+ clock-names = "core", "iface"; - clock-frequency = <400000>; - dmas = <&blsp_dma 14>, <&blsp_dma 15>; - dma-names = "tx", "rx"; -@@ -328,9 +328,9 @@ - #size-cells = <0>; - reg = <0x0 0x078b7000 0x0 0x600>; - interrupts = ; -- clocks = <&gcc GCC_BLSP1_AHB_CLK>, -- <&gcc GCC_BLSP1_QUP3_I2C_APPS_CLK>; -- clock-names = "iface", "core"; -+ clocks = <&gcc GCC_BLSP1_QUP3_I2C_APPS_CLK>, -+ <&gcc GCC_BLSP1_AHB_CLK>; -+ clock-names = "core", "iface"; - clock-frequency = <400000>; - dmas = <&blsp_dma 16>, <&blsp_dma 17>; - dma-names = "tx", "rx"; diff --git a/target/linux/ipq60xx/patches-5.15/0149-arm64-dts-qcom-ipq6018-Fix-qmp-usb3-phy-node.patch b/target/linux/ipq60xx/patches-5.15/0149-arm64-dts-qcom-ipq6018-Fix-qmp-usb3-phy-node.patch deleted file mode 100644 index 5cd08b7bc..000000000 --- a/target/linux/ipq60xx/patches-5.15/0149-arm64-dts-qcom-ipq6018-Fix-qmp-usb3-phy-node.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 7011db96f69316e8055961b366ac92b6c28403dd Mon Sep 17 00:00:00 2001 -From: Bhupesh Sharma -Date: Mon, 28 Feb 2022 18:00:17 +0530 -Subject: [PATCH] arm64: dts: qcom: ipq6018: Fix qmp usb3 phy node - -Fix the following 'make dtbs_check' warning(s) by -using phy@ instead of lanes@ and by moving '#clock-cells' to -sub-node: - -arch/arm64/boot/dts/qcom/ipq6018-cp01-c1.dt.yaml: ssphy@78000: - 'lane@78200' does not match any of the regexes: '^phy@[0-9a-f]+$', 'pinctrl-[0-9]+' - -Cc: Bjorn Andersson -Cc: Rob Herring -Signed-off-by: Bhupesh Sharma -Reviewed-by: Shawn Guo -[bjorn: s/clock-names/clock-cells/ per Shawn's feedback] -Signed-off-by: Bjorn Andersson -Link: https://lore.kernel.org/r/20220228123019.382037-7-bhupesh.sharma@linaro.org ---- - arch/arm64/boot/dts/qcom/ipq6018.dtsi | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi -@@ -676,7 +676,6 @@ - reg = <0x0 0x78000 0x0 0x1C4>; - #address-cells = <2>; - #size-cells = <2>; -- #clock-cells = <1>; - ranges; - - clocks = <&gcc GCC_USB0_AUX_CLK>, -@@ -688,12 +687,13 @@ - reset-names = "phy","common"; - status = "disabled"; - -- usb0_ssphy: lane@78200 { -+ usb0_ssphy: phy@78200 { - reg = <0x0 0x00078200 0x0 0x130>, /* Tx */ - <0x0 0x00078400 0x0 0x200>, /* Rx */ - <0x0 0x00078800 0x0 0x1F8>, /* PCS */ - <0x0 0x00078600 0x0 0x044>; /* PCS misc */ - #phy-cells = <0>; -+ #clock-cells = <1>; - clocks = <&gcc GCC_USB0_PIPE_CLK>; - clock-names = "pipe0"; - clock-output-names = "gcc_usb0_pipe_clk_src"; diff --git a/target/linux/ipq60xx/patches-5.15/0150-arm64-dts-qcom-correct-DWC3-node-names-and-unit-addresses.patch b/target/linux/ipq60xx/patches-5.15/0150-arm64-dts-qcom-correct-DWC3-node-names-and-unit-addresses.patch deleted file mode 100644 index b2e2467fa..000000000 --- a/target/linux/ipq60xx/patches-5.15/0150-arm64-dts-qcom-correct-DWC3-node-names-and-unit-addresses.patch +++ /dev/null @@ -1,45 +0,0 @@ -From b77a1c4d6b058d801645a9f46030e7f8829628b2 Mon Sep 17 00:00:00 2001 -From: Krzysztof Kozlowski -Date: Wed, 4 May 2022 15:19:16 +0200 -Subject: [PATCH] arm64: dts: qcom: correct DWC3 node names and unit addresses - -Align DWC3 USB node names with DT schema ("usb" is expected) and correct -the unit addresses to match the "reg" property. This also implies -overriding nodes by label, instead of full path. - -Signed-off-by: Krzysztof Kozlowski -Link: https://lore.kernel.org/r/20220504131923.214367-7-krzysztof.kozlowski@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - arch/arm64/boot/dts/qcom/ipq6018.dtsi | 6 +++--- - 1 files changed, 3 insertions(+), 3 deletions(-) - ---- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi -@@ -636,7 +636,7 @@ - status = "disabled"; - }; - -- usb2: usb2@7000000 { -+ usb2: usb@70f8800 { - compatible = "qcom,ipq6018-dwc3", "qcom,dwc3"; - reg = <0x0 0x070F8800 0x0 0x400>; - #address-cells = <2>; -@@ -713,7 +713,7 @@ - status = "disabled"; - }; - -- usb3: usb3@8A00000 { -+ usb3: usb@8af8800 { - compatible = "qcom,ipq6018-dwc3", "qcom,dwc3"; - reg = <0x0 0x8AF8800 0x0 0x400>; - #address-cells = <2>; -@@ -739,7 +739,7 @@ - resets = <&gcc GCC_USB0_BCR>; - status = "disabled"; - -- dwc_0: usb@8A00000 { -+ dwc_0: usb@8a00000 { - compatible = "snps,dwc3"; - reg = <0x0 0x8A00000 0x0 0xcd00>; - interrupts = ; diff --git a/target/linux/ipq60xx/patches-5.15/0151-arm64-dts-qcom-align-DWC3-USB-clocks-with-DT-schema.patch b/target/linux/ipq60xx/patches-5.15/0151-arm64-dts-qcom-align-DWC3-USB-clocks-with-DT-schema.patch deleted file mode 100644 index 833c991a5..000000000 --- a/target/linux/ipq60xx/patches-5.15/0151-arm64-dts-qcom-align-DWC3-USB-clocks-with-DT-schema.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 8d5fd4e4d4e3c128d5afa925bf98c98e66a5205b Mon Sep 17 00:00:00 2001 -From: Krzysztof Kozlowski -Date: Wed, 4 May 2022 15:19:22 +0200 -Subject: [PATCH] arm64: dts: qcom: align DWC3 USB clocks with DT schema - -Align order of clocks and their names with Qualcomm DWC3 USB DT schema. -No functional impact expected. - -Signed-off-by: Krzysztof Kozlowski -Link: https://lore.kernel.org/r/20220504131923.214367-13-krzysztof.kozlowski@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - arch/arm64/boot/dts/qcom/ipq6018.dtsi | 6 +++--- - 1 files changed, 3 insertions(+), 3 deletions(-) - ---- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi -@@ -645,7 +645,7 @@ - clocks = <&gcc GCC_USB1_MASTER_CLK>, - <&gcc GCC_USB1_SLEEP_CLK>, - <&gcc GCC_USB1_MOCK_UTMI_CLK>; -- clock-names = "master", -+ clock-names = "core", - "sleep", - "mock_utmi"; - -@@ -724,8 +724,8 @@ - <&gcc GCC_USB0_MASTER_CLK>, - <&gcc GCC_USB0_SLEEP_CLK>, - <&gcc GCC_USB0_MOCK_UTMI_CLK>; -- clock-names = "sys_noc_axi", -- "master", -+ clock-names = "cfg_noc", -+ "core", - "sleep", - "mock_utmi"; - diff --git a/target/linux/ipq60xx/patches-5.15/0152-arm64-dts-qcom-align-OPP-table-names-with-DT-schema.patch b/target/linux/ipq60xx/patches-5.15/0152-arm64-dts-qcom-align-OPP-table-names-with-DT-schema.patch deleted file mode 100644 index 6a3b4f1a2..000000000 --- a/target/linux/ipq60xx/patches-5.15/0152-arm64-dts-qcom-align-OPP-table-names-with-DT-schema.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0e3e654696074b304302c7cc2a67314b7875f1ae Mon Sep 17 00:00:00 2001 -From: Krzysztof Kozlowski -Date: Mon, 27 Jun 2022 11:32:50 +0200 -Subject: [PATCH] arm64: dts: qcom: align OPP table names with DT schema - -DT schema expects names of operating points tables to start with -"opp-table": - - ipq6018-cp01-c1.dtb: cpu_opp_table: $nodename:0: 'cpu_opp_table' does not match '^opp-table(-[a-z0-9]+)?$' - -Use hyphens instead of underscores, fix the names to match DT schema or -remove the prefix entirely when it is not needed. - -Signed-off-by: Krzysztof Kozlowski -Reviewed-by: Bjorn Andersson -Signed-off-by: Bjorn Andersson -Link: https://lore.kernel.org/r/20220627093250.84391-1-krzysztof.kozlowski@linaro.org ---- - arch/arm64/boot/dts/qcom/ipq6018.dtsi | 2 +- - 1 files changed, 1 insertions(+), 1 deletions(-) - ---- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi -@@ -87,7 +87,7 @@ - }; - }; - -- cpu_opp_table: cpu_opp_table { -+ cpu_opp_table: opp-table-cpu { - compatible = "operating-points-v2"; - opp-shared; - diff --git a/target/linux/ipq60xx/patches-5.15/0153-arm64-dts-qcom-timer-should-use-only-32-bit-size.patch b/target/linux/ipq60xx/patches-5.15/0153-arm64-dts-qcom-timer-should-use-only-32-bit-size.patch deleted file mode 100644 index 23df27f9c..000000000 --- a/target/linux/ipq60xx/patches-5.15/0153-arm64-dts-qcom-timer-should-use-only-32-bit-size.patch +++ /dev/null @@ -1,94 +0,0 @@ -From 458ebdbb8e5d596a462d8125cec74142ff5dfa97 Mon Sep 17 00:00:00 2001 -From: David Heidelberg -Date: Sun, 26 Jun 2022 12:57:59 +0200 -Subject: [PATCH] arm64: dts: qcom: timer should use only 32-bit size - -There's no reason the timer needs > 32-bits of address or size. -Since we using 32-bit size, we need to define ranges properly. - -Fixes warnings as: -``` -arch/arm64/boot/dts/qcom/sdm845-oneplus-fajita.dt.yaml: timer@17c90000: #size-cells:0:0: 1 was expected - From schema: Documentation/devicetree/bindings/timer/arm,arch_timer_mmio.yaml -``` - -Signed-off-by: David Heidelberg -Signed-off-by: Bjorn Andersson -Link: https://lore.kernel.org/r/20220626105800.35586-1-david@ixit.cz ---- - arch/arm64/boot/dts/qcom/ipq6018.dtsi | 22 +++++++++++----------- - 1 files changed, 11 insertions(+), 11 deletions(-) - ---- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi -@@ -518,9 +518,9 @@ - }; - - timer@b120000 { -- #address-cells = <2>; -- #size-cells = <2>; -- ranges; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ ranges = <0 0 0 0x10000000>; - compatible = "arm,armv7-timer-mem"; - reg = <0x0 0x0b120000 0x0 0x1000>; - -@@ -528,49 +528,49 @@ - frame-number = <0>; - interrupts = , - ; -- reg = <0x0 0x0b121000 0x0 0x1000>, -- <0x0 0x0b122000 0x0 0x1000>; -+ reg = <0x0b121000 0x1000>, -+ <0x0b122000 0x1000>; - }; - - frame@b123000 { - frame-number = <1>; - interrupts = ; -- reg = <0x0 0xb123000 0x0 0x1000>; -+ reg = <0x0b123000 0x1000>; - status = "disabled"; - }; - - frame@b124000 { - frame-number = <2>; - interrupts = ; -- reg = <0x0 0x0b124000 0x0 0x1000>; -+ reg = <0x0b124000 0x1000>; - status = "disabled"; - }; - - frame@b125000 { - frame-number = <3>; - interrupts = ; -- reg = <0x0 0x0b125000 0x0 0x1000>; -+ reg = <0x0b125000 0x1000>; - status = "disabled"; - }; - - frame@b126000 { - frame-number = <4>; - interrupts = ; -- reg = <0x0 0x0b126000 0x0 0x1000>; -+ reg = <0x0b126000 0x1000>; - status = "disabled"; - }; - - frame@b127000 { - frame-number = <5>; - interrupts = ; -- reg = <0x0 0x0b127000 0x0 0x1000>; -+ reg = <0x0b127000 0x1000>; - status = "disabled"; - }; - - frame@b128000 { - frame-number = <6>; - interrupts = ; -- reg = <0x0 0x0b128000 0x0 0x1000>; -+ reg = <0x0b128000 0x1000>; - status = "disabled"; - }; - }; diff --git a/target/linux/ipq60xx/patches-5.15/0154-arm64-dts-qcom-adjust-whitespace-around-.patch b/target/linux/ipq60xx/patches-5.15/0154-arm64-dts-qcom-adjust-whitespace-around-.patch deleted file mode 100644 index 89e5eb2c4..000000000 --- a/target/linux/ipq60xx/patches-5.15/0154-arm64-dts-qcom-adjust-whitespace-around-.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 372cf591acbca3bd9a729742ea4c81d7f99f1b6e Mon Sep 17 00:00:00 2001 -From: Krzysztof Kozlowski -Date: Thu, 26 May 2022 22:42:47 +0200 -Subject: [PATCH] arm64: dts: qcom: adjust whitespace around '=' - -Fix whitespace coding style: use single space instead of tabs or -multiple spaces around '=' sign in property assignment. No functional -changes (same DTB). - -Signed-off-by: Krzysztof Kozlowski -Signed-off-by: Bjorn Andersson -Link: https://lore.kernel.org/r/20220526204248.832139-1-krzysztof.kozlowski@linaro.org ---- - arch/arm64/boot/dts/qcom/ipq6018.dtsi | 4 ++-- - 1 files changed, 2 insertions(+), 2 deletions(-) - ---- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi -@@ -316,7 +316,7 @@ - clocks = <&gcc GCC_BLSP1_QUP2_I2C_APPS_CLK>, - <&gcc GCC_BLSP1_AHB_CLK>; - clock-names = "core", "iface"; -- clock-frequency = <400000>; -+ clock-frequency = <400000>; - dmas = <&blsp_dma 14>, <&blsp_dma 15>; - dma-names = "tx", "rx"; - status = "disabled"; -@@ -331,7 +331,7 @@ - clocks = <&gcc GCC_BLSP1_QUP3_I2C_APPS_CLK>, - <&gcc GCC_BLSP1_AHB_CLK>; - clock-names = "core", "iface"; -- clock-frequency = <400000>; -+ clock-frequency = <400000>; - dmas = <&blsp_dma 16>, <&blsp_dma 17>; - dma-names = "tx", "rx"; - status = "disabled"; diff --git a/target/linux/ipq60xx/patches-5.15/0155-arm64-dts-qcom-ipq6018-add-label-to-remoteproc-node.patch b/target/linux/ipq60xx/patches-5.15/0155-arm64-dts-qcom-ipq6018-add-label-to-remoteproc-node.patch deleted file mode 100644 index 304356d56..000000000 --- a/target/linux/ipq60xx/patches-5.15/0155-arm64-dts-qcom-ipq6018-add-label-to-remoteproc-node.patch +++ /dev/null @@ -1,26 +0,0 @@ -From f0b255b4f012055ab12137ecc1b68dfe12b06107 Mon Sep 17 00:00:00 2001 -From: Krzysztof Kozlowski -Date: Tue, 17 May 2022 09:01:10 +0200 -Subject: [PATCH] arm64: dts: qcom: ipq6018: add label to remoteproc node - -glink-edge bindings require label: - - ipq6018-cp01-c1.dtb: glink-edge: 'label' is a required property - -Signed-off-by: Krzysztof Kozlowski -Signed-off-by: Bjorn Andersson -Link: https://lore.kernel.org/r/20220517070113.18023-10-krzysztof.kozlowski@linaro.org ---- - arch/arm64/boot/dts/qcom/ipq6018.dtsi | 1 + - 1 file changed, 1 insertion(+) - ---- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi -@@ -614,6 +614,7 @@ - - glink-edge { - interrupts = ; -+ label = "rtr"; - qcom,remote-pid = <1>; - mboxes = <&apcs_glb 8>; - diff --git a/target/linux/ipq60xx/patches-5.15/0156-arm64-dts-qcom-ipq6018-correct-QUP-peripheral-labels.patch b/target/linux/ipq60xx/patches-5.15/0156-arm64-dts-qcom-ipq6018-correct-QUP-peripheral-labels.patch deleted file mode 100644 index 68b24b1a2..000000000 --- a/target/linux/ipq60xx/patches-5.15/0156-arm64-dts-qcom-ipq6018-correct-QUP-peripheral-labels.patch +++ /dev/null @@ -1,82 +0,0 @@ -From f82c48d468521cd9d1a31797c6f9e6cac6f7c1b3 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Sat, 4 Jun 2022 17:30:03 +0200 -Subject: [PATCH] arm64: dts: qcom: ipq6018: correct QUP peripheral labels - -Current QUP peripheral labels like spi_0 and i2c_0 dont really tell what is -the exact QUP HW being used as there are actually 6 identical QUP HW blocks -for UART, SPI and I2C. -For example current i2c_0 label actually points to the QUP2 I2C HW. - -This style of labeling does not follow what the rest of Qualcomm SoC-s use, -for example IPQ8074 which has the identical QUP blocks. -It also makes it really hard to add the missing QUP DT nodes as there are -multiple missing. - -So utilize the same style as other Qualcomm SoC-s are using and update the -CP01 DTS as its the current sole user of them. - -Signed-off-by: Robert Marko -Signed-off-by: Bjorn Andersson -Link: https://lore.kernel.org/r/20220604153003.55172-1-robimarko@gmail.com ---- - arch/arm64/boot/dts/qcom/ipq6018-cp01-c1.dts | 4 ++-- - arch/arm64/boot/dts/qcom/ipq6018.dtsi | 8 ++++---- - 2 files changed, 6 insertions(+), 6 deletions(-) - ---- a/arch/arm64/boot/dts/qcom/ipq6018-cp01-c1.dts -+++ b/arch/arm64/boot/dts/qcom/ipq6018-cp01-c1.dts -@@ -29,13 +29,13 @@ - status = "okay"; - }; - --&i2c_1 { -+&blsp1_i2c3 { - pinctrl-0 = <&i2c_1_pins>; - pinctrl-names = "default"; - status = "okay"; - }; - --&spi_0 { -+&blsp1_spi1 { - cs-select = <0>; - pinctrl-0 = <&spi_0_pins>; - pinctrl-names = "default"; ---- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi -@@ -277,7 +277,7 @@ - status = "disabled"; - }; - -- spi_0: spi@78b5000 { -+ blsp1_spi1: spi@78b5000 { - compatible = "qcom,spi-qup-v2.2.1"; - #address-cells = <1>; - #size-cells = <0>; -@@ -292,7 +292,7 @@ - status = "disabled"; - }; - -- spi_1: spi@78b6000 { -+ blsp1_spi2: spi@78b6000 { - compatible = "qcom,spi-qup-v2.2.1"; - #address-cells = <1>; - #size-cells = <0>; -@@ -307,7 +307,7 @@ - status = "disabled"; - }; - -- i2c_0: i2c@78b6000 { -+ blsp1_i2c2: i2c@78b6000 { - compatible = "qcom,i2c-qup-v2.2.1"; - #address-cells = <1>; - #size-cells = <0>; -@@ -322,7 +322,7 @@ - status = "disabled"; - }; - -- i2c_1: i2c@78b7000 { /* BLSP1 QUP2 */ -+ blsp1_i2c3: i2c@78b7000 { - compatible = "qcom,i2c-qup-v2.2.1"; - #address-cells = <1>; - #size-cells = <0>; diff --git a/target/linux/ipq60xx/patches-5.15/0157-arm64-dts-qcom-extend-scm-compatible-strings.patch b/target/linux/ipq60xx/patches-5.15/0157-arm64-dts-qcom-extend-scm-compatible-strings.patch deleted file mode 100644 index 48902f55e..000000000 --- a/target/linux/ipq60xx/patches-5.15/0157-arm64-dts-qcom-extend-scm-compatible-strings.patch +++ /dev/null @@ -1,26 +0,0 @@ -From b9c0c0e5da43ff3aa6dd93e2f994dc889dd5b261 Mon Sep 17 00:00:00 2001 -From: David Heidelberg -Date: Sun, 26 Jun 2022 20:32:46 +0200 -Subject: [PATCH] arm64: dts: qcom: extend scm compatible strings - -First device specific compatible, then general one. - -Reviewed-by: Krzysztof Kozlowski -Signed-off-by: David Heidelberg -Signed-off-by: Bjorn Andersson -Link: https://lore.kernel.org/r/20220626183247.142776-2-david@ixit.cz ---- - arch/arm64/boot/dts/qcom/ipq6018.dtsi | 2 +- - 1 files changed, 1 insertions(+), 1 deletions(-) - ---- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi -@@ -125,7 +125,7 @@ - - firmware { - scm { -- compatible = "qcom,scm"; -+ compatible = "qcom,scm-ipq6018", "qcom,scm"; - }; - }; - diff --git a/target/linux/ipq60xx/patches-5.15/0158-arm64-dts-qcom-ipq6018-drop-USB-PHY-clock-index.patch b/target/linux/ipq60xx/patches-5.15/0158-arm64-dts-qcom-ipq6018-drop-USB-PHY-clock-index.patch deleted file mode 100644 index 04dfd032b..000000000 --- a/target/linux/ipq60xx/patches-5.15/0158-arm64-dts-qcom-ipq6018-drop-USB-PHY-clock-index.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 9215a64a0776c4797ed08520655fba7e85530156 Mon Sep 17 00:00:00 2001 -From: Johan Hovold -Date: Tue, 5 Jul 2022 13:40:21 +0200 -Subject: [PATCH] arm64: dts: qcom: ipq6018: drop USB PHY clock index - -The QMP USB PHY provides a single clock so drop the redundant clock -index. - -Signed-off-by: Johan Hovold -Reviewed-by: Dmitry Baryshkov -Signed-off-by: Bjorn Andersson -Link: https://lore.kernel.org/r/20220705114032.22787-4-johan+linaro@kernel.org ---- - arch/arm64/boot/dts/qcom/ipq6018.dtsi | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi -@@ -694,7 +694,7 @@ - <0x0 0x00078800 0x0 0x1F8>, /* PCS */ - <0x0 0x00078600 0x0 0x044>; /* PCS misc */ - #phy-cells = <0>; -- #clock-cells = <1>; -+ #clock-cells = <0>; - clocks = <&gcc GCC_USB0_PIPE_CLK>; - clock-names = "pipe0"; - clock-output-names = "gcc_usb0_pipe_clk_src"; diff --git a/target/linux/ipq60xx/patches-5.15/0159-arm64-dts-qcom-ipq6018-add-missing-TCSR-syscon-compatible.patch b/target/linux/ipq60xx/patches-5.15/0159-arm64-dts-qcom-ipq6018-add-missing-TCSR-syscon-compatible.patch deleted file mode 100644 index fc16ae58d..000000000 --- a/target/linux/ipq60xx/patches-5.15/0159-arm64-dts-qcom-ipq6018-add-missing-TCSR-syscon-compatible.patch +++ /dev/null @@ -1,25 +0,0 @@ -From d30bcfa4408596e8dd3714dfdd90334d2bdc9856 Mon Sep 17 00:00:00 2001 -From: Krzysztof Kozlowski -Date: Fri, 9 Sep 2022 11:20:25 +0200 -Subject: [PATCH] arm64: dts: qcom: ipq6018: add missing TCSR syscon compatible - -TCSR syscon node should come with dedicated compatible. - -Signed-off-by: Krzysztof Kozlowski -Signed-off-by: Bjorn Andersson -Link: https://lore.kernel.org/r/20220909092035.223915-6-krzysztof.kozlowski@linaro.org ---- - arch/arm64/boot/dts/qcom/ipq6018.dtsi | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi -@@ -253,7 +253,7 @@ - }; - - tcsr: syscon@1937000 { -- compatible = "syscon"; -+ compatible = "qcom,tcsr-ipq6018", "syscon"; - reg = <0x0 0x01937000 0x0 0x21000>; - }; - diff --git a/target/linux/ipq60xx/patches-5.15/0163-arm64-dts-qcom-ipq6018-add-QUP6-I2C-node.patch b/target/linux/ipq60xx/patches-5.15/0163-arm64-dts-qcom-ipq6018-add-QUP6-I2C-node.patch deleted file mode 100644 index 32d1eec53..000000000 --- a/target/linux/ipq60xx/patches-5.15/0163-arm64-dts-qcom-ipq6018-add-QUP6-I2C-node.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 50867cfbbd1ed91870b660536ed1e459c8c4b1d2 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Sat, 4 Jun 2022 21:15:26 +0200 -Subject: [PATCH] arm64: dts: qcom: ipq6018: add QUP6 I2C node - -Add node to support QUP6 I2C controller in IPQ6018. - -Signed-off-by: Robert Marko ---- - arch/arm64/boot/dts/qcom/ipq6018.dtsi | 15 +++++++++++++++ - 1 file changed, 15 insertions(+) - ---- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi -@@ -337,6 +337,21 @@ - status = "disabled"; - }; - -+ blsp1_i2c6: i2c@78ba000 { -+ compatible = "qcom,i2c-qup-v2.2.1"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ reg = <0x0 0x078ba000 0x0 0x600>; -+ interrupts = ; -+ clocks = <&gcc GCC_BLSP1_QUP6_I2C_APPS_CLK>, -+ <&gcc GCC_BLSP1_AHB_CLK>; -+ clock-names = "core", "iface"; -+ clock-frequency = <400000>; -+ dmas = <&blsp_dma 22>, <&blsp_dma 23>; -+ dma-names = "tx", "rx"; -+ status = "disabled"; -+ }; -+ - qpic_bam: dma-controller@7984000 { - compatible = "qcom,bam-v1.7.0"; - reg = <0x0 0x07984000 0x0 0x1a000>; diff --git a/target/linux/ipq60xx/patches-5.15/0164-arm64-dts-qcom-ipq6018-add-MP5496-LDO2-node.patch b/target/linux/ipq60xx/patches-5.15/0164-arm64-dts-qcom-ipq6018-add-MP5496-LDO2-node.patch deleted file mode 100644 index 61e5a28fa..000000000 --- a/target/linux/ipq60xx/patches-5.15/0164-arm64-dts-qcom-ipq6018-add-MP5496-LDO2-node.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 5ef3b4abce82a56fbbfe99ee5ba112f64eef596a Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Mon, 6 Jun 2022 23:16:44 +0200 -Subject: [PATCH] arm64: dts: qcom: ipq6018: add MP5496 LDO2 node - -Add support for the MP5496 LDO2 which is the SDHCI VQMMC supply. - -Signed-off-by: Robert Marko ---- - arch/arm64/boot/dts/qcom/ipq6018.dtsi | 6 ++++++ - 1 file changed, 6 insertions(+) - ---- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi -@@ -815,6 +815,12 @@ - regulator-max-microvolt = <1062500>; - regulator-always-on; - }; -+ -+ ipq6018_l2: l2 { -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-always-on; -+ }; - }; - }; - }; diff --git a/target/linux/ipq60xx/patches-5.15/0165-arm64-dts-qcom-ipq6018-add-SDHCI-controller-node.patch b/target/linux/ipq60xx/patches-5.15/0165-arm64-dts-qcom-ipq6018-add-SDHCI-controller-node.patch deleted file mode 100644 index 1b10a59c8..000000000 --- a/target/linux/ipq60xx/patches-5.15/0165-arm64-dts-qcom-ipq6018-add-SDHCI-controller-node.patch +++ /dev/null @@ -1,47 +0,0 @@ -From b5a258e564a70e0fed38ada2a03e99688fc38e85 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Mon, 6 Jun 2022 23:46:28 +0200 -Subject: [PATCH] arm64: dts: qcom: ipq6018: add SDHCI controller node - -Add the required DT node for SDCC v5 SDHCI controller. - -Signed-off-by: Robert Marko ---- - arch/arm64/boot/dts/qcom/ipq6018.dtsi | 26 ++++++++++++++++++++++++++ - 1 file changed, 26 insertions(+) - ---- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi -@@ -257,6 +257,32 @@ - reg = <0x0 0x01937000 0x0 0x21000>; - }; - -+ sdhci: mmc@780400 { -+ compatible = "qcom,ipq6018-sdhci", "qcom,sdhci-msm-v5"; -+ reg = <0x0 0x07804000 0x0 0x1000>, -+ <0x0 0x07805000 0x0 0x1000>, -+ <0x0 0x07808000 0x0 0x2000>; -+ reg-names = "hc", "cqhci", "ice"; -+ -+ interrupts = , -+ ; -+ interrupt-names = "hc_irq", "pwr_irq"; -+ -+ clocks = <&gcc GCC_SDCC1_AHB_CLK>, -+ <&gcc GCC_SDCC1_APPS_CLK>, -+ <&xo>, -+ <&gcc GCC_SDCC1_ICE_CORE_CLK>; -+ clock-names = "iface", "core", "xo", "ice"; -+ resets = <&gcc GCC_SDCC1_BCR>; -+ max-frequency = <192000000>; -+ mmc-ddr-1_8v; -+ mmc-hs200-1_8v; -+ sd-uhs-sdr104; -+ bus-width = <8>; -+ vqmmc-supply = <&ipq6018_l2>; -+ status = "disabled"; -+ }; -+ - blsp_dma: dma-controller@7884000 { - compatible = "qcom,bam-v1.7.0"; - reg = <0x0 0x07884000 0x0 0x2b000>; diff --git a/target/linux/ipq60xx/patches-5.15/0166-arm64-dts-qcom-ipq6018-add-QFPROM-node.patch b/target/linux/ipq60xx/patches-5.15/0166-arm64-dts-qcom-ipq6018-add-QFPROM-node.patch deleted file mode 100644 index ff9e9e51a..000000000 --- a/target/linux/ipq60xx/patches-5.15/0166-arm64-dts-qcom-ipq6018-add-QFPROM-node.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 3513844ff4d3057e384c5b59604462938375285a Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Tue, 27 Sep 2022 12:50:08 +0200 -Subject: [PATCH] arm64: dts: qcom: ipq6018: add QFPROM node - -Add QFPROM node to IPQ6018 and expose the CPU speed bin only for now. - -Signed-off-by: Robert Marko ---- - arch/arm64/boot/dts/qcom/ipq6018.dtsi | 12 ++++++++++++ - 1 file changed, 12 insertions(+) - ---- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi -@@ -179,6 +179,18 @@ - dma-ranges; - compatible = "simple-bus"; - -+ qfprom: efuse@a4000 { -+ compatible = "qcom,ipq6018-qfprom", "qcom,qfprom"; -+ reg = <0x0 0xa4000 0x0 0x2000>; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ cpu_speed_bin: cpu_speed_bin@135 { -+ reg = <0x135 0x1>; -+ bits = <7 1>; -+ }; -+ }; -+ - prng: qrng@e1000 { - compatible = "qcom,prng-ee"; - reg = <0x0 0xe3000 0x0 0x1000>; diff --git a/target/linux/ipq60xx/patches-5.15/0169-arm64-dts-qcom-align-SPI-NOR-node-name-with-dtschema.patch b/target/linux/ipq60xx/patches-5.15/0169-arm64-dts-qcom-align-SPI-NOR-node-name-with-dtschema.patch deleted file mode 100644 index 9e6e116a5..000000000 --- a/target/linux/ipq60xx/patches-5.15/0169-arm64-dts-qcom-align-SPI-NOR-node-name-with-dtschema.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 2b6d37f6b7fe2f98197b77adcce81d4198aeb305 Mon Sep 17 00:00:00 2001 -From: Krzysztof Kozlowski -Date: Thu, 7 Apr 2022 16:31:12 +0200 -Subject: [PATCH] arm64: dts: qcom: align SPI NOR node name with dtschema - -The node names should be generic and SPI NOR dtschema expects "flash". - -Signed-off-by: Krzysztof Kozlowski -Signed-off-by: Bjorn Andersson -Link: https://lore.kernel.org/r/20220407143112.294930-2-krzysztof.kozlowski@linaro.org ---- - arch/arm64/boot/dts/qcom/ipq6018-cp01-c1.dts | 2 +- - 1 files changed, 1 insertions(+), 1 deletions(-) - ---- a/arch/arm64/boot/dts/qcom/ipq6018-cp01-c1.dts -+++ b/arch/arm64/boot/dts/qcom/ipq6018-cp01-c1.dts -@@ -41,7 +41,7 @@ - pinctrl-names = "default"; - status = "okay"; - -- m25p80@0 { -+ flash@0 { - #address-cells = <1>; - #size-cells = <1>; - reg = <0>; diff --git a/target/linux/ipq60xx/patches-5.15/0170-arm64-dts-qcom-ipq6018-cp01-c1-fix-Micron-SPI-NOR-compatible.patch b/target/linux/ipq60xx/patches-5.15/0170-arm64-dts-qcom-ipq6018-cp01-c1-fix-Micron-SPI-NOR-compatible.patch deleted file mode 100644 index 5bb312831..000000000 --- a/target/linux/ipq60xx/patches-5.15/0170-arm64-dts-qcom-ipq6018-cp01-c1-fix-Micron-SPI-NOR-compatible.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 693b6207fc7fbfe81aa9759ef82c3953245641d9 Mon Sep 17 00:00:00 2001 -From: Krzysztof Kozlowski -Date: Sat, 21 May 2022 18:45:49 +0200 -Subject: [PATCH] arm64: dts: qcom: ipq6018-cp01-c1: fix Micron SPI NOR - compatible - -The proper compatible for Micron n25q128a11 SPI NOR flash should include -vendor-prefix. - -Signed-off-by: Krzysztof Kozlowski -Signed-off-by: Bjorn Andersson -Link: https://lore.kernel.org/r/20220521164550.91115-11-krzysztof.kozlowski@linaro.org ---- - arch/arm64/boot/dts/qcom/ipq6018-cp01-c1.dts | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/arch/arm64/boot/dts/qcom/ipq6018-cp01-c1.dts -+++ b/arch/arm64/boot/dts/qcom/ipq6018-cp01-c1.dts -@@ -45,7 +45,7 @@ - #address-cells = <1>; - #size-cells = <1>; - reg = <0>; -- compatible = "n25q128a11"; -+ compatible = "micron,n25q128a11", "jedec,spi-nor"; - spi-max-frequency = <50000000>; - }; - }; diff --git a/target/linux/ipq60xx/patches-5.15/0172-arm64-dts-qcom-cp01-c1-enable-SDHCI-controller.patch b/target/linux/ipq60xx/patches-5.15/0172-arm64-dts-qcom-cp01-c1-enable-SDHCI-controller.patch deleted file mode 100644 index 7a970c36e..000000000 --- a/target/linux/ipq60xx/patches-5.15/0172-arm64-dts-qcom-cp01-c1-enable-SDHCI-controller.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 743ac0846de33fd4e3af03b5a94689027de9c479 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Mon, 6 Jun 2022 23:47:21 +0200 -Subject: [PATCH] arm64: dts: qcom: cp01-c1: enable SDHCI controller - -Enable the SDHCI controller for onboard uSD card slot. -CD and WP GPIO-s are present. - -Signed-off-by: Robert Marko ---- - arch/arm64/boot/dts/qcom/ipq6018-cp01-c1.dts | 25 ++++++++++++++++++++ - 1 file changed, 25 insertions(+) - ---- a/arch/arm64/boot/dts/qcom/ipq6018-cp01-c1.dts -+++ b/arch/arm64/boot/dts/qcom/ipq6018-cp01-c1.dts -@@ -8,6 +8,7 @@ - /dts-v1/; - - #include "ipq6018.dtsi" -+#include - - / { - model = "Qualcomm Technologies, Inc. IPQ6018/AP-CP01-C1"; -@@ -63,6 +64,20 @@ - drive-strength = <8>; - bias-pull-down; - }; -+ -+ sdio_pins: sdio-state { -+ cd-pins { -+ pins = "gpio62"; -+ function = "gpio"; -+ bias-pull-up; -+ }; -+ -+ wp-pins { -+ pins = "gpio63"; -+ function = "gpio"; -+ bias-pull-down; -+ }; -+ }; - }; - - &qpic_bam { -@@ -81,6 +96,16 @@ - }; - }; - -+&sdhci { -+ status = "okay"; -+ -+ pinctrl-0 = <&sdio_pins>; -+ pinctrl-names = "default"; -+ cd-gpios = <&tlmm 62 GPIO_ACTIVE_LOW>; -+ wp-gpios = <&tlmm 63 GPIO_ACTIVE_HIGH>; -+ bus-width = <4>; -+}; -+ - &qusb_phy_1 { - status = "ok"; - }; diff --git a/target/linux/ipq60xx/patches-5.15/0173-arm64-dts-qcom-cp01-c1-remove-bootargs-append.patch b/target/linux/ipq60xx/patches-5.15/0173-arm64-dts-qcom-cp01-c1-remove-bootargs-append.patch deleted file mode 100644 index 4e8c83282..000000000 --- a/target/linux/ipq60xx/patches-5.15/0173-arm64-dts-qcom-cp01-c1-remove-bootargs-append.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 3e461b07274d5c10120c201f825cc77d2126ab8a Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Tue, 7 Jun 2022 00:09:08 +0200 -Subject: [PATCH] arm64: dts: qcom: cp01-c1: remove bootargs-append - -bootargs-append is a leftover from the vendor SDK, and does not exist -in the mainline kernel at all, so remove it. - -Signed-off-by: Robert Marko ---- - arch/arm64/boot/dts/qcom/ipq6018-cp01-c1.dts | 1 - - 1 file changed, 1 deletion(-) - ---- a/arch/arm64/boot/dts/qcom/ipq6018-cp01-c1.dts -+++ b/arch/arm64/boot/dts/qcom/ipq6018-cp01-c1.dts -@@ -20,7 +20,6 @@ - - chosen { - stdout-path = "serial0:115200n8"; -- bootargs-append = " swiotlb=1"; - }; - }; - diff --git a/target/linux/ipq60xx/patches-5.15/0174-arm64-dts-qcom-cp01-c1-use-okay-instead-of-ok.patch b/target/linux/ipq60xx/patches-5.15/0174-arm64-dts-qcom-cp01-c1-use-okay-instead-of-ok.patch deleted file mode 100644 index 430517560..000000000 --- a/target/linux/ipq60xx/patches-5.15/0174-arm64-dts-qcom-cp01-c1-use-okay-instead-of-ok.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 381329da5b7f33a7f48d10405af65c6d68108fc1 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Tue, 7 Jun 2022 00:13:46 +0200 -Subject: [PATCH] arm64: dts: qcom: cp01-c1: use "okay" instead of "ok" - -Use "okay" instead of "ok" in USB nodes as "ok" is deprecated. - -Signed-off-by: Robert Marko ---- - arch/arm64/boot/dts/qcom/ipq6018-cp01-c1.dts | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/arch/arm64/boot/dts/qcom/ipq6018-cp01-c1.dts -+++ b/arch/arm64/boot/dts/qcom/ipq6018-cp01-c1.dts -@@ -106,9 +106,9 @@ - }; - - &qusb_phy_1 { -- status = "ok"; -+ status = "okay"; - }; - - &usb2 { -- status = "ok"; -+ status = "okay"; - }; diff --git a/target/linux/ipq60xx/patches-5.15/0175-arm64-dts-qcom-cp01-c1-enable-USB3.0.patch b/target/linux/ipq60xx/patches-5.15/0175-arm64-dts-qcom-cp01-c1-enable-USB3.0.patch deleted file mode 100644 index 672c7428f..000000000 --- a/target/linux/ipq60xx/patches-5.15/0175-arm64-dts-qcom-cp01-c1-enable-USB3.0.patch +++ /dev/null @@ -1,33 +0,0 @@ -From cb9032f20e1f3230cb761ce5cd1558471f108bd6 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Tue, 7 Jun 2022 00:14:42 +0200 -Subject: [PATCH] arm64: dts: qcom: cp01-c1: enable USB3.0 - -Enable the USB3.0 controller as Type-C port is connected to it. - -Signed-off-by: Robert Marko ---- - arch/arm64/boot/dts/qcom/ipq6018-cp01-c1.dts | 12 ++++++++++++ - 1 file changed, 12 insertions(+) - ---- a/arch/arm64/boot/dts/qcom/ipq6018-cp01-c1.dts -+++ b/arch/arm64/boot/dts/qcom/ipq6018-cp01-c1.dts -@@ -105,6 +105,18 @@ - bus-width = <4>; - }; - -+&qusb_phy_0 { -+ status = "okay"; -+}; -+ -+&ssphy_0 { -+ status = "okay"; -+}; -+ -+&usb3 { -+ status = "okay"; -+}; -+ - &qusb_phy_1 { - status = "okay"; - }; diff --git a/target/linux/ipq60xx/patches-5.15/0176-arm64-dts-qcom-cp01-c1-enable-PCIe.patch b/target/linux/ipq60xx/patches-5.15/0176-arm64-dts-qcom-cp01-c1-enable-PCIe.patch deleted file mode 100644 index d92cba1e7..000000000 --- a/target/linux/ipq60xx/patches-5.15/0176-arm64-dts-qcom-cp01-c1-enable-PCIe.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 2504aba5d9de54aef522151a86e43baeedb77436 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Tue, 7 Jun 2022 15:13:03 +0200 -Subject: [PATCH] arm64: dts: qcom: cp01-c1: enable PCIe - -CP01 has a M.2 Key E slot with a single lane PCIe 3.0. -So enable the node and add the PERST and WAKE GPIO-s. - -Signed-off-by: Robert Marko ---- - arch/arm64/boot/dts/qcom/ipq6018-cp01-c1.dts | 11 +++++++++++ - 1 file changed, 11 insertions(+) - ---- a/arch/arm64/boot/dts/qcom/ipq6018-cp01-c1.dts -+++ b/arch/arm64/boot/dts/qcom/ipq6018-cp01-c1.dts -@@ -124,3 +124,14 @@ - &usb2 { - status = "okay"; - }; -+ -+&pcie_phy { -+ status = "okay"; -+}; -+ -+&pcie0 { -+ status = "okay"; -+ -+ perst-gpios = <&tlmm 60 GPIO_ACTIVE_LOW>; -+ wake-gpios = <&tlmm 36 GPIO_ACTIVE_HIGH>; -+}; diff --git a/target/linux/ipq60xx/patches-5.15/0177-arm64-dts-qcom-cp01-c1-add-MDIO-PHY-s.patch b/target/linux/ipq60xx/patches-5.15/0177-arm64-dts-qcom-cp01-c1-add-MDIO-PHY-s.patch deleted file mode 100644 index 96531f738..000000000 --- a/target/linux/ipq60xx/patches-5.15/0177-arm64-dts-qcom-cp01-c1-add-MDIO-PHY-s.patch +++ /dev/null @@ -1,81 +0,0 @@ -From 829ec1663e492824458f2b0f0cdbbe0662a65e1e Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Tue, 7 Jun 2022 15:31:00 +0200 -Subject: [PATCH] arm64: dts: qcom: cp01-c1: add MDIO PHY-s - -Add the required DT nodes for the onboard QCA8075 and QCA8081 ethernet -PHY-s. - -Signed-off-by: Robert Marko ---- - arch/arm64/boot/dts/qcom/ipq6018-cp01-c1.dts | 55 ++++++++++++++++++++ - 1 file changed, 55 insertions(+) - ---- a/arch/arm64/boot/dts/qcom/ipq6018-cp01-c1.dts -+++ b/arch/arm64/boot/dts/qcom/ipq6018-cp01-c1.dts -@@ -77,6 +77,22 @@ - bias-pull-down; - }; - }; -+ -+ mdio_pins: mdio-state { -+ mdc-pins { -+ pins = "gpio64"; -+ function = "mdc"; -+ drive-strength = <8>; -+ bias-pull-up; -+ }; -+ -+ mdio-pins { -+ pins = "gpio65"; -+ function = "mdio"; -+ drive-strength = <8>; -+ bias-pull-up; -+ }; -+ }; - }; - - &qpic_bam { -@@ -135,3 +151,42 @@ - perst-gpios = <&tlmm 60 GPIO_ACTIVE_LOW>; - wake-gpios = <&tlmm 36 GPIO_ACTIVE_HIGH>; - }; -+ -+&mdio { -+ status = "okay"; -+ -+ pinctrl-0 = <&mdio_pins>; -+ pinctrl-names = "default"; -+ reset-gpios = <&tlmm 75 GPIO_ACTIVE_LOW>; -+ -+ ethernet-phy@0 { -+ compatible = "ethernet-phy-ieee802.3-c22"; -+ reg = <0>; -+ }; -+ -+ ethernet-phy@1 { -+ compatible = "ethernet-phy-ieee802.3-c22"; -+ reg = <1>; -+ }; -+ -+ ethernet-phy@2 { -+ compatible = "ethernet-phy-ieee802.3-c22"; -+ reg = <2>; -+ }; -+ -+ ethernet-phy@3 { -+ compatible = "ethernet-phy-ieee802.3-c22"; -+ reg = <3>; -+ }; -+ -+ ethernet-phy@4 { -+ compatible = "ethernet-phy-ieee802.3-c22"; -+ reg = <4>; -+ }; -+ -+ ethernet-phy@24 { -+ compatible = "ethernet-phy-id004d.d101"; -+ reg = <24>; -+ reset-gpios = <&tlmm 77 GPIO_ACTIVE_LOW>; -+ }; -+}; diff --git a/target/linux/ipq60xx/patches-5.15/0600-5.15-qca-nss-ecm-support-CORE.patch b/target/linux/ipq60xx/patches-5.15/0600-5.15-qca-nss-ecm-support-CORE.patch deleted file mode 100644 index a6be2c15f..000000000 --- a/target/linux/ipq60xx/patches-5.15/0600-5.15-qca-nss-ecm-support-CORE.patch +++ /dev/null @@ -1,615 +0,0 @@ ---- a/include/linux/if_bridge.h -+++ b/include/linux/if_bridge.h -@@ -69,6 +69,9 @@ void brioctl_set(int (*hook)(struct net - void __user *uarg)); - int br_ioctl_call(struct net *net, struct net_bridge *br, unsigned int cmd, - struct ifreq *ifr, void __user *uarg); -+extern void br_dev_update_stats(struct net_device *dev, -+ struct rtnl_link_stats64 *nlstats); -+extern bool br_is_hairpin_enabled(struct net_device *dev); - - extern void br_dev_update_stats(struct net_device *dev, - struct rtnl_link_stats64 *nlstats); -@@ -195,4 +198,42 @@ static inline clock_t br_get_ageing_time - } - #endif - -+/* QCA NSS ECM support - Start */ -+extern struct net_device *br_port_dev_get(struct net_device *dev, -+ unsigned char *addr, -+ struct sk_buff *skb, -+ unsigned int cookie); -+extern void br_refresh_fdb_entry(struct net_device *dev, const char *addr); -+extern void br_fdb_entry_refresh(struct net_device *dev, const char *addr, __u16 vid); -+extern struct net_bridge_fdb_entry *br_fdb_has_entry(struct net_device *dev, -+ const char *addr, -+ __u16 vid); -+extern void br_fdb_update_register_notify(struct notifier_block *nb); -+extern void br_fdb_update_unregister_notify(struct notifier_block *nb); -+ -+typedef struct net_bridge_port *br_port_dev_get_hook_t(struct net_device *dev, -+ struct sk_buff *skb, -+ unsigned char *addr, -+ unsigned int cookie); -+extern br_port_dev_get_hook_t __rcu *br_port_dev_get_hook; -+ -+#define BR_FDB_EVENT_ADD 0x01 -+#define BR_FDB_EVENT_DEL 0x02 -+ -+struct br_fdb_event { -+ struct net_device *dev; -+ unsigned char addr[6]; -+ unsigned char is_local; -+ struct net_bridge *br; -+ struct net_device *orig_dev; -+}; -+extern void br_fdb_register_notify(struct notifier_block *nb); -+extern void br_fdb_unregister_notify(struct notifier_block *nb); -+ -+typedef struct net_bridge_port *br_get_dst_hook_t( -+ const struct net_bridge_port *src, -+ struct sk_buff **skb); -+extern br_get_dst_hook_t __rcu *br_get_dst_hook; -+/* QCA NSS ECM support - End */ -+ - #endif ---- a/include/linux/if_vlan.h -+++ b/include/linux/if_vlan.h -@@ -230,7 +230,28 @@ extern void vlan_vids_del_by_dev(struct - - extern bool vlan_uses_dev(const struct net_device *dev); - -+/* QCA NSS ECM support - Start */ -+extern void __vlan_dev_update_accel_stats(struct net_device *dev, -+ struct rtnl_link_stats64 *stats); -+extern u16 vlan_dev_get_egress_prio(struct net_device *dev, u32 skb_prio); -+extern struct net_device *vlan_dev_next_dev(const struct net_device *dev); -+/* QCA NSS ECM support - End */ -+ - #else -+/* QCA NSS ECM support - Start */ -+static inline void __vlan_dev_update_accel_stats(struct net_device *dev, -+ struct rtnl_link_stats64 *stats) -+{ -+ -+} -+ -+static inline u16 vlan_dev_get_egress_prio(struct net_device *dev, -+ u32 skb_prio) -+{ -+ return 0; -+} -+/* QCA NSS ECM support - End */ -+ - static inline struct net_device * - __vlan_find_dev_deep_rcu(struct net_device *real_dev, - __be16 vlan_proto, u16 vlan_id) ---- a/include/linux/netdevice.h -+++ b/include/linux/netdevice.h -@@ -2857,6 +2857,10 @@ enum netdev_cmd { - NETDEV_CVLAN_FILTER_DROP_INFO, - NETDEV_SVLAN_FILTER_PUSH_INFO, - NETDEV_SVLAN_FILTER_DROP_INFO, -+ /* QCA NSS ECM Support - Start */ -+ NETDEV_BR_JOIN, -+ NETDEV_BR_LEAVE, -+ /* QCA NSS ECM Support - End */ - }; - const char *netdev_cmd_to_name(enum netdev_cmd cmd); - ---- a/include/net/ip6_route.h -+++ b/include/net/ip6_route.h -@@ -211,6 +211,11 @@ void rt6_multipath_rebalance(struct fib6 - void rt6_uncached_list_add(struct rt6_info *rt); - void rt6_uncached_list_del(struct rt6_info *rt); - -+/* QCA NSS ECM support - Start */ -+int rt6_register_notifier(struct notifier_block *nb); -+int rt6_unregister_notifier(struct notifier_block *nb); -+/* QCA NSS ECM support - End */ -+ - static inline const struct rt6_info *skb_rt6_info(const struct sk_buff *skb) - { - const struct dst_entry *dst = skb_dst(skb); ---- a/include/net/neighbour.h -+++ b/include/net/neighbour.h -@@ -567,4 +567,15 @@ static inline void neigh_update_is_route - *notify = 1; - } - } -+ -+/* QCA NSS ECM support - Start */ -+struct neigh_mac_update { -+ unsigned char old_mac[ALIGN(MAX_ADDR_LEN, sizeof(unsigned long))]; -+ unsigned char update_mac[ALIGN(MAX_ADDR_LEN, sizeof(unsigned long))]; -+}; -+ -+extern void neigh_mac_update_register_notify(struct notifier_block *nb); -+extern void neigh_mac_update_unregister_notify(struct notifier_block *nb); -+/* QCA NSS ECM support - End */ -+ - #endif ---- a/include/net/route.h -+++ b/include/net/route.h -@@ -234,6 +234,11 @@ struct rtable *rt_dst_alloc(struct net_d - bool nopolicy, bool noxfrm); - struct rtable *rt_dst_clone(struct net_device *dev, struct rtable *rt); - -+/* QCA NSS ECM support - Start */ -+int ip_rt_register_notifier(struct notifier_block *nb); -+int ip_rt_unregister_notifier(struct notifier_block *nb); -+/* QCA NSS ECM support - End */ -+ - struct in_ifaddr; - void fib_add_ifaddr(struct in_ifaddr *); - void fib_del_ifaddr(struct in_ifaddr *, struct in_ifaddr *); ---- a/net/bridge/br_fdb.c -+++ b/net/bridge/br_fdb.c -@@ -38,6 +38,35 @@ static int fdb_insert(struct net_bridge - static void fdb_notify(struct net_bridge *br, - const struct net_bridge_fdb_entry *, int, bool); - -+/* QCA NSS ECM support - Start */ -+ATOMIC_NOTIFIER_HEAD(br_fdb_notifier_list); -+ATOMIC_NOTIFIER_HEAD(br_fdb_update_notifier_list); -+ -+void br_fdb_register_notify(struct notifier_block *nb) -+{ -+ atomic_notifier_chain_register(&br_fdb_notifier_list, nb); -+} -+EXPORT_SYMBOL_GPL(br_fdb_register_notify); -+ -+void br_fdb_unregister_notify(struct notifier_block *nb) -+{ -+ atomic_notifier_chain_unregister(&br_fdb_notifier_list, nb); -+} -+EXPORT_SYMBOL_GPL(br_fdb_unregister_notify); -+ -+void br_fdb_update_register_notify(struct notifier_block *nb) -+{ -+ atomic_notifier_chain_register(&br_fdb_update_notifier_list, nb); -+} -+EXPORT_SYMBOL_GPL(br_fdb_update_register_notify); -+ -+void br_fdb_update_unregister_notify(struct notifier_block *nb) -+{ -+ atomic_notifier_chain_unregister(&br_fdb_update_notifier_list, nb); -+} -+EXPORT_SYMBOL_GPL(br_fdb_update_unregister_notify); -+/* QCA NSS ECM support - End */ -+ - int __init br_fdb_init(void) - { - br_fdb_cache = kmem_cache_create("bridge_fdb_cache", -@@ -343,6 +372,7 @@ void br_fdb_cleanup(struct work_struct * - unsigned long delay = hold_time(br); - unsigned long work_delay = delay; - unsigned long now = jiffies; -+ u8 mac_addr[6]; /* QCA NSS ECM support */ - - /* this part is tricky, in order to avoid blocking learning and - * consequently forwarding, we rely on rcu to delete objects with -@@ -369,8 +399,15 @@ void br_fdb_cleanup(struct work_struct * - work_delay = min(work_delay, this_timer - now); - } else { - spin_lock_bh(&br->hash_lock); -- if (!hlist_unhashed(&f->fdb_node)) -+ if (!hlist_unhashed(&f->fdb_node)) { -+ ether_addr_copy(mac_addr, f->key.addr.addr); - fdb_delete(br, f, true); -+ /* QCA NSS ECM support - Start */ -+ atomic_notifier_call_chain( -+ &br_fdb_update_notifier_list, 0, -+ (void *)mac_addr); -+ /* QCA NSS ECM support - End */ -+ } - spin_unlock_bh(&br->hash_lock); - } - } -@@ -618,6 +655,12 @@ void br_fdb_update(struct net_bridge *br - &fdb->flags))) - clear_bit(BR_FDB_ADDED_BY_EXT_LEARN, - &fdb->flags); -+ -+ /* QCA NSS ECM support - Start */ -+ atomic_notifier_call_chain( -+ &br_fdb_update_notifier_list, -+ 0, (void *)addr); -+ /* QCA NSS ECM support - End */ - } - - if (unlikely(test_bit(BR_FDB_ADDED_BY_USER, &flags))) -@@ -799,6 +842,25 @@ static void fdb_notify(struct net_bridge - - br_offload_fdb_update(fdb); - -+ /* QCA NSS ECM support - Start */ -+ if (fdb->dst) { -+ int event; -+ struct br_fdb_event fdb_event; -+ -+ if (type == RTM_NEWNEIGH) -+ event = BR_FDB_EVENT_ADD; -+ else -+ event = BR_FDB_EVENT_DEL; -+ -+ fdb_event.dev = fdb->dst->dev; -+ ether_addr_copy(fdb_event.addr, fdb->key.addr.addr); -+ fdb_event.is_local = test_bit(BR_FDB_LOCAL, &fdb->flags); -+ atomic_notifier_call_chain(&br_fdb_notifier_list, -+ event, -+ (void *)&fdb_event); -+ } -+ /* QCA NSS ECM support - End */ -+ - if (swdev_notify) - br_switchdev_fdb_notify(br, fdb, type); - -@@ -1382,3 +1444,62 @@ void br_fdb_clear_offload(const struct n - spin_unlock_bh(&p->br->hash_lock); - } - EXPORT_SYMBOL_GPL(br_fdb_clear_offload); -+ -+/* QCA NSS ECM support - Start */ -+/* Refresh FDB entries for bridge packets being forwarded by offload engines */ -+void br_refresh_fdb_entry(struct net_device *dev, const char *addr) -+{ -+ struct net_bridge_port *p = br_port_get_rcu(dev); -+ -+ if (!p || p->state == BR_STATE_DISABLED) -+ return; -+ -+ if (!is_valid_ether_addr(addr)) { -+ pr_info("bridge: Attempt to refresh with invalid ether address %pM\n", -+ addr); -+ return; -+ } -+ -+ rcu_read_lock(); -+ br_fdb_update(p->br, p, addr, 0, true); -+ rcu_read_unlock(); -+} -+EXPORT_SYMBOL_GPL(br_refresh_fdb_entry); -+ -+/* Update timestamp of FDB entries for bridge packets being forwarded by offload engines */ -+void br_fdb_entry_refresh(struct net_device *dev, const char *addr, __u16 vid) -+{ -+ struct net_bridge_fdb_entry *fdb; -+ struct net_bridge_port *p = br_port_get_rcu(dev); -+ -+ if (!p || p->state == BR_STATE_DISABLED) -+ return; -+ -+ rcu_read_lock(); -+ fdb = fdb_find_rcu(&p->br->fdb_hash_tbl, addr, vid); -+ if (likely(fdb)) { -+ fdb->updated = jiffies; -+ } -+ rcu_read_unlock(); -+} -+EXPORT_SYMBOL_GPL(br_fdb_entry_refresh); -+ -+/* Look up the MAC address in the device's bridge fdb table */ -+struct net_bridge_fdb_entry *br_fdb_has_entry(struct net_device *dev, -+ const char *addr, __u16 vid) -+{ -+ struct net_bridge_port *p = br_port_get_rcu(dev); -+ struct net_bridge_fdb_entry *fdb; -+ -+ if (!p || p->state == BR_STATE_DISABLED) -+ return NULL; -+ -+ rcu_read_lock(); -+ fdb = fdb_find_rcu(&p->br->fdb_hash_tbl, addr, vid); -+ rcu_read_unlock(); -+ -+ return fdb; -+} -+EXPORT_SYMBOL_GPL(br_fdb_has_entry); -+/* QCA NSS ECM support - End */ -+ ---- a/net/bridge/br_if.c -+++ b/net/bridge/br_if.c -@@ -27,6 +27,12 @@ - #include "br_private.h" - #include "br_private_offload.h" - -+/* QCA NSS ECM support - Start */ -+/* Hook for external forwarding logic */ -+br_port_dev_get_hook_t __rcu *br_port_dev_get_hook __read_mostly; -+EXPORT_SYMBOL_GPL(br_port_dev_get_hook); -+/* QCA NSS ECM support - End */ -+ - /* - * Determine initial path cost based on speed. - * using recommendations from 802.1d standard -@@ -708,6 +714,8 @@ int br_add_if(struct net_bridge *br, str - - kobject_uevent(&p->kobj, KOBJ_ADD); - -+ call_netdevice_notifiers(NETDEV_BR_JOIN, dev); /* QCA NSS ECM support */ -+ - return 0; - - err6: -@@ -743,6 +751,8 @@ int br_del_if(struct net_bridge *br, str - if (!p || p->br != br) - return -EINVAL; - -+ call_netdevice_notifiers(NETDEV_BR_LEAVE, dev); /* QCA NSS ECM support */ -+ - /* Since more than one interface can be attached to a bridge, - * there still maybe an alternate path for netconsole to use; - * therefore there is no reason for a NETDEV_RELEASE event. -@@ -811,3 +821,74 @@ bool br_port_flag_is_set(const struct ne - return p->flags & flag; - } - EXPORT_SYMBOL_GPL(br_port_flag_is_set); -+ -+/* API to know if hairpin feature is enabled/disabled on this bridge port */ -+bool br_is_hairpin_enabled(struct net_device *dev) -+{ -+ struct net_bridge_port *port = br_port_get_check_rcu(dev); -+ -+ if (likely(port)) -+ return port->flags & BR_HAIRPIN_MODE; -+ return false; -+} -+EXPORT_SYMBOL_GPL(br_is_hairpin_enabled); -+ -+/* br_port_dev_get() -+ * If a skb is provided, and the br_port_dev_get_hook_t hook exists, -+ * use that to try and determine the egress port for that skb. -+ * If not, or no egress port could be determined, use the given addr -+ * to identify the port to which it is reachable, -+ * returing a reference to the net device associated with that port. -+ * -+ * NOTE: Return NULL if given dev is not a bridge or the mac has no -+ * associated port. -+ */ -+struct net_device *br_port_dev_get(struct net_device *dev, unsigned char *addr, -+ struct sk_buff *skb, -+ unsigned int cookie) -+{ -+ struct net_bridge_fdb_entry *fdbe; -+ struct net_bridge *br; -+ struct net_device *netdev = NULL; -+ -+ /* Is this a bridge? */ -+ if (!(dev->priv_flags & IFF_EBRIDGE)) -+ return NULL; -+ -+ rcu_read_lock(); -+ -+ /* If the hook exists and the skb isn't NULL, try and get the port */ -+ if (skb) { -+ br_port_dev_get_hook_t *port_dev_get_hook; -+ -+ port_dev_get_hook = rcu_dereference(br_port_dev_get_hook); -+ if (port_dev_get_hook) { -+ struct net_bridge_port *pdst = -+ __br_get(port_dev_get_hook, NULL, dev, skb, -+ addr, cookie); -+ if (pdst) { -+ dev_hold(pdst->dev); -+ netdev = pdst->dev; -+ goto out; -+ } -+ } -+ } -+ -+ /* Either there is no hook, or can't -+ * determine the port to use - fall back to using FDB -+ */ -+ -+ br = netdev_priv(dev); -+ -+ /* Lookup the fdb entry and get reference to the port dev */ -+ fdbe = br_fdb_find_rcu(br, addr, 0); -+ if (fdbe && fdbe->dst) { -+ netdev = fdbe->dst->dev; /* port device */ -+ dev_hold(netdev); -+ } -+out: -+ rcu_read_unlock(); -+ return netdev; -+} -+EXPORT_SYMBOL_GPL(br_port_dev_get); -+/* QCA NSS ECM support - End */ ---- a/net/bridge/br_private.h -+++ b/net/bridge/br_private.h -@@ -2122,4 +2122,9 @@ void br_do_proxy_suppress_arp(struct sk_ - void br_do_suppress_nd(struct sk_buff *skb, struct net_bridge *br, - u16 vid, struct net_bridge_port *p, struct nd_msg *msg); - struct nd_msg *br_is_nd_neigh_msg(struct sk_buff *skb, struct nd_msg *m); -+ -+/* QCA NSS ECM support - Start */ -+#define __br_get(__hook, __default, __args ...) \ -+ (__hook ? (__hook(__args)) : (__default)) -+/* QCA NSS ECM support - End */ - #endif ---- a/net/core/neighbour.c -+++ b/net/core/neighbour.c -@@ -1211,7 +1211,21 @@ static void neigh_update_hhs(struct neig - } - } - -+/* QCA NSS ECM support - start */ -+ATOMIC_NOTIFIER_HEAD(neigh_mac_update_notifier_list); -+ -+void neigh_mac_update_register_notify(struct notifier_block *nb) -+{ -+ atomic_notifier_chain_register(&neigh_mac_update_notifier_list, nb); -+} -+EXPORT_SYMBOL_GPL(neigh_mac_update_register_notify); - -+void neigh_mac_update_unregister_notify(struct notifier_block *nb) -+{ -+ atomic_notifier_chain_unregister(&neigh_mac_update_notifier_list, nb); -+} -+EXPORT_SYMBOL_GPL(neigh_mac_update_unregister_notify); -+/* QCA NSS ECM support - End */ - - /* Generic update routine. - -- lladdr is new lladdr or NULL, if it is not supplied. -@@ -1242,6 +1256,7 @@ static int __neigh_update(struct neighbo - int notify = 0; - struct net_device *dev; - int update_isrouter = 0; -+ struct neigh_mac_update nmu; /* QCA NSS ECM support */ - - trace_neigh_update(neigh, lladdr, new, flags, nlmsg_pid); - -@@ -1256,6 +1271,8 @@ static int __neigh_update(struct neighbo - new = old; - goto out; - } -+ memset(&nmu, 0, sizeof(struct neigh_mac_update)); /* QCA NSS ECM support */ -+ - if (!(flags & NEIGH_UPDATE_F_ADMIN) && - (old & (NUD_NOARP | NUD_PERMANENT))) - goto out; -@@ -1293,6 +1310,11 @@ static int __neigh_update(struct neighbo - - compare new & old - - if they are different, check override flag - */ -+ /* QCA NSS ECM update - Start */ -+ memcpy(nmu.old_mac, neigh->ha, dev->addr_len); -+ memcpy(nmu.update_mac, lladdr, dev->addr_len); -+ /* QCA NSS ECM update - End */ -+ - if ((old & NUD_VALID) && - !memcmp(lladdr, neigh->ha, dev->addr_len)) - lladdr = neigh->ha; -@@ -1415,8 +1437,11 @@ out: - if (((new ^ old) & NUD_PERMANENT) || ext_learn_change) - neigh_update_gc_list(neigh); - -- if (notify) -+ if (notify) { - neigh_update_notify(neigh, nlmsg_pid); -+ atomic_notifier_call_chain(&neigh_mac_update_notifier_list, 0, -+ (struct neigh_mac_update *)&nmu); /* QCA NSS ECM support */ -+ } - - trace_neigh_update_done(neigh, err); - ---- a/net/ipv4/fib_trie.c -+++ b/net/ipv4/fib_trie.c -@@ -1206,6 +1206,9 @@ static bool fib_valid_key_len(u32 key, u - static void fib_remove_alias(struct trie *t, struct key_vector *tp, - struct key_vector *l, struct fib_alias *old); - -+/* Define route change notification chain. */ -+static BLOCKING_NOTIFIER_HEAD(iproute_chain); /* QCA NSS ECM support */ -+ - /* Caller must hold RTNL. */ - int fib_table_insert(struct net *net, struct fib_table *tb, - struct fib_config *cfg, struct netlink_ext_ack *extack) -@@ -1398,6 +1401,9 @@ int fib_table_insert(struct net *net, st - rtmsg_fib(RTM_NEWROUTE, htonl(key), new_fa, plen, new_fa->tb_id, - &cfg->fc_nlinfo, nlflags); - succeeded: -+ blocking_notifier_call_chain(&iproute_chain, -+ RTM_NEWROUTE, fi); -+ - return 0; - - out_remove_new_fa: -@@ -1769,6 +1775,9 @@ int fib_table_delete(struct net *net, st - if (fa_to_delete->fa_state & FA_S_ACCESSED) - rt_cache_flush(cfg->fc_nlinfo.nl_net); - -+ blocking_notifier_call_chain(&iproute_chain, -+ RTM_DELROUTE, fa_to_delete->fa_info); -+ - fib_release_info(fa_to_delete->fa_info); - alias_free_mem_rcu(fa_to_delete); - return 0; -@@ -2401,6 +2410,20 @@ void __init fib_trie_init(void) - 0, SLAB_PANIC | SLAB_ACCOUNT, NULL); - } - -+/* QCA NSS ECM support - Start */ -+int ip_rt_register_notifier(struct notifier_block *nb) -+{ -+ return blocking_notifier_chain_register(&iproute_chain, nb); -+} -+EXPORT_SYMBOL(ip_rt_register_notifier); -+ -+int ip_rt_unregister_notifier(struct notifier_block *nb) -+{ -+ return blocking_notifier_chain_unregister(&iproute_chain, nb); -+} -+EXPORT_SYMBOL(ip_rt_unregister_notifier); -+/* QCA NSS ECM support - End */ -+ - struct fib_table *fib_trie_table(u32 id, struct fib_table *alias) - { - struct fib_table *tb; ---- a/include/net/addrconf.h -+++ b/include/net/addrconf.h -@@ -512,4 +512,9 @@ int if6_proc_init(void); - void if6_proc_exit(void); - #endif - -+/* QCA NSS ECM support - Start */ -+struct net_device *ipv6_dev_find_and_hold(struct net *net, struct in6_addr *addr, -+ int strict); -+/* QCA NSS ECM support - End */ -+ - #endif ---- a/net/ipv6/route.c -+++ b/net/ipv6/route.c -@@ -3875,6 +3875,9 @@ out_free: - return ERR_PTR(err); - } - -+/* Define route change notification chain. */ -+ATOMIC_NOTIFIER_HEAD(ip6route_chain); /* QCA NSS ECM support */ -+ - int ip6_route_add(struct fib6_config *cfg, gfp_t gfp_flags, - struct netlink_ext_ack *extack) - { -@@ -3886,6 +3889,10 @@ int ip6_route_add(struct fib6_config *cf - return PTR_ERR(rt); - - err = __ip6_ins_rt(rt, &cfg->fc_nlinfo, extack); -+ if (!err) -+ atomic_notifier_call_chain(&ip6route_chain, -+ RTM_NEWROUTE, rt); -+ - fib6_info_release(rt); - - return err; -@@ -3907,6 +3914,9 @@ static int __ip6_del_rt(struct fib6_info - err = fib6_del(rt, info); - spin_unlock_bh(&table->tb6_lock); - -+ if (!err) -+ atomic_notifier_call_chain(&ip6route_chain, -+ RTM_DELROUTE, rt); - out: - fib6_info_release(rt); - return err; -@@ -6350,6 +6360,20 @@ static int ip6_route_dev_notify(struct n - return NOTIFY_OK; - } - -+/* QCA NSS ECM support - Start */ -+int rt6_register_notifier(struct notifier_block *nb) -+{ -+ return atomic_notifier_chain_register(&ip6route_chain, nb); -+} -+EXPORT_SYMBOL(rt6_register_notifier); -+ -+int rt6_unregister_notifier(struct notifier_block *nb) -+{ -+ return atomic_notifier_chain_unregister(&ip6route_chain, nb); -+} -+EXPORT_SYMBOL(rt6_unregister_notifier); -+/* QCA NSS ECM support - End */ -+ - /* - * /proc - */ diff --git a/target/linux/ipq60xx/patches-5.15/0601-5.15-netfilter-export-udp_get_timeouts-function.patch b/target/linux/ipq60xx/patches-5.15/0601-5.15-netfilter-export-udp_get_timeouts-function.patch deleted file mode 100644 index c0504805b..000000000 --- a/target/linux/ipq60xx/patches-5.15/0601-5.15-netfilter-export-udp_get_timeouts-function.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 9d2a00412fde5f5d7dbd341f42acb6799c2db65c Mon Sep 17 00:00:00 2001 -From: Simon Casey -Date: Wed, 2 Feb 2022 19:30:09 +0100 -Subject: [PATCH] Update 601-netfilter-export-udp_get_timeouts-function.patch - for kernel 5.15 - ---- - include/net/netfilter/nf_conntrack_timeout.h | 1 + - net/netfilter/nf_conntrack_proto_udp.c | 3 ++- - 2 files changed, 3 insertions(+), 1 deletion(-) - ---- a/include/net/netfilter/nf_conntrack_timeout.h -+++ b/include/net/netfilter/nf_conntrack_timeout.h -@@ -123,5 +123,6 @@ static inline void nf_ct_destroy_timeout - extern struct nf_ct_timeout *(*nf_ct_timeout_find_get_hook)(struct net *net, const char *name); - extern void (*nf_ct_timeout_put_hook)(struct nf_ct_timeout *timeout); - #endif -+extern unsigned int *udp_get_timeouts(struct net *net); - - #endif /* _NF_CONNTRACK_TIMEOUT_H */ ---- a/net/netfilter/nf_conntrack_proto_udp.c -+++ b/net/netfilter/nf_conntrack_proto_udp.c -@@ -29,10 +29,11 @@ static const unsigned int udp_timeouts[U - [UDP_CT_REPLIED] = 120*HZ, - }; - --static unsigned int *udp_get_timeouts(struct net *net) -+unsigned int *udp_get_timeouts(struct net *net) - { - return nf_udp_pernet(net)->timeouts; - } -+EXPORT_SYMBOL(udp_get_timeouts); - - static void udp_error_log(const struct sk_buff *skb, - const struct nf_hook_state *state, diff --git a/target/linux/ipq60xx/patches-5.15/0602-5.15-qca-add-pppoe-offload-support.patch b/target/linux/ipq60xx/patches-5.15/0602-5.15-qca-add-pppoe-offload-support.patch deleted file mode 100644 index e1412b752..000000000 --- a/target/linux/ipq60xx/patches-5.15/0602-5.15-qca-add-pppoe-offload-support.patch +++ /dev/null @@ -1,602 +0,0 @@ -From ac4b71aecf237fd07a29788706d198b4e36fa660 Mon Sep 17 00:00:00 2001 -From: Simon Casey -Date: Wed, 2 Feb 2022 19:32:54 +0100 -Subject: [PATCH] Update 602-qca-add-pppoe-offload-support.patch for kernel - 5.15 - ---- - drivers/net/ppp/ppp_generic.c | 276 +++++++++++++++++++++++++++++++++- - drivers/net/ppp/pppoe.c | 82 +++++++++- - include/linux/if_pppox.h | 13 ++ - include/linux/netdevice.h | 19 +++ - include/linux/ppp_channel.h | 63 +++++++- - 5 files changed, 445 insertions(+), 8 deletions(-) - ---- a/drivers/net/ppp/ppp_generic.c -+++ b/drivers/net/ppp/ppp_generic.c -@@ -48,6 +48,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -253,6 +254,25 @@ struct ppp_net { - #define seq_before(a, b) ((s32)((a) - (b)) < 0) - #define seq_after(a, b) ((s32)((a) - (b)) > 0) - -+ -+/* -+ * Registration/Unregistration methods -+ * for PPP channel connect and disconnect event notifications. -+ */ -+RAW_NOTIFIER_HEAD(ppp_channel_connection_notifier_list); -+ -+void ppp_channel_connection_register_notify(struct notifier_block *nb) -+{ -+ raw_notifier_chain_register(&ppp_channel_connection_notifier_list, nb); -+} -+EXPORT_SYMBOL_GPL(ppp_channel_connection_register_notify); -+ -+void ppp_channel_connection_unregister_notify(struct notifier_block *nb) -+{ -+ raw_notifier_chain_unregister(&ppp_channel_connection_notifier_list, nb); -+} -+EXPORT_SYMBOL_GPL(ppp_channel_connection_unregister_notify); -+ - /* Prototypes. */ - static int ppp_unattached_ioctl(struct net *net, struct ppp_file *pf, - struct file *file, unsigned int cmd, unsigned long arg); -@@ -3452,7 +3472,10 @@ ppp_connect_channel(struct channel *pch, - struct ppp_net *pn; - int ret = -ENXIO; - int hdrlen; -+ int ppp_proto; -+ int version; - -+ int notify = 0; - pn = ppp_pernet(pch->chan_net); - - mutex_lock(&pn->all_ppp_mutex); -@@ -3484,13 +3507,40 @@ ppp_connect_channel(struct channel *pch, - ++ppp->n_channels; - pch->ppp = ppp; - refcount_inc(&ppp->file.refcnt); -+ -+ /* Set the netdev priv flag if the prototype -+ * is L2TP or PPTP. Return success in all cases -+ */ -+ if (!pch->chan) -+ goto out2; -+ -+ ppp_proto = ppp_channel_get_protocol(pch->chan); -+ if (ppp_proto == PX_PROTO_PPTP) { -+ ppp->dev->priv_flags_ext |= IFF_EXT_PPP_PPTP; -+ } else if (ppp_proto == PX_PROTO_OL2TP) { -+ version = ppp_channel_get_proto_version(pch->chan); -+ if (version == 2) -+ ppp->dev->priv_flags_ext |= IFF_EXT_PPP_L2TPV2; -+ else if (version == 3) -+ ppp->dev->priv_flags_ext |= IFF_EXT_PPP_L2TPV3; -+ } -+ notify = 1; -+ -+ out2: - ppp_unlock(ppp); - ret = 0; -- - outl: - write_unlock_bh(&pch->upl); - out: - mutex_unlock(&pn->all_ppp_mutex); -+ -+ if (notify && ppp && ppp->dev) { -+ dev_hold(ppp->dev); -+ raw_notifier_call_chain(&ppp_channel_connection_notifier_list, -+ PPP_CHANNEL_CONNECT, ppp->dev); -+ dev_put(ppp->dev); -+ } -+ - return ret; - } - -@@ -3508,6 +3558,13 @@ ppp_disconnect_channel(struct channel *p - pch->ppp = NULL; - write_unlock_bh(&pch->upl); - if (ppp) { -+ if (ppp->dev) { -+ dev_hold(ppp->dev); -+ raw_notifier_call_chain(&ppp_channel_connection_notifier_list, -+ PPP_CHANNEL_DISCONNECT, ppp->dev); -+ dev_put(ppp->dev); -+ } -+ - /* remove it from the ppp unit's list */ - ppp_lock(ppp); - list_del(&pch->clist); -@@ -3587,6 +3644,222 @@ static void *unit_find(struct idr *p, in - return idr_find(p, n); - } - -+/* Updates the PPP interface statistics. */ -+void ppp_update_stats(struct net_device *dev, unsigned long rx_packets, -+ unsigned long rx_bytes, unsigned long tx_packets, -+ unsigned long tx_bytes, unsigned long rx_errors, -+ unsigned long tx_errors, unsigned long rx_dropped, -+ unsigned long tx_dropped) -+{ -+ struct ppp *ppp; -+ -+ if (!dev) -+ return; -+ -+ if (dev->type != ARPHRD_PPP) -+ return; -+ -+ ppp = netdev_priv(dev); -+ -+ ppp_xmit_lock(ppp); -+ ppp->stats64.tx_packets += tx_packets; -+ ppp->stats64.tx_bytes += tx_bytes; -+ ppp->dev->stats.tx_errors += tx_errors; -+ ppp->dev->stats.tx_dropped += tx_dropped; -+ if (tx_packets) -+ ppp->last_xmit = jiffies; -+ ppp_xmit_unlock(ppp); -+ -+ ppp_recv_lock(ppp); -+ ppp->stats64.rx_packets += rx_packets; -+ ppp->stats64.rx_bytes += rx_bytes; -+ ppp->dev->stats.rx_errors += rx_errors; -+ ppp->dev->stats.rx_dropped += rx_dropped; -+ if (rx_packets) -+ ppp->last_recv = jiffies; -+ ppp_recv_unlock(ppp); -+} -+ -+/* Returns >0 if the device is a multilink PPP netdevice, 0 if not or < 0 if -+ * the device is not PPP. -+ */ -+int ppp_is_multilink(struct net_device *dev) -+{ -+ struct ppp *ppp; -+ unsigned int flags; -+ -+ if (!dev) -+ return -1; -+ -+ if (dev->type != ARPHRD_PPP) -+ return -1; -+ -+ ppp = netdev_priv(dev); -+ ppp_lock(ppp); -+ flags = ppp->flags; -+ ppp_unlock(ppp); -+ -+ if (flags & SC_MULTILINK) -+ return 1; -+ -+ return 0; -+} -+EXPORT_SYMBOL(ppp_is_multilink); -+ -+/* ppp_channel_get_protocol() -+ * Call this to obtain the underlying protocol of the PPP channel, -+ * e.g. PX_PROTO_OE -+ * -+ * NOTE: Some channels do not use PX sockets so the protocol value may be very -+ * different for them. -+ * NOTE: -1 indicates failure. -+ * NOTE: Once you know the channel protocol you may then either cast 'chan' to -+ * its sub-class or use the channel protocol specific API's as provided by that -+ * channel sub type. -+ */ -+int ppp_channel_get_protocol(struct ppp_channel *chan) -+{ -+ if (!chan->ops->get_channel_protocol) -+ return -1; -+ -+ return chan->ops->get_channel_protocol(chan); -+} -+EXPORT_SYMBOL(ppp_channel_get_protocol); -+ -+/* ppp_channel_get_proto_version() -+ * Call this to get channel protocol version -+ */ -+int ppp_channel_get_proto_version(struct ppp_channel *chan) -+{ -+ if (!chan->ops->get_channel_protocol_ver) -+ return -1; -+ -+ return chan->ops->get_channel_protocol_ver(chan); -+} -+EXPORT_SYMBOL(ppp_channel_get_proto_version); -+ -+/* ppp_channel_hold() -+ * Call this to hold a channel. -+ * -+ * Returns true on success or false if the hold could not happen. -+ * -+ * NOTE: chan must be protected against destruction during this call - -+ * either by correct locking etc. or because you already have an implicit -+ * or explicit hold to the channel already and this is an additional hold. -+ */ -+bool ppp_channel_hold(struct ppp_channel *chan) -+{ -+ if (!chan->ops->hold) -+ return false; -+ -+ chan->ops->hold(chan); -+ return true; -+} -+EXPORT_SYMBOL(ppp_channel_hold); -+ -+/* ppp_channel_release() -+ * Call this to release a hold you have upon a channel -+ */ -+void ppp_channel_release(struct ppp_channel *chan) -+{ -+ chan->ops->release(chan); -+} -+EXPORT_SYMBOL(ppp_channel_release); -+ -+/* Check if ppp xmit lock is on hold */ -+bool ppp_is_xmit_locked(struct net_device *dev) -+{ -+ struct ppp *ppp; -+ -+ if (!dev) -+ return false; -+ -+ if (dev->type != ARPHRD_PPP) -+ return false; -+ -+ ppp = netdev_priv(dev); -+ if (!ppp) -+ return false; -+ -+ if (spin_is_locked(&(ppp)->wlock)) -+ return true; -+ -+ return false; -+} -+EXPORT_SYMBOL(ppp_is_xmit_locked); -+ -+/* ppp_hold_channels() -+ * Returns the PPP channels of the PPP device, storing each one into -+ * channels[]. -+ * -+ * channels[] has chan_sz elements. -+ * This function returns the number of channels stored, up to chan_sz. -+ * It will return < 0 if the device is not PPP. -+ * -+ * You MUST release the channels using ppp_release_channels(). -+ */ -+int ppp_hold_channels(struct net_device *dev, struct ppp_channel *channels[], -+ unsigned int chan_sz) -+{ -+ struct ppp *ppp; -+ int c; -+ struct channel *pch; -+ -+ if (!dev) -+ return -1; -+ -+ if (dev->type != ARPHRD_PPP) -+ return -1; -+ -+ ppp = netdev_priv(dev); -+ -+ c = 0; -+ ppp_lock(ppp); -+ list_for_each_entry(pch, &ppp->channels, clist) { -+ struct ppp_channel *chan; -+ -+ if (!pch->chan) { -+ /* Channel is going / gone away */ -+ continue; -+ } -+ -+ if (c == chan_sz) { -+ /* No space to record channel */ -+ ppp_unlock(ppp); -+ return c; -+ } -+ -+ /* Hold the channel, if supported */ -+ chan = pch->chan; -+ if (!chan->ops->hold) -+ continue; -+ -+ chan->ops->hold(chan); -+ -+ /* Record the channel */ -+ channels[c++] = chan; -+ } -+ ppp_unlock(ppp); -+ return c; -+} -+EXPORT_SYMBOL(ppp_hold_channels); -+ -+/* ppp_release_channels() -+ * Releases channels -+ */ -+void ppp_release_channels(struct ppp_channel *channels[], unsigned int chan_sz) -+{ -+ unsigned int c; -+ -+ for (c = 0; c < chan_sz; ++c) { -+ struct ppp_channel *chan; -+ -+ chan = channels[c]; -+ chan->ops->release(chan); -+ } -+} -+EXPORT_SYMBOL(ppp_release_channels); -+ - /* Module/initialization stuff */ - - module_init(ppp_init); -@@ -3603,6 +3876,7 @@ EXPORT_SYMBOL(ppp_input_error); - EXPORT_SYMBOL(ppp_output_wakeup); - EXPORT_SYMBOL(ppp_register_compressor); - EXPORT_SYMBOL(ppp_unregister_compressor); -+EXPORT_SYMBOL(ppp_update_stats); - MODULE_LICENSE("GPL"); - MODULE_ALIAS_CHARDEV(PPP_MAJOR, 0); - MODULE_ALIAS_RTNL_LINK("ppp"); ---- a/drivers/net/ppp/pppoe.c -+++ b/drivers/net/ppp/pppoe.c -@@ -62,6 +62,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -87,7 +88,7 @@ - static int __pppoe_xmit(struct sock *sk, struct sk_buff *skb); - - static const struct proto_ops pppoe_ops; --static const struct ppp_channel_ops pppoe_chan_ops; -+static const struct pppoe_channel_ops pppoe_chan_ops; - - /* per-net private data for this module */ - static unsigned int pppoe_net_id __read_mostly; -@@ -692,7 +693,7 @@ static int pppoe_connect(struct socket * - - po->chan.mtu = dev->mtu - sizeof(struct pppoe_hdr) - 2; - po->chan.private = sk; -- po->chan.ops = &pppoe_chan_ops; -+ po->chan.ops = (struct ppp_channel_ops *)&pppoe_chan_ops; - - error = ppp_register_net_channel(dev_net(dev), &po->chan); - if (error) { -@@ -995,9 +996,80 @@ static int pppoe_fill_forward_path(struc - return 0; - } - --static const struct ppp_channel_ops pppoe_chan_ops = { -- .start_xmit = pppoe_xmit, -- .fill_forward_path = pppoe_fill_forward_path, -+/************************************************************************ -+ * -+ * function called by generic PPP driver to hold channel -+ * -+ ***********************************************************************/ -+static void pppoe_hold_chan(struct ppp_channel *chan) -+{ -+ struct sock *sk = (struct sock *)chan->private; -+ -+ sock_hold(sk); -+} -+ -+/************************************************************************ -+ * -+ * function called by generic PPP driver to release channel -+ * -+ ***********************************************************************/ -+static void pppoe_release_chan(struct ppp_channel *chan) -+{ -+ struct sock *sk = (struct sock *)chan->private; -+ -+ sock_put(sk); -+} -+ -+/************************************************************************ -+ * -+ * function called to get the channel protocol type -+ * -+ ***********************************************************************/ -+static int pppoe_get_channel_protocol(struct ppp_channel *chan) -+{ -+ return PX_PROTO_OE; -+} -+ -+/************************************************************************ -+ * -+ * function called to get the PPPoE channel addressing -+ * NOTE: This function returns a HOLD to the netdevice -+ * -+ ***********************************************************************/ -+static int pppoe_get_addressing(struct ppp_channel *chan, -+ struct pppoe_opt *addressing) -+{ -+ struct sock *sk = (struct sock *)chan->private; -+ struct pppox_sock *po = pppox_sk(sk); -+ int err = 0; -+ -+ *addressing = po->proto.pppoe; -+ if (!addressing->dev) -+ return -ENODEV; -+ -+ dev_hold(addressing->dev); -+ return err; -+} -+ -+/* pppoe_channel_addressing_get() -+ * Return PPPoE channel specific addressing information. -+ */ -+int pppoe_channel_addressing_get(struct ppp_channel *chan, -+ struct pppoe_opt *addressing) -+{ -+ return pppoe_get_addressing(chan, addressing); -+} -+EXPORT_SYMBOL(pppoe_channel_addressing_get); -+ -+static const struct pppoe_channel_ops pppoe_chan_ops = { -+ /* PPPoE specific channel ops */ -+ .get_addressing = pppoe_get_addressing, -+ /* General ppp channel ops */ -+ .ops.start_xmit = pppoe_xmit, -+ .ops.get_channel_protocol = pppoe_get_channel_protocol, -+ .ops.hold = pppoe_hold_chan, -+ .ops.release = pppoe_release_chan, -+ .ops.fill_forward_path = pppoe_fill_forward_path, - }; - - static int pppoe_recvmsg(struct socket *sock, struct msghdr *m, ---- a/include/linux/if_pppox.h -+++ b/include/linux/if_pppox.h -@@ -93,4 +93,17 @@ enum { - PPPOX_DEAD = 16 /* dead, useless, please clean me up!*/ - }; - -+/* -+ * PPPoE Channel specific operations -+ */ -+struct pppoe_channel_ops { -+ /* Must be first - general to all PPP channels */ -+ struct ppp_channel_ops ops; -+ int (*get_addressing)(struct ppp_channel *, struct pppoe_opt *); -+}; -+ -+/* Return PPPoE channel specific addressing information */ -+extern int pppoe_channel_addressing_get(struct ppp_channel *chan, -+ struct pppoe_opt *addressing); -+ - #endif /* !(__LINUX_IF_PPPOX_H) */ ---- a/include/linux/netdevice.h -+++ b/include/linux/netdevice.h -@@ -1686,6 +1686,24 @@ enum netdev_extra_priv_flags { - IFF_NO_IP_ALIGN = 1<<0, - }; - -+ -+/** -+ * enum netdev_priv_flags_ext - &struct net_device priv_flags_ext -+ * -+ * These flags are used to check for device type and can be -+ * set and used by the drivers -+ * -+ */ -+enum netdev_priv_flags_ext { -+ IFF_EXT_TUN_TAP = 1<<0, -+ IFF_EXT_PPP_L2TPV2 = 1<<1, -+ IFF_EXT_PPP_L2TPV3 = 1<<2, -+ IFF_EXT_PPP_PPTP = 1<<3, -+ IFF_EXT_GRE_V4_TAP = 1<<4, -+ IFF_EXT_GRE_V6_TAP = 1<<5, -+ IFF_EXT_IFB = 1<<6, -+}; -+ - #define IFF_802_1Q_VLAN IFF_802_1Q_VLAN - #define IFF_EBRIDGE IFF_EBRIDGE - #define IFF_BONDING IFF_BONDING -@@ -2020,6 +2038,7 @@ struct net_device { - unsigned int flags; - unsigned int priv_flags; - unsigned int extra_priv_flags; -+ unsigned int priv_flags_ext; - const struct net_device_ops *netdev_ops; - int ifindex; - unsigned short gflags; ---- a/include/linux/ppp_channel.h -+++ b/include/linux/ppp_channel.h -@@ -19,6 +19,10 @@ - #include - #include - #include -+#include -+ -+#define PPP_CHANNEL_DISCONNECT 0 -+#define PPP_CHANNEL_CONNECT 1 - - struct ppp_channel; - -@@ -28,9 +32,19 @@ struct ppp_channel_ops { - int (*start_xmit)(struct ppp_channel *, struct sk_buff *); - /* Handle an ioctl call that has come in via /dev/ppp. */ - int (*ioctl)(struct ppp_channel *, unsigned int, unsigned long); -+ /* Get channel protocol type, one of PX_PROTO_XYZ or specific to -+ * the channel subtype -+ */ -+ int (*get_channel_protocol)(struct ppp_channel *); -+ /* Get channel protocol version */ -+ int (*get_channel_protocol_ver)(struct ppp_channel *); -+ /* Hold the channel from being destroyed */ -+ void (*hold)(struct ppp_channel *); -+ /* Release hold on the channel */ -+ void (*release)(struct ppp_channel *); - int (*fill_forward_path)(struct net_device_path_ctx *, -- struct net_device_path *, -- const struct ppp_channel *); -+ struct net_device_path *, -+ const struct ppp_channel *); - }; - - struct ppp_channel { -@@ -74,6 +88,51 @@ extern int ppp_unit_number(struct ppp_ch - /* Get the device name associated with a channel, or NULL if none */ - extern char *ppp_dev_name(struct ppp_channel *); - -+/* Call this to obtain the underlying protocol of the PPP channel, -+ * e.g. PX_PROTO_OE -+ */ -+extern int ppp_channel_get_protocol(struct ppp_channel *); -+ -+/* Call this get protocol version */ -+extern int ppp_channel_get_proto_version(struct ppp_channel *); -+ -+/* Call this to hold a channel */ -+extern bool ppp_channel_hold(struct ppp_channel *); -+ -+/* Call this to release a hold you have upon a channel */ -+extern void ppp_channel_release(struct ppp_channel *); -+ -+/* Release hold on PPP channels */ -+extern void ppp_release_channels(struct ppp_channel *channels[], -+ unsigned int chan_sz); -+ -+/* Hold PPP channels for the PPP device */ -+extern int ppp_hold_channels(struct net_device *dev, -+ struct ppp_channel *channels[], -+ unsigned int chan_sz); -+ -+/* Test if ppp xmit lock is locked */ -+extern bool ppp_is_xmit_locked(struct net_device *dev); -+ -+/* Test if the ppp device is a multi-link ppp device */ -+extern int ppp_is_multilink(struct net_device *dev); -+ -+/* Register the PPP channel connect notifier */ -+extern void ppp_channel_connection_register_notify(struct notifier_block *nb); -+ -+/* Unregister the PPP channel connect notifier */ -+extern void ppp_channel_connection_unregister_notify(struct notifier_block *nb); -+ -+/* Update statistics of the PPP net_device by incrementing related -+ * statistics field value with corresponding parameter -+ */ -+extern void ppp_update_stats(struct net_device *dev, unsigned long rx_packets, -+ unsigned long rx_bytes, unsigned long tx_packets, -+ unsigned long tx_bytes, unsigned long rx_errors, -+ unsigned long tx_errors, unsigned long rx_dropped, -+ unsigned long tx_dropped); -+ -+ - /* - * SMP locking notes: - * The channel code must ensure that when it calls ppp_unregister_channel, diff --git a/target/linux/ipq60xx/patches-5.15/0603-net-core-Flag-to-identify-ingress-shaping-done-for-e.patch b/target/linux/ipq60xx/patches-5.15/0603-net-core-Flag-to-identify-ingress-shaping-done-for-e.patch deleted file mode 100644 index a9fa4b7d3..000000000 --- a/target/linux/ipq60xx/patches-5.15/0603-net-core-Flag-to-identify-ingress-shaping-done-for-e.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 03a9fdd468ba3635b26477ca80a1599c29341aed Mon Sep 17 00:00:00 2001 -From: Simon Casey -Date: Wed, 2 Feb 2022 19:35:35 +0100 -Subject: [PATCH] Update - 603-net-core-Flag-to-identify-ingress-shaping-done-for-e.patch for kernel - 5.15 - -Also combined with 604-net-core-Replace-nss-keyword-with-offload.patch that just changes -variable names created with 603. ---- - include/linux/skbuff.h | 2 ++ - include/net/sch_generic.h | 34 ++++++++++++++++++++++++++++++++++ - 2 files changed, 36 insertions(+) - ---- a/include/linux/skbuff.h -+++ b/include/linux/skbuff.h -@@ -689,6 +689,7 @@ typedef unsigned char *sk_buff_data_t; - * @offload_fwd_mark: Packet was L2-forwarded in hardware - * @offload_l3_fwd_mark: Packet was L3-forwarded in hardware - * @tc_skip_classify: do not classify packet. set by IFB device -+ * @tc_skip_classify_offload: do not classify packet set by offload IFB device - * @tc_at_ingress: used within tc_classify to distinguish in/egress - * @redirected: packet was redirected by packet classifier - * @from_ingress: packet was redirected from the ingress path -@@ -905,6 +906,7 @@ struct sk_buff { - #ifdef CONFIG_NET_CLS_ACT - __u8 tc_skip_classify:1; - __u8 tc_at_ingress:1; -+ __u8 tc_skip_classify_offload:1; - #endif - __u8 redirected:1; - #ifdef CONFIG_NET_REDIRECT ---- a/include/net/sch_generic.h -+++ b/include/net/sch_generic.h -@@ -739,6 +739,40 @@ static inline bool skb_skip_tc_classify( - return false; - } - -+/* -+ * Set skb classify bit field. -+ */ -+static inline void skb_set_tc_classify_offload(struct sk_buff *skb) -+{ -+#ifdef CONFIG_NET_CLS_ACT -+ skb->tc_skip_classify_offload = 1; -+#endif -+} -+ -+/* -+ * Clear skb classify bit field. -+ */ -+static inline void skb_clear_tc_classify_offload(struct sk_buff *skb) -+{ -+#ifdef CONFIG_NET_CLS_ACT -+ skb->tc_skip_classify_offload = 0; -+#endif -+} -+ -+/* -+ * Skip skb processing if sent from ifb dev. -+ */ -+static inline bool skb_skip_tc_classify_offload(struct sk_buff *skb) -+{ -+#ifdef CONFIG_NET_CLS_ACT -+ if (skb->tc_skip_classify_offload) { -+ skb_clear_tc_classify_offload(skb); -+ return true; -+ } -+#endif -+ return false; -+} -+ - /* Reset all TX qdiscs greater than index of a device. */ - static inline void qdisc_reset_all_tx_gt(struct net_device *dev, unsigned int i) - { diff --git a/target/linux/ipq60xx/patches-5.15/0605-5.15-qca-add-add-nss-bridge-mgr-support.patch b/target/linux/ipq60xx/patches-5.15/0605-5.15-qca-add-add-nss-bridge-mgr-support.patch deleted file mode 100644 index 4cf919974..000000000 --- a/target/linux/ipq60xx/patches-5.15/0605-5.15-qca-add-add-nss-bridge-mgr-support.patch +++ /dev/null @@ -1,95 +0,0 @@ -From 3c17a0e1112be70071e98d5208da5b55dcec20a6 Mon Sep 17 00:00:00 2001 -From: Simon Casey -Date: Wed, 2 Feb 2022 19:37:29 +0100 -Subject: [PATCH] Update 605-qca-add-add-nss-bridge-mgr-support.patch for - kernel 5.15 - ---- - include/linux/if_bridge.h | 4 ++++ - net/bridge/br_fdb.c | 25 +++++++++++++++++++++---- - 2 files changed, 25 insertions(+), 4 deletions(-) - ---- a/include/linux/if_bridge.h -+++ b/include/linux/if_bridge.h -@@ -236,4 +236,8 @@ typedef struct net_bridge_port *br_get_d - extern br_get_dst_hook_t __rcu *br_get_dst_hook; - /* QCA NSS ECM support - End */ - -+/* QCA NSS bridge-mgr support - Start */ -+extern struct net_device *br_fdb_bridge_dev_get_and_hold(struct net_bridge *br); -+/* QCA NSS bridge-mgr support - End */ -+ - #endif ---- a/net/bridge/br_fdb.c -+++ b/net/bridge/br_fdb.c -@@ -67,6 +67,15 @@ void br_fdb_update_unregister_notify(str - EXPORT_SYMBOL_GPL(br_fdb_update_unregister_notify); - /* QCA NSS ECM support - End */ - -+/* QCA NSS bridge-mgr support - Start */ -+struct net_device *br_fdb_bridge_dev_get_and_hold(struct net_bridge *br) -+{ -+ dev_hold(br->dev); -+ return br->dev; -+} -+EXPORT_SYMBOL_GPL(br_fdb_bridge_dev_get_and_hold); -+/* QCA NSS bridge-mgr support - End */ -+ - int __init br_fdb_init(void) - { - br_fdb_cache = kmem_cache_create("bridge_fdb_cache", -@@ -372,7 +381,7 @@ void br_fdb_cleanup(struct work_struct * - unsigned long delay = hold_time(br); - unsigned long work_delay = delay; - unsigned long now = jiffies; -- u8 mac_addr[6]; /* QCA NSS ECM support */ -+ struct br_fdb_event fdb_event; /* QCA NSS bridge-mgr support */ - - /* this part is tricky, in order to avoid blocking learning and - * consequently forwarding, we rely on rcu to delete objects with -@@ -400,12 +409,13 @@ void br_fdb_cleanup(struct work_struct * - } else { - spin_lock_bh(&br->hash_lock); - if (!hlist_unhashed(&f->fdb_node)) { -- ether_addr_copy(mac_addr, f->key.addr.addr); -+ memset(&fdb_event, 0, sizeof(fdb_event)); -+ ether_addr_copy(fdb_event.addr, f->key.addr.addr); - fdb_delete(br, f, true); - /* QCA NSS ECM support - Start */ - atomic_notifier_call_chain( - &br_fdb_update_notifier_list, 0, -- (void *)mac_addr); -+ (void *)&fdb_event); - /* QCA NSS ECM support - End */ - } - spin_unlock_bh(&br->hash_lock); -@@ -623,6 +633,7 @@ void br_fdb_update(struct net_bridge *br - const unsigned char *addr, u16 vid, unsigned long flags) - { - struct net_bridge_fdb_entry *fdb; -+ struct br_fdb_event fdb_event; /* QCA NSS bridge-mgr support */ - - /* some users want to always flood. */ - if (hold_time(br) == 0) -@@ -648,6 +659,12 @@ void br_fdb_update(struct net_bridge *br - if (unlikely(source != READ_ONCE(fdb->dst) && - !test_bit(BR_FDB_STICKY, &fdb->flags))) { - br_switchdev_fdb_notify(br, fdb, RTM_DELNEIGH); -+ /* QCA NSS bridge-mgr support - Start */ -+ ether_addr_copy(fdb_event.addr, addr); -+ fdb_event.br = br; -+ fdb_event.orig_dev = READ_ONCE(fdb->dst->dev); -+ fdb_event.dev = source->dev; -+ /* QCA NSS bridge-mgr support - End */ - WRITE_ONCE(fdb->dst, source); - fdb_modified = true; - /* Take over HW learned entry */ -@@ -659,7 +676,7 @@ void br_fdb_update(struct net_bridge *br - /* QCA NSS ECM support - Start */ - atomic_notifier_call_chain( - &br_fdb_update_notifier_list, -- 0, (void *)addr); -+ 0, (void *)&fdb_event); - /* QCA NSS ECM support - End */ - } - diff --git a/target/linux/ipq60xx/patches-5.15/0606-5.15-qca-nss-ecm-bonding-add-bond_get_id.patch b/target/linux/ipq60xx/patches-5.15/0606-5.15-qca-nss-ecm-bonding-add-bond_get_id.patch deleted file mode 100644 index 5480ae631..000000000 --- a/target/linux/ipq60xx/patches-5.15/0606-5.15-qca-nss-ecm-bonding-add-bond_get_id.patch +++ /dev/null @@ -1,81 +0,0 @@ ---- a/drivers/net/bonding/bond_main.c -+++ b/drivers/net/bonding/bond_main.c -@@ -249,6 +249,9 @@ static const struct flow_dissector_key f - }, - }; - -+/* QCA NSS bonding support */ -+static unsigned long bond_id_mask = 0xFFFFFFF0; -+ - static struct flow_dissector flow_keys_bonding __read_mostly; - - /*-------------------------- Forward declarations ---------------------------*/ -@@ -4115,6 +4118,23 @@ static int bond_get_lowest_level_rcu(str - } - #endif - -+/* QCA NSS bonding support */ -+int bond_get_id(struct net_device *bond_dev) -+{ -+ struct bonding *bond; -+ int bond_id = 0; -+ -+ if (!((bond_dev->priv_flags & IFF_BONDING) && -+ (bond_dev->flags & IFF_MASTER))) -+ return -EINVAL; -+ -+ bond = netdev_priv(bond_dev); -+ bond_id = bond->id; -+ -+ return bond_id; -+} -+EXPORT_SYMBOL(bond_get_id); -+ - static void bond_get_stats(struct net_device *bond_dev, - struct rtnl_link_stats64 *stats) - { -@@ -5447,6 +5467,10 @@ static void bond_destructor(struct net_d - - if (bond->rr_tx_counter) - free_percpu(bond->rr_tx_counter); -+ -+ /* QCA NSS bonding support */ -+ if (bond->id != (~0U)) -+ clear_bit(bond->id, &bond_id_mask); - } - - void bond_setup(struct net_device *bond_dev) -@@ -6020,7 +6044,14 @@ int bond_create(struct net *net, const c - - bond_work_init_all(bond); - -- rtnl_unlock(); -+ /* QCA NSS bonding support */ -+ bond->id = ~0U; -+ if (bond_id_mask != (~0UL)) { -+ bond->id = (u32)ffz(bond_id_mask); -+ set_bit(bond->id, &bond_id_mask); -+ } -+ -+ rtnl_unlock(); - return 0; - } - ---- a/include/net/bonding.h -+++ b/include/net/bonding.h -@@ -257,6 +257,7 @@ struct bonding { - spinlock_t ipsec_lock; - #endif /* CONFIG_XFRM_OFFLOAD */ - struct bpf_prog *xdp_prog; -+ u32 id; /* QCA NSS bonding */ - }; - - #define bond_slave_get_rcu(dev) \ -@@ -631,6 +632,7 @@ struct bond_net { - - int bond_arp_rcv(const struct sk_buff *skb, struct bonding *bond, struct slave *slave); - netdev_tx_t bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, struct net_device *slave_dev); -+int bond_get_id(struct net_device *bond_dev); /* QCA NSS bonding support */ - int bond_create(struct net *net, const char *name); - int bond_create_sysfs(struct bond_net *net); - void bond_destroy_sysfs(struct bond_net *net); diff --git a/target/linux/ipq60xx/patches-5.15/0607-5.15-qca-nss-ecm-Add-bridge-join-and-leave-netdev-cmds.patch b/target/linux/ipq60xx/patches-5.15/0607-5.15-qca-nss-ecm-Add-bridge-join-and-leave-netdev-cmds.patch deleted file mode 100644 index 6f812b26d..000000000 --- a/target/linux/ipq60xx/patches-5.15/0607-5.15-qca-nss-ecm-Add-bridge-join-and-leave-netdev-cmds.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/net/core/dev.c -+++ b/net/core/dev.c -@@ -1705,7 +1705,7 @@ const char *netdev_cmd_to_name(enum netd - N(UDP_TUNNEL_DROP_INFO) N(CHANGE_TX_QUEUE_LEN) - N(CVLAN_FILTER_PUSH_INFO) N(CVLAN_FILTER_DROP_INFO) - N(SVLAN_FILTER_PUSH_INFO) N(SVLAN_FILTER_DROP_INFO) -- N(PRE_CHANGEADDR) -+ N(PRE_CHANGEADDR) N(BR_JOIN) N(BR_LEAVE) - } - #undef N - return "UNKNOWN_NETDEV_EVENT"; diff --git a/target/linux/ipq60xx/patches-5.15/0800-5.15-qca-nss-ssdk-delete-fdb-entry-using-netdev.patch b/target/linux/ipq60xx/patches-5.15/0800-5.15-qca-nss-ssdk-delete-fdb-entry-using-netdev.patch deleted file mode 100644 index 041d3a460..000000000 --- a/target/linux/ipq60xx/patches-5.15/0800-5.15-qca-nss-ssdk-delete-fdb-entry-using-netdev.patch +++ /dev/null @@ -1,32 +0,0 @@ ---- a/include/linux/if_bridge.h -+++ b/include/linux/if_bridge.h -@@ -240,4 +240,7 @@ extern br_get_dst_hook_t __rcu *br_get_d - extern struct net_device *br_fdb_bridge_dev_get_and_hold(struct net_bridge *br); - /* QCA NSS bridge-mgr support - End */ - -+/* QCA NSS SSDK support - Start */ -+extern int br_fdb_delete_by_netdev(struct net_device *dev,const unsigned char *addr, u16 vid); -+/* QCA NSS SSDK support - End */ - #endif ---- a/net/bridge/br_fdb.c -+++ b/net/bridge/br_fdb.c -@@ -1246,6 +1246,19 @@ static int __br_fdb_delete(struct net_br - return err; - } - -+int br_fdb_delete_by_netdev(struct net_device *dev, -+ const unsigned char *addr, u16 vid) -+{ -+ int err; -+ -+ rtnl_lock(); -+ err = br_fdb_delete(NULL, NULL, dev, addr, vid); -+ rtnl_unlock(); -+ -+ return err; -+} -+EXPORT_SYMBOL_GPL(br_fdb_delete_by_netdev); -+ - /* Remove neighbor entry with RTM_DELNEIGH */ - int br_fdb_delete(struct ndmsg *ndm, struct nlattr *tb[], - struct net_device *dev, diff --git a/target/linux/ipq60xx/patches-5.15/0902-5.15-arm64-provide-dma-cache-routines-with-same-API-as-32.patch b/target/linux/ipq60xx/patches-5.15/0902-5.15-arm64-provide-dma-cache-routines-with-same-API-as-32.patch deleted file mode 100644 index b5f7e2367..000000000 --- a/target/linux/ipq60xx/patches-5.15/0902-5.15-arm64-provide-dma-cache-routines-with-same-API-as-32.patch +++ /dev/null @@ -1,29 +0,0 @@ -From a2f32cec773113a9d0a80f0b20947da9bc29f3bd Mon Sep 17 00:00:00 2001 -From: Simon Casey -Date: Wed, 2 Feb 2022 20:17:21 +0100 -Subject: [PATCH] Update - 902-arm64-provide-dma-cache-routines-with-same-API-as-32.patch for kernel - 5.15 - ---- - arch/arm64/include/asm/cacheflush.h | 9 +++++++++ - 1 file changed, 9 insertions(+) - ---- a/arch/arm64/include/asm/cacheflush.h -+++ b/arch/arm64/include/asm/cacheflush.h -@@ -110,6 +110,15 @@ static inline void flush_icache_range(un - extern void __dma_map_area(const void *, size_t, int); - extern void __dma_unmap_area(const void *, size_t, int); - extern void __dma_flush_area(const void *, size_t); -+extern void __dma_inv_area(const void *start, const void *end); -+extern void __dma_clean_area(const void *start, const void *end); -+ -+#define dmac_flush_range(start, end) \ -+ __dma_flush_area(start, (void *)(end) - (void *)(start)) -+#define dmac_inv_range(start, end) \ -+ __dma_inv_area(start, end) -+#define dmac_clean_range(start, end) \ -+ __dma_clean_area(start, end) - - /* - * Copy user data from/to a page which is mapped into a different diff --git a/target/linux/ipq60xx/patches-5.15/0903-5.15-arm64-mm-export-__dma_inv_area-and-__dma_clean_area.patch b/target/linux/ipq60xx/patches-5.15/0903-5.15-arm64-mm-export-__dma_inv_area-and-__dma_clean_area.patch deleted file mode 100644 index e96e9bd70..000000000 --- a/target/linux/ipq60xx/patches-5.15/0903-5.15-arm64-mm-export-__dma_inv_area-and-__dma_clean_area.patch +++ /dev/null @@ -1,56 +0,0 @@ -From 6fae2dc7f45d14b5341e9929b5c5fef60596ed4f Mon Sep 17 00:00:00 2001 -From: Simon Casey -Date: Wed, 2 Feb 2022 20:25:38 +0100 -Subject: [PATCH] Update - 903-arm64-mm-export-__dma_inv_area-and-__dma_clean_area.patch for kernel 5.15 - ---- - arch/arm64/include/asm/cacheflush.h | 4 ++-- - arch/arm64/mm/cache.S | 4 ++-- - arch/arm64/mm/flush.c | 2 ++ - 3 files changed, 6 insertions(+), 4 deletions(-) - ---- a/arch/arm64/include/asm/cacheflush.h -+++ b/arch/arm64/include/asm/cacheflush.h -@@ -110,8 +110,8 @@ static inline void flush_icache_range(un - extern void __dma_map_area(const void *, size_t, int); - extern void __dma_unmap_area(const void *, size_t, int); - extern void __dma_flush_area(const void *, size_t); --extern void __dma_inv_area(const void *start, const void *end); --extern void __dma_clean_area(const void *start, const void *end); -+extern void __dma_inv_area(const void *, const void *); -+extern void __dma_clean_area(const void *, const void *); - - #define dmac_flush_range(start, end) \ - __dma_flush_area(start, (void *)(end) - (void *)(start)) ---- a/arch/arm64/mm/cache.S -+++ b/arch/arm64/mm/cache.S -@@ -140,7 +140,7 @@ SYM_FUNC_END(dcache_clean_pou) - * - start - kernel start address of region - * - end - kernel end address of region - */ --SYM_FUNC_START_LOCAL(__dma_inv_area) -+SYM_FUNC_START(__dma_inv_area) - SYM_FUNC_START_PI(dcache_inval_poc) - /* FALLTHROUGH */ - -@@ -178,7 +178,7 @@ SYM_FUNC_END(__dma_inv_area) - * - start - virtual start address of region - * - end - virtual end address of region - */ --SYM_FUNC_START_LOCAL(__dma_clean_area) -+SYM_FUNC_START(__dma_clean_area) - SYM_FUNC_START_PI(dcache_clean_poc) - /* FALLTHROUGH */ - ---- a/arch/arm64/mm/flush.c -+++ b/arch/arm64/mm/flush.c -@@ -77,6 +77,8 @@ EXPORT_SYMBOL(flush_dcache_page); - * Additional functions defined in assembly. - */ - EXPORT_SYMBOL(caches_clean_inval_pou); -+EXPORT_SYMBOL(__dma_inv_area); -+EXPORT_SYMBOL(__dma_clean_area); - - #ifdef CONFIG_ARCH_HAS_PMEM_API - void arch_wb_cache_pmem(void *addr, size_t size) diff --git a/target/linux/ipq60xx/patches-5.15/1000-arm64-dts-add-OpenWrt-DTS-files.patch b/target/linux/ipq60xx/patches-5.15/1000-arm64-dts-add-OpenWrt-DTS-files.patch deleted file mode 100644 index 38175c72d..000000000 --- a/target/linux/ipq60xx/patches-5.15/1000-arm64-dts-add-OpenWrt-DTS-files.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0b8ea8ba796dfeb9e9012ae07633e9df15c4c7da Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Tue, 11 May 2021 13:29:33 +0200 -Subject: [PATCH 1000/1011] arm64: dts: add OpenWrt DTS files - -Lets add custom OpenWrt DTS files to Makefile. - -Signed-off-by: Robert Marko -[mrnuke: Replace ipq807x dtbs with ipx601x] -Signed-off-by: Alexandru Gagniuc ---- - arch/arm64/boot/dts/qcom/Makefile | 1 + - 1 file changed, 1 insertion(+) - ---- a/arch/arm64/boot/dts/qcom/Makefile -+++ b/arch/arm64/boot/dts/qcom/Makefile -@@ -4,6 +4,11 @@ dtb-$(CONFIG_ARCH_QCOM) += apq8094-sony- - dtb-$(CONFIG_ARCH_QCOM) += apq8096-db820c.dtb - dtb-$(CONFIG_ARCH_QCOM) += apq8096-ifc6640.dtb - dtb-$(CONFIG_ARCH_QCOM) += ipq6018-cp01-c1.dtb -+dtb-$(CONFIG_ARCH_QCOM) += ipq6018-eap610-outdoor.dtb -+dtb-$(CONFIG_ARCH_QCOM) += ipq6018-mr7350.dtb -+dtb-$(CONFIG_ARCH_QCOM) += ipq6018-ax18.dtb -+dtb-$(CONFIG_ARCH_QCOM) += ipq6018-m2.dtb -+dtb-$(CONFIG_ARCH_QCOM) += ipq6018-v6.dtb - dtb-$(CONFIG_ARCH_QCOM) += ipq8074-hk01.dtb - dtb-$(CONFIG_ARCH_QCOM) += ipq8074-hk10-c1.dtb - dtb-$(CONFIG_ARCH_QCOM) += ipq8074-hk10-c2.dtb diff --git a/target/linux/ipq60xx/patches-5.15/1001-arm64-dts-qcom-ipq6018-Add-mdio-bus-description.patch b/target/linux/ipq60xx/patches-5.15/1001-arm64-dts-qcom-ipq6018-Add-mdio-bus-description.patch deleted file mode 100644 index 439fc97cd..000000000 --- a/target/linux/ipq60xx/patches-5.15/1001-arm64-dts-qcom-ipq6018-Add-mdio-bus-description.patch +++ /dev/null @@ -1,35 +0,0 @@ -From e6beff2e1210057ff2226d3dae088e91ba2941dc Mon Sep 17 00:00:00 2001 -From: Baruch Siach -Date: Mon, 28 Feb 2022 08:58:44 +0200 -Subject: [PATCH 1001/1011] arm64: dts: qcom: ipq6018: Add mdio bus description - -The IPQ60xx has the same MDIO bug block as IPQ4019. Add IO range and -clock resources description. - -Reviewed-by: Bryan O'Donoghue -Signed-off-by: Baruch Siach -Signed-off-by: Bjorn Andersson -Link: https://lore.kernel.org/r/ef01a79ccc6ef86dc3a10d0fa3331794d49e9859.1646031524.git.baruch@tkos.co.il ---- - arch/arm64/boot/dts/qcom/ipq6018.dtsi | 10 ++++++++++ - 1 file changed, 10 insertions(+) - ---- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi -@@ -669,6 +669,16 @@ - }; - }; - -+ mdio: mdio@90000 { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ compatible = "qcom,ipq6018-mdio", "qcom,ipq4019-mdio"; -+ reg = <0x0 0x90000 0x0 0x64>; -+ clocks = <&gcc GCC_MDIO_AHB_CLK>; -+ clock-names = "gcc_mdio_ahb_clk"; -+ status = "disabled"; -+ }; -+ - qusb_phy_1: qusb@59000 { - compatible = "qcom,ipq6018-qusb2-phy"; - reg = <0x0 0x059000 0x0 0x180>; diff --git a/target/linux/ipq60xx/patches-5.15/1002-clk-qcom-add-support-for-hw-controlled-RCG.patch b/target/linux/ipq60xx/patches-5.15/1002-clk-qcom-add-support-for-hw-controlled-RCG.patch deleted file mode 100644 index 3f0ddeb3b..000000000 --- a/target/linux/ipq60xx/patches-5.15/1002-clk-qcom-add-support-for-hw-controlled-RCG.patch +++ /dev/null @@ -1,143 +0,0 @@ -From e21cc1fb80e1b220628f565bb003f6682cadea16 Mon Sep 17 00:00:00 2001 -From: Praveenkumar I -Date: Tue, 13 Jun 2017 15:30:39 +0530 -Subject: [PATCH 1002/1011] clk: qcom: add support for hw controlled RCG -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The current driver generates stack trace during RCG update if the RCG -is off and new parent source is also disabled. For hardware controlled -RCG’s, clock is forced on during update process and goes back to off -status once switch is completed. - -Since the new parent is in disabled state so update bit won’t be -cleared. The check for update bit can be skipped in this case. - -Signed-off-by: Abhishek Sahu -Signed-off-by: Praveenkumar I -Signed-off-by: Alexandru Gagniuc ---- - drivers/clk/qcom/clk-rcg.h | 4 ++++ - drivers/clk/qcom/clk-rcg2.c | 29 ++++++++++++++++++++++------- - 2 files changed, 26 insertions(+), 7 deletions(-) - ---- a/drivers/clk/qcom/clk-rcg.h -+++ b/drivers/clk/qcom/clk-rcg.h -@@ -135,6 +135,7 @@ extern const struct clk_ops clk_dyn_rcg_ - * @mnd_width: number of bits in m/n/d values - * @hid_width: number of bits in half integer divider - * @safe_src_index: safe src index value -+ * @flags: RCG2 specific clock flags - * @parent_map: map from software's parent index to hardware's src_sel field - * @freq_tbl: frequency table - * @clkr: regmap clock handle -@@ -145,6 +146,9 @@ struct clk_rcg2 { - u8 mnd_width; - u8 hid_width; - u8 safe_src_index; -+ -+#define CLK_RCG2_HW_CONTROLLED BIT(0) -+ u8 flags; - const struct parent_map *parent_map; - const struct freq_tbl *freq_tbl; - struct clk_regmap clkr; ---- a/drivers/clk/qcom/clk-rcg2.c -+++ b/drivers/clk/qcom/clk-rcg2.c -@@ -98,7 +98,7 @@ err: - return 0; - } - --static int update_config(struct clk_rcg2 *rcg) -+static int update_config(struct clk_rcg2 *rcg, bool check_update_clear) - { - int count, ret; - u32 cmd; -@@ -110,6 +110,9 @@ static int update_config(struct clk_rcg2 - if (ret) - return ret; - -+ if (!check_update_clear) -+ return 0; -+ - /* Wait for update to take effect */ - for (count = 500; count > 0; count--) { - ret = regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CMD_REG, &cmd); -@@ -128,14 +131,19 @@ static int clk_rcg2_set_parent(struct cl - { - struct clk_rcg2 *rcg = to_clk_rcg2(hw); - int ret; -+ bool check_update_clear = true; - u32 cfg = rcg->parent_map[index].cfg << CFG_SRC_SEL_SHIFT; - -+ if ((rcg->flags & CLK_RCG2_HW_CONTROLLED) && -+ !clk_hw_is_enabled(clk_hw_get_parent_by_index(hw, index))) -+ check_update_clear = false; -+ - ret = regmap_update_bits(rcg->clkr.regmap, RCG_CFG_OFFSET(rcg), - CFG_SRC_SEL_MASK, cfg); - if (ret) - return ret; - -- return update_config(rcg); -+ return update_config(rcg, check_update_clear); - } - - /* -@@ -306,12 +314,19 @@ static int __clk_rcg2_configure(struct c - static int clk_rcg2_configure(struct clk_rcg2 *rcg, const struct freq_tbl *f) - { - int ret; -+ bool check_update_clear = true; -+ struct clk_hw *hw = &rcg->clkr.hw; -+ int index = qcom_find_src_index(hw, rcg->parent_map, f->src); - - ret = __clk_rcg2_configure(rcg, f); - if (ret) - return ret; - -- return update_config(rcg); -+ if ((rcg->flags & CLK_RCG2_HW_CONTROLLED) && -+ !clk_hw_is_enabled(clk_hw_get_parent_by_index(hw, index))) -+ check_update_clear = false; -+ -+ return update_config(rcg, check_update_clear); - } - - static int __clk_rcg2_set_rate(struct clk_hw *hw, unsigned long rate, -@@ -442,7 +457,7 @@ static int clk_rcg2_set_duty_cycle(struc - if (ret) - return ret; - -- return update_config(rcg); -+ return update_config(rcg, true); - } - - const struct clk_ops clk_rcg2_ops = { -@@ -904,7 +919,7 @@ static int clk_gfx3d_set_rate_and_parent - if (ret) - return ret; - -- return update_config(rcg); -+ return update_config(rcg, true); - } - - static int clk_gfx3d_set_rate(struct clk_hw *hw, unsigned long rate, -@@ -1016,7 +1031,7 @@ static int clk_rcg2_shared_enable(struct - if (ret) - return ret; - -- ret = update_config(rcg); -+ ret = update_config(rcg, true); - if (ret) - return ret; - -@@ -1047,7 +1062,7 @@ static void clk_rcg2_shared_disable(stru - regmap_write(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG, - rcg->safe_src_index << CFG_SRC_SEL_SHIFT); - -- update_config(rcg); -+ update_config(rcg, true); - - clk_rcg2_clear_force_enable(hw); - diff --git a/target/linux/ipq60xx/patches-5.15/1003-clk-qcom-ipq6018-add-missing-clock-flags.patch b/target/linux/ipq60xx/patches-5.15/1003-clk-qcom-ipq6018-add-missing-clock-flags.patch deleted file mode 100644 index 02279a70f..000000000 --- a/target/linux/ipq60xx/patches-5.15/1003-clk-qcom-ipq6018-add-missing-clock-flags.patch +++ /dev/null @@ -1,147 +0,0 @@ -From a9179aeead3fe0737b47d11ef687edc2dc15c964 Mon Sep 17 00:00:00 2001 -From: Kathiravan T -Date: Fri, 6 Nov 2020 12:18:37 +0530 -Subject: [PATCH 1003/1011] clk: qcom: ipq6018: add missing clock flags - -The downstream QCA 5.4 kernel sets several extra clock flags. From -their reasoning: - -Add the CLK_IS_CRITICAL, CLK_RCG2_HW_CONTROLLED for the required clocks. - -Without the critical flag, below warning is seen when QDSS -components are enabled. - -[ 1.712722] ------------[ cut here ]------------ -[ 1.719039] gcc_qdss_dap_clk status stuck at 'on' -[ 1.719084] WARNING: CPU: 1 PID: 1 at drivers/clk/qcom/clk-branch.c:92 clk_branch_toggle+0x160/0x178 - -Signed-off-by: Kathiravan T -Signed-off-by: Alexandru Gagniuc ---- - drivers/clk/qcom/gcc-ipq6018.c | 19 +++++++++++++++---- - 1 file changed, 15 insertions(+), 4 deletions(-) - ---- a/drivers/clk/qcom/gcc-ipq6018.c -+++ b/drivers/clk/qcom/gcc-ipq6018.c -@@ -62,6 +62,7 @@ static struct clk_alpha_pll gpll0_main = - }, - .num_parents = 1, - .ops = &clk_alpha_pll_ops, -+ .flags = CLK_IS_CRITICAL, - }, - }, - }; -@@ -148,6 +149,7 @@ static struct clk_alpha_pll gpll6_main = - }, - .num_parents = 1, - .ops = &clk_alpha_pll_ops, -+ .flags = CLK_IS_CRITICAL, - }, - }, - }; -@@ -178,6 +180,7 @@ static struct clk_alpha_pll gpll4_main = - }, - .num_parents = 1, - .ops = &clk_alpha_pll_ops, -+ .flags = CLK_IS_CRITICAL, - }, - }, - }; -@@ -207,6 +210,7 @@ static struct clk_rcg2 pcnoc_bfdcd_clk_s - .freq_tbl = ftbl_pcnoc_bfdcd_clk_src, - .hid_width = 5, - .parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map, -+ .flags = CLK_RCG2_HW_CONTROLLED, - .clkr.hw.init = &(struct clk_init_data){ - .name = "pcnoc_bfdcd_clk_src", - .parent_data = gcc_xo_gpll0_gpll0_out_main_div2, -@@ -228,6 +232,7 @@ static struct clk_alpha_pll gpll2_main = - }, - .num_parents = 1, - .ops = &clk_alpha_pll_ops, -+ .flags = CLK_IS_CRITICAL, - }, - }, - }; -@@ -450,6 +455,7 @@ static struct clk_branch gcc_sleep_clk_s - }, - .num_parents = 1, - .ops = &clk_branch2_ops, -+ .flags = CLK_IS_CRITICAL, - }, - }, - }; -@@ -954,6 +960,7 @@ static struct clk_rcg2 nss_crypto_clk_sr - .mnd_width = 16, - .hid_width = 5, - .parent_map = gcc_xo_nss_crypto_pll_gpll0_map, -+ .flags = CLK_RCG2_HW_CONTROLLED, - .clkr.hw.init = &(struct clk_init_data){ - .name = "nss_crypto_clk_src", - .parent_data = gcc_xo_nss_crypto_pll_gpll0, -@@ -1125,6 +1132,7 @@ static struct clk_rcg2 nss_ubi0_clk_src - .freq_tbl = ftbl_nss_ubi_clk_src, - .hid_width = 5, - .parent_map = gcc_xo_ubi32_gpll0_gpll2_gpll4_gpll6_map, -+ .flags = CLK_RCG2_HW_CONTROLLED, - .clkr.hw.init = &(struct clk_init_data){ - .name = "nss_ubi0_clk_src", - .parent_data = gcc_xo_ubi32_pll_gpll0_gpll2_gpll4_gpll6, -@@ -1863,7 +1871,7 @@ static struct clk_branch gcc_apss_ahb_cl - .parent_hws = (const struct clk_hw *[]){ - &apss_ahb_postdiv_clk_src.clkr.hw }, - .num_parents = 1, -- .flags = CLK_SET_RATE_PARENT, -+ .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, - .ops = &clk_branch2_ops, - }, - }, -@@ -1885,11 +1893,13 @@ static struct clk_rcg2 system_noc_bfdcd_ - .freq_tbl = ftbl_system_noc_bfdcd_clk_src, - .hid_width = 5, - .parent_map = gcc_xo_gpll0_gpll6_gpll0_out_main_div2_map, -+ .flags = CLK_RCG2_HW_CONTROLLED, - .clkr.hw.init = &(struct clk_init_data){ - .name = "system_noc_bfdcd_clk_src", - .parent_data = gcc_xo_gpll0_gpll6_gpll0_out_main_div2, - .num_parents = 4, - .ops = &clk_rcg2_ops, -+ .flags = CLK_IS_CRITICAL, - }, - }; - -@@ -1939,7 +1949,7 @@ static struct clk_branch gcc_apss_axi_cl - .parent_hws = (const struct clk_hw *[]){ - &apss_axi_clk_src.clkr.hw }, - .num_parents = 1, -- .flags = CLK_SET_RATE_PARENT, -+ .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, - .ops = &clk_branch2_ops, - }, - }, -@@ -2308,7 +2318,7 @@ static struct clk_branch gcc_xo_clk = { - .parent_hws = (const struct clk_hw *[]){ - &gcc_xo_clk_src.clkr.hw }, - .num_parents = 1, -- .flags = CLK_SET_RATE_PARENT, -+ .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, - .ops = &clk_branch2_ops, - }, - }, -@@ -3157,6 +3167,7 @@ static struct clk_branch gcc_nssnoc_ppe_ - .name = "gcc_nssnoc_ppe_cfg_clk", - .parent_hws = (const struct clk_hw *[]){ - &nss_ppe_clk_src.clkr.hw }, -+ .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, - .ops = &clk_branch2_ops, - }, -@@ -3515,7 +3526,7 @@ static struct clk_branch gcc_qdss_dap_cl - .parent_hws = (const struct clk_hw *[]){ - &qdss_dap_sync_clk_src.hw }, - .num_parents = 1, -- .flags = CLK_SET_RATE_PARENT, -+ .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, - .ops = &clk_branch2_ops, - }, - }, diff --git a/target/linux/ipq60xx/patches-5.15/1005-clk-qcom-ipq6018-update-Huayra-PLL-settings.patch b/target/linux/ipq60xx/patches-5.15/1005-clk-qcom-ipq6018-update-Huayra-PLL-settings.patch deleted file mode 100644 index 036fd3e3f..000000000 --- a/target/linux/ipq60xx/patches-5.15/1005-clk-qcom-ipq6018-update-Huayra-PLL-settings.patch +++ /dev/null @@ -1,54 +0,0 @@ -From c027fd431bb2326d03d21a57e9f59f7ae414abbf Mon Sep 17 00:00:00 2001 -From: Praveenkumar I -Date: Tue, 12 Nov 2019 10:25:25 +0530 -Subject: [PATCH 1005/1011] clk: qcom: ipq6018: update Huayra PLL settings - -1. Updated APSS PLL and UBI PLL settings recommended by ATE. -2. Added TEST_CTL_VAL configuration for Huayra PLL - -Signed-off-by: Praveenkumar I -Signed-off-by: Alexandru Gagniuc ---- - drivers/clk/qcom/clk-alpha-pll.c | 6 ++++++ - drivers/clk/qcom/gcc-ipq6018.c | 9 ++++++--- - 2 files changed, 12 insertions(+), 3 deletions(-) - ---- a/drivers/clk/qcom/clk-alpha-pll.c -+++ b/drivers/clk/qcom/clk-alpha-pll.c -@@ -287,6 +287,12 @@ void clk_alpha_pll_configure(struct clk_ - - regmap_update_bits(regmap, PLL_USER_CTL(pll), mask, val); - -+ if (config->test_ctl_val != 0) -+ regmap_write(regmap, PLL_TEST_CTL(pll), config->test_ctl_val); -+ -+ if (config->test_ctl_hi_val != 0) -+ regmap_write(regmap, PLL_TEST_CTL_U(pll), config->test_ctl_hi_val); -+ - if (pll->flags & SUPPORTS_FSM_MODE) - qcom_pll_set_fsm_mode(regmap, PLL_MODE(pll), 6, 0); - } ---- a/drivers/clk/qcom/gcc-ipq6018.c -+++ b/drivers/clk/qcom/gcc-ipq6018.c -@@ -4705,15 +4705,18 @@ static struct clk_branch gcc_dcc_clk = { - - static const struct alpha_pll_config ubi32_pll_config = { - .l = 0x3e, -- .alpha = 0x57, -- .config_ctl_val = 0x240d6aa8, -- .config_ctl_hi_val = 0x3c2, -+ .alpha = 0x6667, -+ .config_ctl_val = 0x240d4828, -+ .config_ctl_hi_val = 0x6, - .main_output_mask = BIT(0), - .aux_output_mask = BIT(1), - .pre_div_val = 0x0, - .pre_div_mask = BIT(12), - .post_div_val = 0x0, - .post_div_mask = GENMASK(9, 8), -+ .alpha_en_mask = BIT(24), -+ .test_ctl_val = 0x1C0000C0, -+ .test_ctl_hi_val = 0x4000, - }; - - static const struct alpha_pll_config nss_crypto_pll_config = { diff --git a/target/linux/ipq60xx/patches-5.15/1007-arm64-dts-qcom-ipq6018-Add-missing-fixed-clocks.patch b/target/linux/ipq60xx/patches-5.15/1007-arm64-dts-qcom-ipq6018-Add-missing-fixed-clocks.patch deleted file mode 100644 index 35c18ae88..000000000 --- a/target/linux/ipq60xx/patches-5.15/1007-arm64-dts-qcom-ipq6018-Add-missing-fixed-clocks.patch +++ /dev/null @@ -1,48 +0,0 @@ -From b0da605ab258c02e0ab725a8014bfd961b36bed5 Mon Sep 17 00:00:00 2001 -From: Alexandru Gagniuc -Date: Sat, 27 Aug 2022 17:33:37 -0500 -Subject: [PATCH 1007/1011] arm64: dts: qcom: ipq6018: Add missing fixed-clocks - -Signed-off-by: Alexandru Gagniuc ---- - arch/arm64/boot/dts/qcom/ipq6018.dtsi | 22 ++++++++++++++++++++-- - 1 file changed, 20 insertions(+), 2 deletions(-) - ---- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi -@@ -27,6 +27,18 @@ - clock-frequency = <24000000>; - #clock-cells = <0>; - }; -+ -+ bias_pll_cc_clk: bias-pll-cc-clk { -+ compatible = "fixed-clock"; -+ clock-frequency = <300000000>; -+ #clock-cells = <0>; -+ }; -+ -+ bias_pll_nss_noc_clk: bias-pll-nss-noc-clk { -+ compatible = "fixed-clock"; -+ clock-frequency = <416500000>; -+ #clock-cells = <0>; -+ }; - }; - - cpus: cpus { -@@ -252,8 +264,14 @@ - gcc: gcc@1800000 { - compatible = "qcom,gcc-ipq6018"; - reg = <0x0 0x01800000 0x0 0x80000>; -- clocks = <&xo>, <&sleep_clk>; -- clock-names = "xo", "sleep_clk"; -+ clocks = <&xo>, -+ <&sleep_clk>, -+ <&bias_pll_cc_clk>, -+ <&bias_pll_nss_noc_clk>; -+ clock-names = "xo", -+ "sleep_clk", -+ "bias_pll_cc_clk", -+ "bias_pll_nss_noc_clk"; - #clock-cells = <1>; - #reset-cells = <1>; - }; diff --git a/target/linux/ipq60xx/patches-5.15/1010-Simplify-ipq6018-rproc-Add-non-secure-Q6-bringup-seq.patch b/target/linux/ipq60xx/patches-5.15/1010-Simplify-ipq6018-rproc-Add-non-secure-Q6-bringup-seq.patch deleted file mode 100644 index 044ab2d6f..000000000 --- a/target/linux/ipq60xx/patches-5.15/1010-Simplify-ipq6018-rproc-Add-non-secure-Q6-bringup-seq.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 0fcb001e301b7dec639f948de49f69666fe91669 Mon Sep 17 00:00:00 2001 -From: Alexandru Gagniuc -Date: Fri, 2 Sep 2022 18:31:11 -0500 -Subject: [PATCH 1010/1011] Simplify "ipq6018: rproc: Add non secure Q6 bringup - sequence" - ---- - drivers/remoteproc/qcom_q6v5_wcss.c | 25 +++++++++---------------- - 1 file changed, 9 insertions(+), 16 deletions(-) - ---- a/drivers/remoteproc/qcom_q6v5_wcss.c -+++ b/drivers/remoteproc/qcom_q6v5_wcss.c -@@ -629,18 +629,13 @@ static void q6v5_wcss_halt_axi_port(stru - unsigned long timeout; - unsigned int val; - int ret; -- const struct wcss_data *desc = device_get_match_data(wcss->dev); - -- if (desc != &wcss_ipq6018_res_init) { -- /* Check if we're already idle */ -- ret = regmap_read(halt_map, offset + AXI_IDLE_REG, &val); -- if (!ret && val) -- return; -- } -+ /* Check if we're already idle */ -+ ret = regmap_read(halt_map, offset + AXI_IDLE_REG, &val); -+ if (!ret && val) -+ return; - - /* Assert halt request */ -- regmap_read(halt_map, offset + AXI_HALTREQ_REG, &val); -- val |= BIT(0); - regmap_write(halt_map, offset + AXI_HALTREQ_REG, 1); - - /* Wait for halt */ -@@ -653,14 +648,12 @@ static void q6v5_wcss_halt_axi_port(stru - msleep(1); - } - -- if (desc != &wcss_ipq6018_res_init) { -- ret = regmap_read(halt_map, offset + AXI_IDLE_REG, &val); -- if (ret || !val) -- dev_err(wcss->dev, "port failed halt\n"); -+ ret = regmap_read(halt_map, offset + AXI_IDLE_REG, &val); -+ if (ret || !val) -+ dev_err(wcss->dev, "port failed halt\n"); - -- /* Clear halt request (port will remain halted until reset) */ -- regmap_write(halt_map, offset + AXI_HALTREQ_REG, 0); -- } -+ /* Clear halt request (port will remain halted until reset) */ -+ regmap_write(halt_map, offset + AXI_HALTREQ_REG, 0); - } - - static int q6v5_qcs404_wcss_shutdown(struct q6v5_wcss *wcss) diff --git a/target/linux/qualcommax/Makefile b/target/linux/qualcommax/Makefile index 825cb7578..87f919085 100644 --- a/target/linux/qualcommax/Makefile +++ b/target/linux/qualcommax/Makefile @@ -6,7 +6,7 @@ BOARDNAME:=Qualcomm Atheros 802.11ax WiSoC-s FEATURES:=squashfs ramdisk fpu nand rtc emmc KERNELNAME:=Image dtbs CPU_TYPE:=cortex-a53 -SUBTARGETS:=ipq807x +SUBTARGETS:=ipq60xx ipq807x KERNEL_PATCHVER:=6.1 diff --git a/target/linux/qualcommax/config-6.1 b/target/linux/qualcommax/config-6.1 index 74010c7ff..84af2d7ca 100644 --- a/target/linux/qualcommax/config-6.1 +++ b/target/linux/qualcommax/config-6.1 @@ -351,6 +351,7 @@ CONFIG_POWER_SUPPLY=y CONFIG_PREEMPT_NONE_BUILD=y CONFIG_PRINTK_TIME=y CONFIG_PTP_1588_CLOCK_OPTIONAL=y +# CONFIG_PWM_IPQ is not set # CONFIG_QCM_DISPCC_2290 is not set # CONFIG_QCM_GCC_2290 is not set # CONFIG_QCOM_A53PLL is not set diff --git a/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq6000-360v6.dts b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq6000-360v6.dts new file mode 100644 index 000000000..74d54f094 --- /dev/null +++ b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq6000-360v6.dts @@ -0,0 +1,207 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +/dts-v1/; + +#include "ipq6018-512m.dtsi" +#include "ipq6018-ess.dtsi" +#include "ipq6018-opp.dtsi" + +#include +#include + +/ { + model = "Qihoo 360V6"; + compatible = "qihoo,360v6", "qcom,ipq6018"; + + aliases { + serial0 = &blsp1_uart3; + led-boot = &led_green; + led-failsafe = &led_red; + led-running = &led_green; + led-upgrade = &led_orange; + }; + + chosen { + stdout-path = "serial0:115200n8"; + bootargs-append = " root=/dev/ubiblock0_1"; + }; + + keys { + compatible = "gpio-keys"; + + wps { + label = "wps"; + linux,code = ; + gpios = <&tlmm 19 GPIO_ACTIVE_LOW>; + }; + + reset { + label = "reset"; + linux,code = ; + gpios = <&tlmm 68 GPIO_ACTIVE_LOW>; + }; + }; + + leds { + compatible = "gpio-leds"; + + led_red: status_red { + label = "red:status"; + gpio = <&tlmm 71 GPIO_ACTIVE_HIGH>; + }; + + led_orange: status_orange { + label = "orange:status"; + gpio = <&tlmm 72 GPIO_ACTIVE_HIGH>; + }; + + led_green: status_green { + label = "green:status"; + gpio = <&tlmm 73 GPIO_ACTIVE_HIGH>; + }; + }; +}; + +&tlmm { + mdio_pins: mdio-pins { + mdc { + pins = "gpio64"; + function = "mdc"; + drive-strength = <8>; + bias-pull-up; + }; + + mdio { + pins = "gpio65"; + function = "mdio"; + drive-strength = <8>; + bias-pull-up; + }; + }; +}; + +&blsp1_uart3 { + pinctrl-0 = <&serial_3_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&qpic_nand { + status = "okay"; + + nand@0 { + reg = <0>; + nand-ecc-strength = <4>; + nand-ecc-step-size = <512>; + nand-bus-width = <8>; + + partitions { + compatible = "qcom,smem-part"; + }; + }; +}; + +&qusb_phy_0 { + status = "okay"; +}; + +&ssphy_0 { + status = "okay"; +}; + +&usb3 { + status = "okay"; +}; + +&mdio { + status = "okay"; + + pinctrl-0 = <&mdio_pins>; + pinctrl-names = "default"; + reset-gpios = <&tlmm 75 GPIO_ACTIVE_LOW>; + + qca8075_0: ethernet-phy@0 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <0>; + }; + + qca8075_1: ethernet-phy@1 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <1>; + }; + + qca8075_2: ethernet-phy@2 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <2>; + }; + + qca8075_3: ethernet-phy@3 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <3>; + }; +}; + +&switch { + status = "okay"; + + switch_cpu_bmp = <0x1>; /* cpu port bitmap */ + switch_lan_bmp = <0xe>; /* lan port bitmap */ + switch_wan_bmp = <0x10>; /* wan port bitmap */ + switch_inner_bmp = <0xc0>; /*inner port bitmap*/ + switch_mac_mode = <0x0>; /* mac mode for uniphy 0*/ + switch_mac_mode1 = <0xff>; /* mac mode for uniphy 1*/ + switch_mac_mode2 = <0xff>; /* mac mode for uniphy 2*/ + + qcom,port_phyinfo { + port@0 { + port_id = <1>; + phy_address = <0>; + }; + port@1 { + port_id = <2>; + phy_address = <1>; + }; + port@2 { + port_id = <3>; + phy_address = <2>; + }; + port@3 { + port_id = <4>; + phy_address = <3>; + }; + }; +}; + +&edma { + status = "okay"; +}; + +&dp1 { + status = "okay"; + phy-handle = <&qca8075_0>; + label = "wan"; +}; + +&dp2 { + status = "okay"; + phy-handle = <&qca8075_1>; + label = "lan1"; +}; + +&dp3 { + status = "okay"; + phy-handle = <&qca8075_2>; + label = "lan2"; +}; + +&dp4 { + status = "okay"; + phy-handle = <&qca8075_3>; + label = "lan3"; +}; + +&wifi { + status = "okay"; + + qcom,ath11k-fw-memory-mode = <1>; +}; diff --git a/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq6000-mr7350.dts b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq6000-mr7350.dts new file mode 100644 index 000000000..6767d775a --- /dev/null +++ b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq6000-mr7350.dts @@ -0,0 +1,298 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +/dts-v1/; + +#include "ipq6018-512m.dtsi" +#include "ipq6018-ess.dtsi" +#include "ipq6018-opp.dtsi" + +#include +#include + +/ { + model = "Linksys MR7350"; + compatible = "linksys,mr7350", "qcom,ipq6018"; + + aliases { + serial0 = &blsp1_uart3; + serial1 = &blsp1_uart2; + led-boot = &led_system_blue; + led-failsafe = &led_system_red; + led-running = &led_system_blue; + led-upgrade = &led_system_blue; + }; + + chosen { + stdout-path = "serial0:115200n8"; + bootargs-append = " root=/dev/ubiblock0_0"; + }; + + keys { + compatible = "gpio-keys"; + + wps { + label = "wps"; + linux,code = ; + gpios = <&tlmm 56 GPIO_ACTIVE_LOW>; + }; + + reset { + label = "reset"; + linux,code = ; + gpios = <&tlmm 57 GPIO_ACTIVE_LOW>; + }; + }; + + leds { + compatible = "gpio-leds"; + + usb { + label = "blue:usb"; + gpios = <&tlmm 60 GPIO_ACTIVE_HIGH>; + trigger-sources = <&usb3_port1>, <&usb3_port2>; + linux,default-trigger = "usbport"; + }; + }; + + reg_usb_vbus: regulator-usb-vbus { + compatible = "regulator-fixed"; + regulator-name = "usb_vbus"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + gpio = <&tlmm 61 GPIO_ACTIVE_LOW>; + regulator-always-on; + }; +}; + +&tlmm { + hsuart_pins: hsuart-pins { + mux { + pins = "gpio69", "gpio70", + "gpio71", "gpio72"; + function = "blsp1_uart"; + drive-strength = <8>; + bias-disable; + }; + }; + + i2c_pins: i2c-pins { + mux { + pins = "gpio42", "gpio43"; + function = "blsp2_i2c"; + drive-strength = <8>; + bias-pull-down; + }; + }; + + mdio_pins: mdio-pins { + mdc { + pins = "gpio64"; + function = "mdc"; + drive-strength = <8>; + bias-pull-up; + }; + + mdio { + pins = "gpio65"; + function = "mdio"; + drive-strength = <8>; + bias-pull-up; + }; + }; +}; + +&blsp1_i2c3 { + pinctrl-0 = <&i2c_pins>; + pinctrl-names = "default"; + status = "okay"; + + led-controller@62 { + compatible = "nxp,pca9633"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x62>; + + led_system_red: led@0 { + label = "red:system"; + reg = <0>; + }; + + led_system_green: led@1 { + label = "green:system"; + reg = <1>; + }; + + led_system_blue: led@2 { + label = "blue:system"; + reg = <2>; + default-state = "on"; + }; + }; +}; + +&blsp1_uart2 { + pinctrl-0 = <&hsuart_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&blsp1_uart3 { + pinctrl-0 = <&serial_3_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&dwc_0 { + #address-cells = <1>; + #size-cells = <0>; + + usb3_port1: port@1 { + reg = <1>; + #trigger-source-cells = <0>; + }; + + usb3_port2: port@2 { + reg = <2>; + #trigger-source-cells = <0>; + }; +}; + +&qpic_bam { + status = "okay"; +}; + +&qpic_nand { + status = "okay"; + + nand@0 { + reg = <0>; + nand-ecc-strength = <4>; + nand-ecc-step-size = <512>; + nand-bus-width = <8>; + + partitions { + compatible = "qcom,smem-part"; + }; + }; +}; + +&qusb_phy_0 { + status = "okay"; +}; + +&ssphy_0 { + status = "okay"; +}; + +&usb3 { + vbus-supply = <®_usb_vbus>; + status = "okay"; +}; + +&mdio { + status = "okay"; + + pinctrl-0 = <&mdio_pins>; + pinctrl-names = "default"; + reset-gpios = <&tlmm 75 GPIO_ACTIVE_LOW>; + + qca8075_0: ethernet-phy@0 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <0>; + }; + + qca8075_1: ethernet-phy@1 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <1>; + }; + + qca8075_2: ethernet-phy@2 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <2>; + }; + + qca8075_3: ethernet-phy@3 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <3>; + }; + + qca8075_4: ethernet-phy@4 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <4>; + }; +}; + +&switch { + status = "okay"; + + switch_cpu_bmp = <0x1>; /* cpu port bitmap */ + switch_lan_bmp = <0x1e>; /* lan port bitmap */ + switch_wan_bmp = <0x20>; /* wan port bitmap */ + switch_inner_bmp = <0xc0>; /*inner port bitmap*/ + switch_mac_mode = <0x0>; /* mac mode for uniphy 0*/ + switch_mac_mode1 = <0xff>; /* mac mode for uniphy 1*/ + switch_mac_mode2 = <0xff>; /* mac mode for uniphy 2*/ + + qcom,port_phyinfo { + port@0 { + port_id = <1>; + phy_address = <0>; + }; + port@1 { + port_id = <2>; + phy_address = <1>; + }; + port@2 { + port_id = <3>; + phy_address = <2>; + }; + port@3 { + port_id = <4>; + phy_address = <3>; + }; + port@4 { + port_id = <5>; + phy_address = <4>; + }; + }; +}; + +&edma { + status = "okay"; +}; + +&dp1 { + status = "okay"; + phy-handle = <&qca8075_0>; + label = "lan1"; +}; + +&dp2 { + status = "okay"; + phy-handle = <&qca8075_1>; + label = "lan2"; +}; + +&dp3 { + status = "okay"; + phy-handle = <&qca8075_2>; + label = "lan3"; +}; + +&dp4 { + status = "okay"; + phy-handle = <&qca8075_3>; + label = "lan4"; +}; + +&dp5 { + status = "okay"; + phy-handle = <&qca8075_4>; + label = "wan"; +}; + +&wifi { + status = "okay"; + + qcom,ath11k-fw-memory-mode = <1>; +}; diff --git a/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq6000-rm1800.dts b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq6000-rm1800.dts new file mode 100644 index 000000000..c1d6cbf60 --- /dev/null +++ b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq6000-rm1800.dts @@ -0,0 +1,208 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +/dts-v1/; + +#include "ipq6018-512m.dtsi" +#include "ipq6018-ess.dtsi" +#include "ipq6018-opp.dtsi" + +#include +#include + +/ { + model = "Xiaomi RM1800"; + compatible = "xiaomi,rm1800", "qcom,ipq6018"; + + aliases { + serial0 = &blsp1_uart3; + led-boot = &led_yellow; + led-failsafe = &led_yellow; + led-running = &led_blue; + led-upgrade = &led_yellow; + label-mac-device = &dp2; + + ethernet1 = &dp2; + ethernet2 = &dp3; + ethernet3 = &dp4; + ethernet4 = &dp5; + }; + + chosen { + stdout-path = "serial0:115200n8"; + bootargs-append = " root=/dev/ubiblock0_1"; + }; + + keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + linux,code = ; + gpios = <&tlmm 19 GPIO_ACTIVE_LOW>; + }; + }; + + leds { + compatible = "gpio-leds"; + + led_blue: system-blue { + label = "blue:system"; + gpios = <&tlmm 29 GPIO_ACTIVE_HIGH>; + }; + + led_yellow: system-yellow { + label = "yellow:system"; + gpios = <&tlmm 30 GPIO_ACTIVE_HIGH>; + }; + + network-blue { + label = "blue:network"; + gpios = <&tlmm 31 GPIO_ACTIVE_HIGH>; + }; + + network-yellow { + label = "yellow:network"; + gpios = <&tlmm 32 GPIO_ACTIVE_HIGH>; + }; + }; +}; + +&tlmm { + mdio_pins: mdio-pins { + mdc { + pins = "gpio64"; + function = "mdc"; + drive-strength = <8>; + bias-pull-up; + }; + + mdio { + pins = "gpio65"; + function = "mdio"; + drive-strength = <8>; + bias-pull-up; + }; + }; +}; + +&blsp1_uart3 { + pinctrl-0 = <&serial_3_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&qpic_bam { + status = "okay"; +}; + +&qpic_nand { + status = "okay"; + + nand@0 { + reg = <0>; + nand-ecc-strength = <4>; + nand-ecc-step-size = <512>; + nand-bus-width = <8>; + + partitions { + compatible = "qcom,smem-part"; + }; + }; +}; + +&mdio { + status = "okay"; + + pinctrl-0 = <&mdio_pins>; + pinctrl-names = "default"; + reset-gpios = <&tlmm 75 GPIO_ACTIVE_LOW>; + + qca8075_1: ethernet-phy@1 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <1>; + }; + + qca8075_2: ethernet-phy@2 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <2>; + }; + + qca8075_3: ethernet-phy@3 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <3>; + }; + + qca8075_4: ethernet-phy@4 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <4>; + }; +}; + +&switch { + status = "okay"; + + switch_cpu_bmp = <0x1>; /* cpu port bitmap */ + switch_lan_bmp = <0x1e>; /* lan port bitmap */ + switch_wan_bmp = <0x20>; /* wan port bitmap */ + switch_inner_bmp = <0xc0>; /*inner port bitmap*/ + switch_mac_mode = <0x0>; /* mac mode for uniphy 0*/ + switch_mac_mode1 = <0xff>; /* mac mode for uniphy 1*/ + switch_mac_mode2 = <0xff>; /* mac mode for uniphy 2*/ + + qcom,port_phyinfo { + port@0 { + port_id = <1>; + phy_address = <0>; + }; + port@1 { + port_id = <2>; + phy_address = <1>; + }; + port@2 { + port_id = <3>; + phy_address = <2>; + }; + port@3 { + port_id = <4>; + phy_address = <3>; + }; + port@4 { + port_id = <5>; + phy_address = <4>; + }; + }; +}; + +&edma { + status = "okay"; +}; + +&dp2 { + status = "okay"; + phy-handle = <&qca8075_1>; + label = "lan1"; +}; + +&dp3 { + status = "okay"; + phy-handle = <&qca8075_2>; + label = "lan2"; +}; + +&dp4 { + status = "okay"; + phy-handle = <&qca8075_3>; + label = "lan3"; +}; + +&dp5 { + status = "okay"; + phy-handle = <&qca8075_4>; + label = "wan"; +}; + +&wifi { + status = "okay"; + + qcom,ath11k-fw-memory-mode = <1>; +}; diff --git a/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq6018-256m.dtsi b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq6018-256m.dtsi new file mode 100644 index 000000000..d8e7c7634 --- /dev/null +++ b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq6018-256m.dtsi @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include "ipq6018.dtsi" + +&q6_region { + reg = <0x0 0x4ab00000 0x0 0x2800000>; +}; + +&q6_etr_region { + reg = <0x0 0x4d300000 0x0 0x100000>; +}; + +&m3_dump_region { + reg = <0x0 0x4d400000 0x0 0x100000>; +}; diff --git a/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq6018-512m.dtsi b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq6018-512m.dtsi new file mode 100644 index 000000000..6298123c2 --- /dev/null +++ b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq6018-512m.dtsi @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include "ipq6018.dtsi" + +&q6_region { + reg = <0x0 0x4ab00000 0x0 0x3700000>; +}; + +&q6_etr_region { + reg = <0x0 0x4e200000 0x0 0x100000>; +}; + +&m3_dump_region { + reg = <0x0 0x4e300000 0x0 0x100000>; +}; diff --git a/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq6018-ess.dtsi b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq6018-ess.dtsi new file mode 100644 index 000000000..55912f81e --- /dev/null +++ b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq6018-ess.dtsi @@ -0,0 +1,495 @@ +// SPDX-License-Identifier: GPL-2.0-only + +&clocks { + bias_pll_cc_clk { + compatible = "fixed-clock"; + clock-frequency = <300000000>; + #clock-cells = <0>; + }; + + bias_pll_nss_noc_clk { + compatible = "fixed-clock"; + clock-frequency = <416500000>; + #clock-cells = <0>; + }; +}; + +&soc { + switch: ess-switch@3a000000 { + compatible = "qcom,ess-switch-ipq60xx"; + reg = <0x3a000000 0x1000000>; + switch_access_mode = "local bus"; + switch_cpu_bmp = <0x1>; /* cpu port bitmap */ + switch_inner_bmp = <0xc0>; /*inner port bitmap*/ + bm_tick_mode = <0>; /* bm tick mode */ + tm_tick_mode = <0>; /* tm tick mode */ + clocks = <&gcc GCC_CMN_12GPLL_AHB_CLK>, + <&gcc GCC_CMN_12GPLL_SYS_CLK>, + <&gcc GCC_UNIPHY0_AHB_CLK>, + <&gcc GCC_UNIPHY0_SYS_CLK>, + <&gcc GCC_UNIPHY1_AHB_CLK>, + <&gcc GCC_UNIPHY1_SYS_CLK>, + <&gcc GCC_PORT1_MAC_CLK>, + <&gcc GCC_PORT2_MAC_CLK>, + <&gcc GCC_PORT3_MAC_CLK>, + <&gcc GCC_PORT4_MAC_CLK>, + <&gcc GCC_PORT5_MAC_CLK>, + <&gcc GCC_NSS_PPE_CLK>, + <&gcc GCC_NSS_PPE_CFG_CLK>, + <&gcc GCC_NSSNOC_PPE_CLK>, + <&gcc GCC_NSSNOC_PPE_CFG_CLK>, + <&gcc GCC_NSS_EDMA_CLK>, + <&gcc GCC_NSS_EDMA_CFG_CLK>, + <&gcc GCC_NSS_PPE_IPE_CLK>, + <&gcc GCC_MDIO_AHB_CLK>, + <&gcc GCC_NSS_NOC_CLK>, + <&gcc GCC_NSSNOC_SNOC_CLK>, + <&gcc GCC_NSS_CRYPTO_CLK>, + <&gcc GCC_NSS_PTP_REF_CLK>, + <&gcc GCC_NSS_PORT1_RX_CLK>, + <&gcc GCC_NSS_PORT1_TX_CLK>, + <&gcc GCC_NSS_PORT2_RX_CLK>, + <&gcc GCC_NSS_PORT2_TX_CLK>, + <&gcc GCC_NSS_PORT3_RX_CLK>, + <&gcc GCC_NSS_PORT3_TX_CLK>, + <&gcc GCC_NSS_PORT4_RX_CLK>, + <&gcc GCC_NSS_PORT4_TX_CLK>, + <&gcc GCC_NSS_PORT5_RX_CLK>, + <&gcc GCC_NSS_PORT5_TX_CLK>, + <&gcc GCC_UNIPHY0_PORT1_RX_CLK>, + <&gcc GCC_UNIPHY0_PORT1_TX_CLK>, + <&gcc GCC_UNIPHY0_PORT2_RX_CLK>, + <&gcc GCC_UNIPHY0_PORT2_TX_CLK>, + <&gcc GCC_UNIPHY0_PORT3_RX_CLK>, + <&gcc GCC_UNIPHY0_PORT3_TX_CLK>, + <&gcc GCC_UNIPHY0_PORT4_RX_CLK>, + <&gcc GCC_UNIPHY0_PORT4_TX_CLK>, + <&gcc GCC_UNIPHY0_PORT5_RX_CLK>, + <&gcc GCC_UNIPHY0_PORT5_TX_CLK>, + <&gcc GCC_UNIPHY1_PORT5_RX_CLK>, + <&gcc GCC_UNIPHY1_PORT5_TX_CLK>, + <&gcc NSS_PORT5_RX_CLK_SRC>, + <&gcc NSS_PORT5_TX_CLK_SRC>, + <&gcc GCC_SNOC_NSSNOC_CLK>; + clock-names = "cmn_ahb_clk", "cmn_sys_clk", + "uniphy0_ahb_clk", "uniphy0_sys_clk", + "uniphy1_ahb_clk", "uniphy1_sys_clk", + "port1_mac_clk", "port2_mac_clk", + "port3_mac_clk", "port4_mac_clk", + "port5_mac_clk", + "nss_ppe_clk", "nss_ppe_cfg_clk", + "nssnoc_ppe_clk", "nssnoc_ppe_cfg_clk", + "nss_edma_clk", "nss_edma_cfg_clk", + "nss_ppe_ipe_clk", + "gcc_mdio_ahb_clk", "gcc_nss_noc_clk", + "gcc_nssnoc_snoc_clk", + "gcc_nss_crypto_clk", + "gcc_nss_ptp_ref_clk", + "nss_port1_rx_clk", "nss_port1_tx_clk", + "nss_port2_rx_clk", "nss_port2_tx_clk", + "nss_port3_rx_clk", "nss_port3_tx_clk", + "nss_port4_rx_clk", "nss_port4_tx_clk", + "nss_port5_rx_clk", "nss_port5_tx_clk", + "uniphy0_port1_rx_clk", + "uniphy0_port1_tx_clk", + "uniphy0_port2_rx_clk", + "uniphy0_port2_tx_clk", + "uniphy0_port3_rx_clk", + "uniphy0_port3_tx_clk", + "uniphy0_port4_rx_clk", + "uniphy0_port4_tx_clk", + "uniphy0_port5_rx_clk", + "uniphy0_port5_tx_clk", + "uniphy1_port5_rx_clk", + "uniphy1_port5_tx_clk", + "nss_port5_rx_clk_src", + "nss_port5_tx_clk_src", + "gcc_snoc_nssnoc_clk"; + resets = <&gcc GCC_PPE_FULL_RESET>, + <&gcc GCC_UNIPHY0_SOFT_RESET>, + <&gcc GCC_UNIPHY0_XPCS_RESET>, + <&gcc GCC_UNIPHY1_SOFT_RESET>, + <&gcc GCC_UNIPHY1_XPCS_RESET>, + <&gcc GCC_NSSPORT1_RESET>, + <&gcc GCC_NSSPORT2_RESET>, + <&gcc GCC_NSSPORT3_RESET>, + <&gcc GCC_NSSPORT4_RESET>, + <&gcc GCC_NSSPORT5_RESET>, + <&gcc GCC_UNIPHY0_PORT1_ARES>, + <&gcc GCC_UNIPHY0_PORT2_ARES>, + <&gcc GCC_UNIPHY0_PORT3_ARES>, + <&gcc GCC_UNIPHY0_PORT4_ARES>, + <&gcc GCC_UNIPHY0_PORT5_ARES>, + <&gcc GCC_UNIPHY0_PORT_4_5_RESET>, + <&gcc GCC_UNIPHY0_PORT_4_RESET>; + reset-names = "ppe_rst", "uniphy0_soft_rst", + "uniphy0_xpcs_rst", "uniphy1_soft_rst", + "uniphy1_xpcs_rst", "nss_port1_rst", + "nss_port2_rst", "nss_port3_rst", + "nss_port4_rst", "nss_port5_rst", + "uniphy0_port1_dis", + "uniphy0_port2_dis", + "uniphy0_port3_dis", + "uniphy0_port4_dis", + "uniphy0_port5_dis", + "uniphy0_port_4_5_rst", + "uniphy0_port_4_rst"; + mdio-bus = <&mdio>; + status = "disabled"; + + port_scheduler_resource { + port@0 { + port_id = <0>; + ucast_queue = <0 143>; + mcast_queue = <256 271>; + l0sp = <0 35>; + l0cdrr = <0 47>; + l0edrr = <0 47>; + l1cdrr = <0 7>; + l1edrr = <0 7>; + }; + port@1 { + port_id = <1>; + ucast_queue = <144 159>; + mcast_queue = <272 275>; + l0sp = <36 39>; + l0cdrr = <48 63>; + l0edrr = <48 63>; + l1cdrr = <8 11>; + l1edrr = <8 11>; + }; + port@2 { + port_id = <2>; + ucast_queue = <160 175>; + mcast_queue = <276 279>; + l0sp = <40 43>; + l0cdrr = <64 79>; + l0edrr = <64 79>; + l1cdrr = <12 15>; + l1edrr = <12 15>; + }; + port@3 { + port_id = <3>; + ucast_queue = <176 191>; + mcast_queue = <280 283>; + l0sp = <44 47>; + l0cdrr = <80 95>; + l0edrr = <80 95>; + l1cdrr = <16 19>; + l1edrr = <16 19>; + }; + port@4 { + port_id = <4>; + ucast_queue = <192 207>; + mcast_queue = <284 287>; + l0sp = <48 51>; + l0cdrr = <96 111>; + l0edrr = <96 111>; + l1cdrr = <20 23>; + l1edrr = <20 23>; + }; + port@5 { + port_id = <5>; + ucast_queue = <208 223>; + mcast_queue = <288 291>; + l0sp = <52 55>; + l0cdrr = <112 127>; + l0edrr = <112 127>; + l1cdrr = <24 27>; + l1edrr = <24 27>; + }; + port@6 { + port_id = <6>; + ucast_queue = <224 239>; + mcast_queue = <292 295>; + l0sp = <56 59>; + l0cdrr = <128 143>; + l0edrr = <128 143>; + l1cdrr = <28 31>; + l1edrr = <28 31>; + }; + port@7 { + port_id = <7>; + ucast_queue = <240 255>; + mcast_queue = <296 299>; + l0sp = <60 63>; + l0cdrr = <144 159>; + l0edrr = <144 159>; + l1cdrr = <32 35>; + l1edrr = <32 35>; + }; + }; + port_scheduler_config { + port@0 { + port_id = <0>; + l1scheduler { + group@0 { + sp = <0 1>; /*L0 SPs*/ + /*cpri cdrr epri edrr*/ + cfg = <0 0 0 0>; + }; + }; + l0scheduler { + group@0 { + /*unicast queues*/ + ucast_queue = <0 4 8>; + /*multicast queues*/ + mcast_queue = <256 260>; + /*sp cpri cdrr epri edrr*/ + cfg = <0 0 0 0 0>; + }; + group@1 { + ucast_queue = <1 5 9>; + mcast_queue = <257 261>; + cfg = <0 1 1 1 1>; + }; + group@2 { + ucast_queue = <2 6 10>; + mcast_queue = <258 262>; + cfg = <0 2 2 2 2>; + }; + group@3 { + ucast_queue = <3 7 11>; + mcast_queue = <259 263>; + cfg = <0 3 3 3 3>; + }; + }; + }; + port@1 { + port_id = <1>; + l1scheduler { + group@0 { + sp = <36>; + cfg = <0 8 0 8>; + }; + group@1 { + sp = <37>; + cfg = <1 9 1 9>; + }; + }; + l0scheduler { + group@0 { + ucast_queue = <144>; + ucast_loop_pri = <16>; + mcast_queue = <272>; + mcast_loop_pri = <4>; + cfg = <36 0 48 0 48>; + }; + }; + }; + port@2 { + port_id = <2>; + l1scheduler { + group@0 { + sp = <40>; + cfg = <0 12 0 12>; + }; + group@1 { + sp = <41>; + cfg = <1 13 1 13>; + }; + }; + l0scheduler { + group@0 { + ucast_queue = <160>; + ucast_loop_pri = <16>; + mcast_queue = <276>; + mcast_loop_pri = <4>; + cfg = <40 0 64 0 64>; + }; + }; + }; + port@3 { + port_id = <3>; + l1scheduler { + group@0 { + sp = <44>; + cfg = <0 16 0 16>; + }; + group@1 { + sp = <45>; + cfg = <1 17 1 17>; + }; + }; + l0scheduler { + group@0 { + ucast_queue = <176>; + ucast_loop_pri = <16>; + mcast_queue = <280>; + mcast_loop_pri = <4>; + cfg = <44 0 80 0 80>; + }; + }; + }; + port@4 { + port_id = <4>; + l1scheduler { + group@0 { + sp = <48>; + cfg = <0 20 0 20>; + }; + group@1 { + sp = <49>; + cfg = <1 21 1 21>; + }; + }; + l0scheduler { + group@0 { + ucast_queue = <192>; + ucast_loop_pri = <16>; + mcast_queue = <284>; + mcast_loop_pri = <4>; + cfg = <48 0 96 0 96>; + }; + }; + }; + port@5 { + port_id = <5>; + l1scheduler { + group@0 { + sp = <52>; + cfg = <0 24 0 24>; + }; + group@1 { + sp = <53>; + cfg = <1 25 1 25>; + }; + }; + l0scheduler { + group@0 { + ucast_queue = <208>; + ucast_loop_pri = <16>; + mcast_queue = <288>; + mcast_loop_pri = <4>; + cfg = <52 0 112 0 112>; + }; + }; + }; + port@6 { + port_id = <6>; + l1scheduler { + group@0 { + sp = <56>; + cfg = <0 28 0 28>; + }; + group@1 { + sp = <57>; + cfg = <1 29 1 29>; + }; + }; + l0scheduler { + group@0 { + ucast_queue = <224>; + ucast_loop_pri = <16>; + mcast_queue = <292>; + mcast_loop_pri = <4>; + cfg = <56 0 128 0 128>; + }; + }; + }; + port@7 { + port_id = <7>; + l1scheduler { + group@0 { + sp = <60>; + cfg = <0 32 0 32>; + }; + group@1 { + sp = <61>; + cfg = <1 33 1 33>; + }; + }; + l0scheduler { + group@0 { + ucast_queue = <240>; + ucast_loop_pri = <16>; + mcast_queue = <296>; + cfg = <60 0 144 0 144>; + }; + }; + }; + }; + }; + + ess-uniphy@7a00000 { + compatible = "qcom,ess-uniphy"; + reg = <0x7a00000 0x30000>; + uniphy_access_mode = "local bus"; + }; + + edma: edma@3ab00000 { + compatible = "qcom,edma"; + reg = <0x0 0x3ab00000 0x0 0xabe00>; + reg-names = "edma-reg-base"; + qcom,txdesc-ring-start = <23>; + qcom,txdesc-rings = <1>; + qcom,txcmpl-ring-start = <23>; + qcom,txcmpl-rings = <1>; + qcom,rxfill-ring-start = <7>; + qcom,rxfill-rings = <1>; + qcom,rxdesc-ring-start = <15>; + qcom,rxdesc-rings = <1>; + interrupts = , + , + , + ; + resets = <&gcc GCC_EDMA_HW_RESET>; + reset-names = "edma_rst"; + status = "disabled"; + }; + + dp1: dp1 { + device_type = "network"; + compatible = "qcom,nss-dp"; + qcom,id = <1>; + reg = <0x0 0x3a001000 0x0 0x200>; + qcom,mactype = <0>; + local-mac-address = [000000000000]; + phy-mode = "sgmii"; + status = "disabled"; + }; + + dp2: dp2 { + device_type = "network"; + compatible = "qcom,nss-dp"; + qcom,id = <2>; + reg = <0x0 0x3a001200 0x0 0x200>; + qcom,mactype = <0>; + local-mac-address = [000000000000]; + phy-mode = "sgmii"; + status = "disabled"; + }; + + dp3: dp3 { + device_type = "network"; + compatible = "qcom,nss-dp"; + qcom,id = <3>; + reg = <0x0 0x3a001400 0x0 0x200>; + qcom,mactype = <0>; + local-mac-address = [000000000000]; + phy-mode = "sgmii"; + status = "disabled"; + }; + + dp4: dp4 { + device_type = "network"; + compatible = "qcom,nss-dp"; + qcom,id = <4>; + reg = <0x0 0x3a001600 0x0 0x200>; + qcom,mactype = <0>; + local-mac-address = [000000000000]; + phy-mode = "sgmii"; + status = "disabled"; + }; + + dp5: dp5 { + device_type = "network"; + compatible = "qcom,nss-dp"; + qcom,id = <5>; + reg = <0x0 0x3a001800 0x0 0x200>; + qcom,mactype = <0>; + local-mac-address = [000000000000]; + phy-mode = "sgmii"; + status = "disabled"; + }; +}; diff --git a/target/linux/qualcommax/image/ipq60xx.mk b/target/linux/qualcommax/image/ipq60xx.mk new file mode 100644 index 000000000..a1ab215ce --- /dev/null +++ b/target/linux/qualcommax/image/ipq60xx.mk @@ -0,0 +1,48 @@ +define Device/FitImage + KERNEL_SUFFIX := -uImage.itb + KERNEL = kernel-bin | libdeflate-gzip | fit gzip $$(KDIR)/image-$$(DEVICE_DTS).dtb + KERNEL_NAME := Image +endef + +define Device/FitImageLzma + KERNEL_SUFFIX := -uImage.itb + KERNEL = kernel-bin | lzma | fit lzma $$(KDIR)/image-$$(DEVICE_DTS).dtb + KERNEL_NAME := Image +endef + +define Device/UbiFit + KERNEL_IN_UBI := 1 + IMAGES := factory.ubi sysupgrade.bin + IMAGE/factory.ubi := append-ubi + IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata +endef + +define Device/linksys_mr7350 + $(call Device/FitImage) + DEVICE_VENDOR := Linksys + DEVICE_MODEL := MR7350 + SOC := ipq6000 + KERNEL_SIZE := 8192k + BLOCKSIZE := 128k + PAGESIZE := 2048 + UBINIZE_OPTS := -E 5 + IMAGES += factory.bin + IMAGE/factory.bin := append-kernel | pad-to $$$$(KERNEL_SIZE) | \ + append-ubi | linksys-image type=MR7350 + DEVICE_PACKAGES := ipq-wifi-linksys_mr7350 \ + kmod-leds-pca963x kmod-usb-ledtrig-usbport +endef +TARGET_DEVICES += linksys_mr7350 + +define Device/qihoo_360v6 + $(call Device/FitImage) + $(call Device/UbiFit) + DEVICE_VENDOR := Qihoo + DEVICE_MODEL := 360V6 + BLOCKSIZE := 128k + PAGESIZE := 2048 + SOC := ipq6000 + DEVICE_DTS_CONFIG := config@cp03-c1 + DEVICE_PACKAGES := ipq-wifi-qihoo_360v6 +endef +TARGET_DEVICES += qihoo_360v6 diff --git a/target/linux/qualcommax/ipq60xx/base-files/etc/board.d/02_network b/target/linux/qualcommax/ipq60xx/base-files/etc/board.d/02_network new file mode 100644 index 000000000..40ae93927 --- /dev/null +++ b/target/linux/qualcommax/ipq60xx/base-files/etc/board.d/02_network @@ -0,0 +1,56 @@ +# +# Copyright (c) 2015 The Linux Foundation. All rights reserved. +# Copyright (c) 2011-2015 OpenWrt.org +# + +. /lib/functions/uci-defaults.sh +. /lib/functions/system.sh + +ipq60xx_setup_interfaces() +{ + local board="$1" + + case "$board" in + linksys,mr7350) + ucidef_set_interfaces_lan_wan "lan1 lan2 lan3 lan4" "wan" + ;; + qihoo,360v6|\ + xiaomi,rm1800) + ucidef_set_interfaces_lan_wan "lan1 lan2 lan3" "wan" + ;; + *) + echo "Unsupported hardware. Network interfaces not initialized" + ;; + esac +} + +ipq60xx_setup_macs() +{ + local board="$1" + local lan_mac="" + local wan_mac="" + local label_mac="" + + case "$board" in + linksys,mr7350) + wan_mac=$(mtd_get_mac_ascii devinfo hw_mac_addr) + lan_mac=$(macaddr_add "$wan_mac" 1) + ;; + qihoo,360v6) + lan_mac=$(mtd_get_mac_ascii factory lanMac) + wan_mac=$(macaddr_add "$lan_mac" 1) + ;; + esac + + [ -n "$lan_mac" ] && ucidef_set_interface_macaddr "lan" $lan_mac + [ -n "$wan_mac" ] && ucidef_set_interface_macaddr "wan" $wan_mac + [ -n "$label_mac" ] && ucidef_set_label_macaddr $label_mac +} + +board_config_update +board=$(board_name) +ipq60xx_setup_interfaces $board +ipq60xx_setup_macs $board +board_config_flush + +exit 0 diff --git a/target/linux/qualcommax/ipq60xx/base-files/etc/hotplug.d/firmware/11-ath11k-caldata b/target/linux/qualcommax/ipq60xx/base-files/etc/hotplug.d/firmware/11-ath11k-caldata new file mode 100644 index 000000000..7084b3a01 --- /dev/null +++ b/target/linux/qualcommax/ipq60xx/base-files/etc/hotplug.d/firmware/11-ath11k-caldata @@ -0,0 +1,21 @@ +#!/bin/sh + +[ -e /lib/firmware/$FIRMWARE ] && exit 0 + +. /lib/functions/caldata.sh + +board=$(board_name) + +case "$FIRMWARE" in +"ath11k/IPQ6018/hw1.0/cal-ahb-c000000.wifi.bin") + case "$board" in + linksys,mr7350|\ + qihoo,360v6) + caldata_extract "0:art" 0x1000 0x20000 + ;; + esac + ;; +*) + exit 1 + ;; +esac diff --git a/target/linux/qualcommax/ipq60xx/base-files/etc/hotplug.d/ieee80211/11_fix_wifi_mac b/target/linux/qualcommax/ipq60xx/base-files/etc/hotplug.d/ieee80211/11_fix_wifi_mac new file mode 100644 index 000000000..88ff7c6ce --- /dev/null +++ b/target/linux/qualcommax/ipq60xx/base-files/etc/hotplug.d/ieee80211/11_fix_wifi_mac @@ -0,0 +1,23 @@ +[ "$ACTION" == "add" ] || exit 0 + +PHYNBR=${DEVPATH##*/phy} + +[ -n $PHYNBR ] || exit 0 + +. /lib/functions.sh +. /lib/functions/system.sh + +board=$(board_name) + +case "$board" in + linksys,mr7350) + addr=$(mtd_get_mac_ascii devinfo hw_mac_addr) + [ "$PHYNBR" = "0" ] && macaddr_add $addr 2 > /sys${DEVPATH}/macaddress + [ "$PHYNBR" = "1" ] && macaddr_add $addr 1 > /sys${DEVPATH}/macaddress + ;; + qihoo,360v6) + addr=$(mtd_get_mac_ascii factory lanMac) + [ "$PHYNBR" = "0" ] && macaddr_add $addr 2 > /sys${DEVPATH}/macaddress + [ "$PHYNBR" = "1" ] && macaddr_add $addr 3 > /sys${DEVPATH}/macaddress + ;; +esac diff --git a/target/linux/qualcommax/ipq60xx/base-files/etc/init.d/bootcount b/target/linux/qualcommax/ipq60xx/base-files/etc/init.d/bootcount new file mode 100644 index 000000000..15ae67aaa --- /dev/null +++ b/target/linux/qualcommax/ipq60xx/base-files/etc/init.d/bootcount @@ -0,0 +1,11 @@ +#!/bin/sh /etc/rc.common + +START=99 + +boot() { + case $(board_name) in + linksys,mr7350) + mtd resetbc s_env || true + ;; + esac +} diff --git a/target/linux/qualcommax/ipq60xx/base-files/lib/upgrade/platform.sh b/target/linux/qualcommax/ipq60xx/base-files/lib/upgrade/platform.sh new file mode 100644 index 000000000..73fb1e3b6 --- /dev/null +++ b/target/linux/qualcommax/ipq60xx/base-files/lib/upgrade/platform.sh @@ -0,0 +1,31 @@ +PART_NAME=firmware +REQUIRE_IMAGE_METADATA=1 + +RAMFS_COPY_BIN='fw_printenv fw_setenv head' +RAMFS_COPY_DATA='/etc/fw_env.config /var/lock/fw_printenv.lock' + +platform_check_image() { + return 0; +} + +platform_do_upgrade() { + case "$(board_name)" in + linksys,mr7350) + boot_part="$(fw_printenv -n boot_part)" + if [ "$boot_part" -eq "1" ]; then + fw_setenv boot_part 2 + CI_KERNPART="alt_kernel" + CI_UBIPART="alt_rootfs" + else + fw_setenv boot_part 1 + CI_UBIPART="rootfs" + fi + fw_setenv boot_part_ready 3 + fw_setenv auto_recovery yes + nand_do_upgrade "$1" + ;; + *) + default_do_upgrade "$1" + ;; + esac +} diff --git a/target/linux/qualcommax/ipq60xx/config-default b/target/linux/qualcommax/ipq60xx/config-default new file mode 100644 index 000000000..83ea4b8ee --- /dev/null +++ b/target/linux/qualcommax/ipq60xx/config-default @@ -0,0 +1,10 @@ +CONFIG_ARM_PSCI_CPUIDLE_DOMAIN=y +CONFIG_IPQ_GCC_6018=y +CONFIG_PINCTRL_IPQ6018=y +CONFIG_PWM=y +CONFIG_PWM_IPQ=y +CONFIG_PWM_SYSFS=y +# CONFIG_QCOM_CLK_SMD_RPM is not set +# CONFIG_QCOM_RPMPD is not set +CONFIG_QCOM_SMD_RPM=y +CONFIG_REGULATOR_QCOM_SMD_RPM=y diff --git a/target/linux/qualcommax/ipq60xx/target.mk b/target/linux/qualcommax/ipq60xx/target.mk new file mode 100644 index 000000000..06a85ab5e --- /dev/null +++ b/target/linux/qualcommax/ipq60xx/target.mk @@ -0,0 +1,7 @@ +SUBTARGET:=ipq60xx +BOARDNAME:=Qualcomm Atheros IPQ60xx +DEFAULT_PACKAGES += ath11k-firmware-ipq6018 + +define Target/Description + Build firmware images for Qualcomm Atheros IPQ60xx based boards. +endef diff --git a/target/linux/ipq60xx/patches-5.15/0161-arm64-dts-qcom-ipq6018-fix-NAND-node-name.patch b/target/linux/qualcommax/patches-6.1/0008-v6.2-arm64-dts-qcom-ipq6018-fix-NAND-node-name.patch similarity index 66% rename from target/linux/ipq60xx/patches-5.15/0161-arm64-dts-qcom-ipq6018-fix-NAND-node-name.patch rename to target/linux/qualcommax/patches-6.1/0008-v6.2-arm64-dts-qcom-ipq6018-fix-NAND-node-name.patch index b8fee6bb5..a87ae4b8a 100644 --- a/target/linux/ipq60xx/patches-5.15/0161-arm64-dts-qcom-ipq6018-fix-NAND-node-name.patch +++ b/target/linux/qualcommax/patches-6.1/0008-v6.2-arm64-dts-qcom-ipq6018-fix-NAND-node-name.patch @@ -1,12 +1,16 @@ -From 00c5b40d342565ece46d23b9e124a6ecade49afd Mon Sep 17 00:00:00 2001 +From 8857b0ab6a562c473c5bded0efda9390b82a84d4 Mon Sep 17 00:00:00 2001 From: Robert Marko -Date: Tue, 27 Sep 2022 15:14:13 +0200 +Date: Tue, 27 Sep 2022 22:12:17 +0200 Subject: [PATCH] arm64: dts: qcom: ipq6018: fix NAND node name Per schema it should be nand-controller@79b0000 instead of nand@79b0000. Fix it to match nand-controller.yaml requirements. Signed-off-by: Robert Marko +Reviewed-by: Krzysztof Kozlowski +Reviewed-by: Neil Armstrong +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20220927201218.1264506-1-robimarko@gmail.com --- arch/arm64/boot/dts/qcom/ipq6018.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/linux/ipq60xx/patches-5.15/0167-arm64-dts-qcom-ipq6018-align-TLMM-pin-configuration-with-DT-schema.patch b/target/linux/qualcommax/patches-6.1/0018-v6.2-arm64-dts-qcom-ipq6018-align-TLMM-pin-configuration-.patch similarity index 85% rename from target/linux/ipq60xx/patches-5.15/0167-arm64-dts-qcom-ipq6018-align-TLMM-pin-configuration-with-DT-schema.patch rename to target/linux/qualcommax/patches-6.1/0018-v6.2-arm64-dts-qcom-ipq6018-align-TLMM-pin-configuration-.patch index 86dde3c05..ceaf68bf7 100644 --- a/target/linux/ipq60xx/patches-5.15/0167-arm64-dts-qcom-ipq6018-align-TLMM-pin-configuration-with-DT-schema.patch +++ b/target/linux/qualcommax/patches-6.1/0018-v6.2-arm64-dts-qcom-ipq6018-align-TLMM-pin-configuration-.patch @@ -1,6 +1,6 @@ -From eed2617c6a237f46db3ed2b63f6dff158407e468 Mon Sep 17 00:00:00 2001 +From 20afb6751739264ea41993877de93923911dfdc3 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski -Date: Tue, 27 Sep 2022 19:36:30 +0200 +Date: Thu, 6 Oct 2022 14:46:27 +0200 Subject: [PATCH] arm64: dts: qcom: ipq6018: align TLMM pin configuration with DT schema @@ -10,6 +10,8 @@ DT schema expects TLMM pin configuration nodes to be named with Signed-off-by: Krzysztof Kozlowski Reviewed-by: Bjorn Andersson Reviewed-by: Konrad Dybcio +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20221006124659.217540-3-krzysztof.kozlowski@linaro.org --- arch/arm64/boot/dts/qcom/ipq6018-cp01-c1.dts | 4 ++-- arch/arm64/boot/dts/qcom/ipq6018.dtsi | 4 ++-- @@ -35,7 +37,7 @@ Reviewed-by: Konrad Dybcio drive-strength = <8>; --- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi +++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi -@@ -230,14 +230,14 @@ +@@ -218,14 +218,14 @@ interrupt-controller; #interrupt-cells = <2>; diff --git a/target/linux/qualcommax/patches-6.1/0022-v6.4-arm64-dts-qcom-ipq8074-add-compatible-fallback-to.patch b/target/linux/qualcommax/patches-6.1/0022-v6.4-arm64-dts-qcom-ipq8074-add-compatible-fallback-to.patch new file mode 100644 index 000000000..934ddea07 --- /dev/null +++ b/target/linux/qualcommax/patches-6.1/0022-v6.4-arm64-dts-qcom-ipq8074-add-compatible-fallback-to.patch @@ -0,0 +1,26 @@ +From d93bd4630ce163f3761aedc0b342b072bee6db6b Mon Sep 17 00:00:00 2001 +From: Krzysztof Kozlowski +Date: Wed, 22 Mar 2023 18:41:40 +0100 +Subject: [PATCH] arm64: dts: qcom: ipq8074: add compatible fallback to mailbox + +IPQ8074 mailbox is compatible with IPQ6018. + +Signed-off-by: Krzysztof Kozlowski +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20230322174148.810938-4-krzysztof.kozlowski@linaro.org +--- + arch/arm64/boot/dts/qcom/ipq8074.dtsi | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi ++++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi +@@ -680,7 +680,8 @@ + }; + + apcs_glb: mailbox@b111000 { +- compatible = "qcom,ipq8074-apcs-apps-global"; ++ compatible = "qcom,ipq8074-apcs-apps-global", ++ "qcom,ipq6018-apcs-apps-global"; + reg = <0x0b111000 0x1000>; + clocks = <&a53pll>, <&xo>; + clock-names = "pll", "xo"; diff --git a/target/linux/qualcommax/patches-6.1/0025-v6.7-cpufreq-qcom-nvmem-add-support-for-IPQ6018.patch b/target/linux/qualcommax/patches-6.1/0025-v6.7-cpufreq-qcom-nvmem-add-support-for-IPQ6018.patch new file mode 100644 index 000000000..63e2f22db --- /dev/null +++ b/target/linux/qualcommax/patches-6.1/0025-v6.7-cpufreq-qcom-nvmem-add-support-for-IPQ6018.patch @@ -0,0 +1,123 @@ +From 47e161a7873b0891f4e01a69a839f6161d816ea8 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Wed, 25 Oct 2023 14:57:57 +0530 +Subject: [PATCH] cpufreq: qcom-nvmem: add support for IPQ6018 + +IPQ6018 SoC series comes in multiple SKU-s, and not all of them support +high frequency OPP points. + +SoC itself does however have a single bit in QFPROM to indicate the CPU +speed-bin. +That bit is used to indicate frequency limit of 1.5GHz, but that alone is +not enough as IPQ6000 only goes up to 1.2GHz, but SMEM ID can be used to +limit it further. + +IPQ6018 compatible is blacklisted from DT platdev as the cpufreq device +will get created by NVMEM CPUFreq driver. + +Signed-off-by: Robert Marko +[ Viresh: Fixed rebase conflict. ] +Signed-off-by: Viresh Kumar +--- + drivers/cpufreq/cpufreq-dt-platdev.c | 1 + + drivers/cpufreq/qcom-cpufreq-nvmem.c | 58 ++++++++++++++++++++++++++++ + 2 files changed, 59 insertions(+) + +--- a/drivers/cpufreq/cpufreq-dt-platdev.c ++++ b/drivers/cpufreq/cpufreq-dt-platdev.c +@@ -163,6 +163,7 @@ static const struct of_device_id blockli + { .compatible = "ti,dra7", }, + { .compatible = "ti,omap3", }, + ++ { .compatible = "qcom,ipq6018", }, + { .compatible = "qcom,ipq8064", }, + { .compatible = "qcom,apq8064", }, + { .compatible = "qcom,msm8974", }, +--- a/drivers/cpufreq/qcom-cpufreq-nvmem.c ++++ b/drivers/cpufreq/qcom-cpufreq-nvmem.c +@@ -31,6 +31,8 @@ + + #include + ++#define IPQ6000_VERSION BIT(2) ++ + struct qcom_cpufreq_drv; + + struct qcom_cpufreq_match_data { +@@ -204,6 +206,57 @@ len_error: + return ret; + } + ++static int qcom_cpufreq_ipq6018_name_version(struct device *cpu_dev, ++ struct nvmem_cell *speedbin_nvmem, ++ char **pvs_name, ++ struct qcom_cpufreq_drv *drv) ++{ ++ u32 msm_id; ++ int ret; ++ u8 *speedbin; ++ *pvs_name = NULL; ++ ++ ret = qcom_smem_get_soc_id(&msm_id); ++ if (ret) ++ return ret; ++ ++ speedbin = nvmem_cell_read(speedbin_nvmem, NULL); ++ if (IS_ERR(speedbin)) ++ return PTR_ERR(speedbin); ++ ++ switch (msm_id) { ++ case QCOM_ID_IPQ6005: ++ case QCOM_ID_IPQ6010: ++ case QCOM_ID_IPQ6018: ++ case QCOM_ID_IPQ6028: ++ /* Fuse Value Freq BIT to set ++ * --------------------------------- ++ * 2’b0 No Limit BIT(0) ++ * 2’b1 1.5 GHz BIT(1) ++ */ ++ drv->versions = 1 << (unsigned int)(*speedbin); ++ break; ++ case QCOM_ID_IPQ6000: ++ /* ++ * IPQ6018 family only has one bit to advertise the CPU ++ * speed-bin, but that is not enough for IPQ6000 which ++ * is only rated up to 1.2GHz. ++ * So for IPQ6000 manually set BIT(2) based on SMEM ID. ++ */ ++ drv->versions = IPQ6000_VERSION; ++ break; ++ default: ++ dev_err(cpu_dev, ++ "SoC ID %u is not part of IPQ6018 family, limiting to 1.2GHz!\n", ++ msm_id); ++ drv->versions = IPQ6000_VERSION; ++ break; ++ } ++ ++ kfree(speedbin); ++ return 0; ++} ++ + static const struct qcom_cpufreq_match_data match_data_kryo = { + .get_version = qcom_cpufreq_kryo_name_version, + }; +@@ -218,6 +271,10 @@ static const struct qcom_cpufreq_match_d + .genpd_names = qcs404_genpd_names, + }; + ++static const struct qcom_cpufreq_match_data match_data_ipq6018 = { ++ .get_version = qcom_cpufreq_ipq6018_name_version, ++}; ++ + static int qcom_cpufreq_probe(struct platform_device *pdev) + { + struct qcom_cpufreq_drv *drv; +@@ -362,6 +419,7 @@ static const struct of_device_id qcom_cp + { .compatible = "qcom,apq8096", .data = &match_data_kryo }, + { .compatible = "qcom,msm8996", .data = &match_data_kryo }, + { .compatible = "qcom,qcs404", .data = &match_data_qcs404 }, ++ { .compatible = "qcom,ipq6018", .data = &match_data_ipq6018 }, + { .compatible = "qcom,ipq8064", .data = &match_data_krait }, + { .compatible = "qcom,apq8064", .data = &match_data_krait }, + { .compatible = "qcom,msm8974", .data = &match_data_krait }, diff --git a/target/linux/qualcommax/patches-6.1/0025-v6.7-cpufreq-qcom-nvmem-add-support-for-IPQ8074.patch b/target/linux/qualcommax/patches-6.1/0026-v6.7-cpufreq-qcom-nvmem-add-support-for-IPQ8074.patch similarity index 84% rename from target/linux/qualcommax/patches-6.1/0025-v6.7-cpufreq-qcom-nvmem-add-support-for-IPQ8074.patch rename to target/linux/qualcommax/patches-6.1/0026-v6.7-cpufreq-qcom-nvmem-add-support-for-IPQ8074.patch index 61cc2a459..cbd7b770f 100644 --- a/target/linux/qualcommax/patches-6.1/0025-v6.7-cpufreq-qcom-nvmem-add-support-for-IPQ8074.patch +++ b/target/linux/qualcommax/patches-6.1/0026-v6.7-cpufreq-qcom-nvmem-add-support-for-IPQ8074.patch @@ -1,4 +1,4 @@ -From df75a00c60c6e58bc36e4c63e9d7f1910412b132 Mon Sep 17 00:00:00 2001 +From 0b9cd949136f1b63f7aa9424b6e583a1ab261e36 Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Fri, 13 Oct 2023 19:20:02 +0200 Subject: [PATCH] cpufreq: qcom-nvmem: add support for IPQ8074 @@ -16,6 +16,7 @@ will get created by NVMEM CPUFreq driver. Signed-off-by: Robert Marko Acked-by: Konrad Dybcio +[ Viresh: Fixed rebase conflict. ] Signed-off-by: Viresh Kumar --- drivers/cpufreq/cpufreq-dt-platdev.c | 1 + @@ -24,9 +25,9 @@ Signed-off-by: Viresh Kumar --- a/drivers/cpufreq/cpufreq-dt-platdev.c +++ b/drivers/cpufreq/cpufreq-dt-platdev.c -@@ -164,6 +164,7 @@ static const struct of_device_id blockli - { .compatible = "ti,omap3", }, +@@ -165,6 +165,7 @@ static const struct of_device_id blockli + { .compatible = "qcom,ipq6018", }, { .compatible = "qcom,ipq8064", }, + { .compatible = "qcom,ipq8074", }, { .compatible = "qcom,apq8064", }, @@ -34,9 +35,9 @@ Signed-off-by: Viresh Kumar { .compatible = "qcom,msm8960", }, --- a/drivers/cpufreq/qcom-cpufreq-nvmem.c +++ b/drivers/cpufreq/qcom-cpufreq-nvmem.c -@@ -31,6 +31,11 @@ +@@ -33,6 +33,11 @@ - #include + #define IPQ6000_VERSION BIT(2) +enum ipq8074_versions { + IPQ8074_HAWKEYE_VERSION = 0, @@ -46,8 +47,8 @@ Signed-off-by: Viresh Kumar struct qcom_cpufreq_drv; struct qcom_cpufreq_match_data { -@@ -204,6 +209,44 @@ len_error: - return ret; +@@ -257,6 +262,44 @@ static int qcom_cpufreq_ipq6018_name_ver + return 0; } +static int qcom_cpufreq_ipq8074_name_version(struct device *cpu_dev, @@ -91,8 +92,8 @@ Signed-off-by: Viresh Kumar static const struct qcom_cpufreq_match_data match_data_kryo = { .get_version = qcom_cpufreq_kryo_name_version, }; -@@ -218,6 +261,10 @@ static const struct qcom_cpufreq_match_d - .genpd_names = qcs404_genpd_names, +@@ -275,6 +318,10 @@ static const struct qcom_cpufreq_match_d + .get_version = qcom_cpufreq_ipq6018_name_version, }; +static const struct qcom_cpufreq_match_data match_data_ipq8074 = { @@ -102,9 +103,9 @@ Signed-off-by: Viresh Kumar static int qcom_cpufreq_probe(struct platform_device *pdev) { struct qcom_cpufreq_drv *drv; -@@ -363,6 +410,7 @@ static const struct of_device_id qcom_cp - { .compatible = "qcom,msm8996", .data = &match_data_kryo }, +@@ -421,6 +468,7 @@ static const struct of_device_id qcom_cp { .compatible = "qcom,qcs404", .data = &match_data_qcs404 }, + { .compatible = "qcom,ipq6018", .data = &match_data_ipq6018 }, { .compatible = "qcom,ipq8064", .data = &match_data_krait }, + { .compatible = "qcom,ipq8074", .data = &match_data_ipq8074 }, { .compatible = "qcom,apq8064", .data = &match_data_krait }, diff --git a/target/linux/qualcommax/patches-6.1/0028-v6.7-arm64-dts-qcom-ipq8074-include-the-GPLL0-as-clock-pr.patch b/target/linux/qualcommax/patches-6.1/0028-v6.7-arm64-dts-qcom-ipq8074-include-the-GPLL0-as-clock-pr.patch index 5ae4fb567..c2d7b6793 100644 --- a/target/linux/qualcommax/patches-6.1/0028-v6.7-arm64-dts-qcom-ipq8074-include-the-GPLL0-as-clock-pr.patch +++ b/target/linux/qualcommax/patches-6.1/0028-v6.7-arm64-dts-qcom-ipq8074-include-the-GPLL0-as-clock-pr.patch @@ -19,9 +19,9 @@ Reviewed-by: Konrad Dybcio --- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi +++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -682,8 +682,8 @@ - apcs_glb: mailbox@b111000 { - compatible = "qcom,ipq8074-apcs-apps-global"; +@@ -683,8 +683,8 @@ + compatible = "qcom,ipq8074-apcs-apps-global", + "qcom,ipq6018-apcs-apps-global"; reg = <0x0b111000 0x1000>; - clocks = <&a53pll>, <&xo>; - clock-names = "pll", "xo"; diff --git a/target/linux/ipq60xx/patches-5.15/0162-arm64-dts-qcom-ipq6018-move-ARMv8-timer-out-of-SoC-node.patch b/target/linux/qualcommax/patches-6.1/0033-v6.2-arm64-dts-qcom-ipq6018-move-ARMv8-timer-out-of-SoC.patch similarity index 80% rename from target/linux/ipq60xx/patches-5.15/0162-arm64-dts-qcom-ipq6018-move-ARMv8-timer-out-of-SoC-node.patch rename to target/linux/qualcommax/patches-6.1/0033-v6.2-arm64-dts-qcom-ipq6018-move-ARMv8-timer-out-of-SoC.patch index 86d3606cc..c3e94a2ae 100644 --- a/target/linux/ipq60xx/patches-5.15/0162-arm64-dts-qcom-ipq6018-move-ARMv8-timer-out-of-SoC-node.patch +++ b/target/linux/qualcommax/patches-6.1/0033-v6.2-arm64-dts-qcom-ipq6018-move-ARMv8-timer-out-of-SoC.patch @@ -1,6 +1,6 @@ -From 555a31aaa3c5e6d9edcb48239e87d9fa52c31284 Mon Sep 17 00:00:00 2001 +From feeef118fda562cf9081edef8ad464d89db070f4 Mon Sep 17 00:00:00 2001 From: Robert Marko -Date: Tue, 27 Sep 2022 22:07:14 +0200 +Date: Tue, 27 Sep 2022 22:12:18 +0200 Subject: [PATCH] arm64: dts: qcom: ipq6018: move ARMv8 timer out of SoC node The ARM timer is usually considered not part of SoC node, just like @@ -10,13 +10,17 @@ arch/arm64/boot/dts/qcom/ipq6018-cp01-c1.dtb: soc: timer: {'compatible': ['arm,a From schema: dtschema/schemas/simple-bus.yaml Signed-off-by: Robert Marko +Reviewed-by: Krzysztof Kozlowski +Reviewed-by: Neil Armstrong +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20220927201218.1264506-2-robimarko@gmail.com --- arch/arm64/boot/dts/qcom/ipq6018.dtsi | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) --- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi +++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi -@@ -509,14 +509,6 @@ +@@ -510,14 +510,6 @@ clock-names = "xo"; }; @@ -31,7 +35,7 @@ Signed-off-by: Robert Marko timer@b120000 { #address-cells = <1>; #size-cells = <1>; -@@ -758,6 +750,14 @@ +@@ -769,6 +761,14 @@ }; }; diff --git a/target/linux/qualcommax/patches-6.1/0034-v6.3-arm64-dts-qcom-ipq6018-Sort-nodes-properly.patch b/target/linux/qualcommax/patches-6.1/0034-v6.3-arm64-dts-qcom-ipq6018-Sort-nodes-properly.patch new file mode 100644 index 000000000..ad32e64fe --- /dev/null +++ b/target/linux/qualcommax/patches-6.1/0034-v6.3-arm64-dts-qcom-ipq6018-Sort-nodes-properly.patch @@ -0,0 +1,605 @@ +From 2c6e322a41c5e1ca45be50b9d5fbcda62dc23a0d Mon Sep 17 00:00:00 2001 +From: Konrad Dybcio +Date: Mon, 2 Jan 2023 10:46:28 +0100 +Subject: [PATCH] arm64: dts: qcom: ipq6018: Sort nodes properly + +Order nodes by unit address if one exists and alphabetically otherwise. + +Signed-off-by: Konrad Dybcio +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20230102094642.74254-4-konrad.dybcio@linaro.org +--- + arch/arm64/boot/dts/qcom/ipq6018.dtsi | 562 +++++++++++++------------- + 1 file changed, 281 insertions(+), 281 deletions(-) + +--- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi ++++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi +@@ -87,6 +87,12 @@ + }; + }; + ++ firmware { ++ scm { ++ compatible = "qcom,scm-ipq6018", "qcom,scm"; ++ }; ++ }; ++ + cpu_opp_table: opp-table-cpu { + compatible = "operating-points-v2"; + opp-shared; +@@ -123,12 +129,6 @@ + }; + }; + +- firmware { +- scm { +- compatible = "qcom,scm-ipq6018", "qcom,scm"; +- }; +- }; +- + pmuv8: pmu { + compatible = "arm,cortex-a53-pmu"; + interrupts = ; ++ qcom,rpm-msg-ram = <&rpm_msg_ram>; ++ mboxes = <&apcs_glb 0>; ++ ++ rpm_requests: glink-channel { ++ compatible = "qcom,rpm-ipq6018"; ++ qcom,glink-channels = "rpm_requests"; ++ ++ regulators { ++ compatible = "qcom,rpm-mp5496-regulators"; ++ ++ ipq6018_s2: s2 { ++ regulator-min-microvolt = <725000>; ++ regulator-max-microvolt = <1062500>; ++ regulator-always-on; ++ }; ++ }; ++ }; ++ }; ++ + smem { + compatible = "qcom,smem"; + memory-region = <&smem_region>; +@@ -179,6 +201,102 @@ + dma-ranges; + compatible = "simple-bus"; + ++ qusb_phy_1: qusb@59000 { ++ compatible = "qcom,ipq6018-qusb2-phy"; ++ reg = <0x0 0x00059000 0x0 0x180>; ++ #phy-cells = <0>; ++ ++ clocks = <&gcc GCC_USB1_PHY_CFG_AHB_CLK>, ++ <&xo>; ++ clock-names = "cfg_ahb", "ref"; ++ ++ resets = <&gcc GCC_QUSB2_1_PHY_BCR>; ++ status = "disabled"; ++ }; ++ ++ ssphy_0: ssphy@78000 { ++ compatible = "qcom,ipq6018-qmp-usb3-phy"; ++ reg = <0x0 0x00078000 0x0 0x1c4>; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ranges; ++ ++ clocks = <&gcc GCC_USB0_AUX_CLK>, ++ <&gcc GCC_USB0_PHY_CFG_AHB_CLK>, <&xo>; ++ clock-names = "aux", "cfg_ahb", "ref"; ++ ++ resets = <&gcc GCC_USB0_PHY_BCR>, ++ <&gcc GCC_USB3PHY_0_PHY_BCR>; ++ reset-names = "phy","common"; ++ status = "disabled"; ++ ++ usb0_ssphy: phy@78200 { ++ reg = <0x0 0x00078200 0x0 0x130>, /* Tx */ ++ <0x0 0x00078400 0x0 0x200>, /* Rx */ ++ <0x0 0x00078800 0x0 0x1f8>, /* PCS */ ++ <0x0 0x00078600 0x0 0x044>; /* PCS misc */ ++ #phy-cells = <0>; ++ #clock-cells = <0>; ++ clocks = <&gcc GCC_USB0_PIPE_CLK>; ++ clock-names = "pipe0"; ++ clock-output-names = "gcc_usb0_pipe_clk_src"; ++ }; ++ }; ++ ++ qusb_phy_0: qusb@79000 { ++ compatible = "qcom,ipq6018-qusb2-phy"; ++ reg = <0x0 0x00079000 0x0 0x180>; ++ #phy-cells = <0>; ++ ++ clocks = <&gcc GCC_USB0_PHY_CFG_AHB_CLK>, ++ <&xo>; ++ clock-names = "cfg_ahb", "ref"; ++ ++ resets = <&gcc GCC_QUSB2_0_PHY_BCR>; ++ status = "disabled"; ++ }; ++ ++ pcie_phy: phy@84000 { ++ compatible = "qcom,ipq6018-qmp-pcie-phy"; ++ reg = <0x0 0x00084000 0x0 0x1bc>; /* Serdes PLL */ ++ status = "disabled"; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ranges; ++ ++ clocks = <&gcc GCC_PCIE0_AUX_CLK>, ++ <&gcc GCC_PCIE0_AHB_CLK>; ++ clock-names = "aux", "cfg_ahb"; ++ ++ resets = <&gcc GCC_PCIE0_PHY_BCR>, ++ <&gcc GCC_PCIE0PHY_PHY_BCR>; ++ reset-names = "phy", ++ "common"; ++ ++ pcie_phy0: phy@84200 { ++ reg = <0x0 0x00084200 0x0 0x16c>, /* Serdes Tx */ ++ <0x0 0x00084400 0x0 0x200>, /* Serdes Rx */ ++ <0x0 0x00084800 0x0 0x1f0>, /* PCS: Lane0, COM, PCIE */ ++ <0x0 0x00084c00 0x0 0xf4>; /* pcs_misc */ ++ #phy-cells = <0>; ++ ++ clocks = <&gcc GCC_PCIE0_PIPE_CLK>; ++ clock-names = "pipe0"; ++ clock-output-names = "gcc_pcie0_pipe_clk_src"; ++ #clock-cells = <0>; ++ }; ++ }; ++ ++ mdio: mdio@90000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "qcom,ipq6018-mdio", "qcom,ipq4019-mdio"; ++ reg = <0x0 0x00090000 0x0 0x64>; ++ clocks = <&gcc GCC_MDIO_AHB_CLK>; ++ clock-names = "gcc_mdio_ahb_clk"; ++ status = "disabled"; ++ }; ++ + prng: qrng@e1000 { + compatible = "qcom,prng-ee"; + reg = <0x0 0x000e3000 0x0 0x1000>; +@@ -257,6 +375,41 @@ + reg = <0x0 0x01937000 0x0 0x21000>; + }; + ++ usb2: usb@70f8800 { ++ compatible = "qcom,ipq6018-dwc3", "qcom,dwc3"; ++ reg = <0x0 0x070F8800 0x0 0x400>; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ranges; ++ clocks = <&gcc GCC_USB1_MASTER_CLK>, ++ <&gcc GCC_USB1_SLEEP_CLK>, ++ <&gcc GCC_USB1_MOCK_UTMI_CLK>; ++ clock-names = "core", ++ "sleep", ++ "mock_utmi"; ++ ++ assigned-clocks = <&gcc GCC_USB1_MASTER_CLK>, ++ <&gcc GCC_USB1_MOCK_UTMI_CLK>; ++ assigned-clock-rates = <133330000>, ++ <24000000>; ++ resets = <&gcc GCC_USB1_BCR>; ++ status = "disabled"; ++ ++ dwc_1: usb@7000000 { ++ compatible = "snps,dwc3"; ++ reg = <0x0 0x07000000 0x0 0xcd00>; ++ interrupts = ; ++ phys = <&qusb_phy_1>; ++ phy-names = "usb2-phy"; ++ tx-fifo-resize; ++ snps,is-utmi-l1-suspend; ++ snps,hird-threshold = /bits/ 8 <0x0>; ++ snps,dis_u2_susphy_quirk; ++ snps,dis_u3_susphy_quirk; ++ dr_mode = "host"; ++ }; ++ }; ++ + blsp_dma: dma-controller@7884000 { + compatible = "qcom,bam-v1.7.0"; + reg = <0x0 0x07884000 0x0 0x2b000>; +@@ -366,6 +519,49 @@ + status = "disabled"; + }; + ++ usb3: usb@8af8800 { ++ compatible = "qcom,ipq6018-dwc3", "qcom,dwc3"; ++ reg = <0x0 0x08af8800 0x0 0x400>; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ranges; ++ ++ clocks = <&gcc GCC_SYS_NOC_USB0_AXI_CLK>, ++ <&gcc GCC_USB0_MASTER_CLK>, ++ <&gcc GCC_USB0_SLEEP_CLK>, ++ <&gcc GCC_USB0_MOCK_UTMI_CLK>; ++ clock-names = "cfg_noc", ++ "core", ++ "sleep", ++ "mock_utmi"; ++ ++ assigned-clocks = <&gcc GCC_SYS_NOC_USB0_AXI_CLK>, ++ <&gcc GCC_USB0_MASTER_CLK>, ++ <&gcc GCC_USB0_MOCK_UTMI_CLK>; ++ assigned-clock-rates = <133330000>, ++ <133330000>, ++ <24000000>; ++ ++ resets = <&gcc GCC_USB0_BCR>; ++ status = "disabled"; ++ ++ dwc_0: usb@8a00000 { ++ compatible = "snps,dwc3"; ++ reg = <0x0 0x08a00000 0x0 0xcd00>; ++ interrupts = ; ++ phys = <&qusb_phy_0>, <&usb0_ssphy>; ++ phy-names = "usb2-phy", "usb3-phy"; ++ clocks = <&xo>; ++ clock-names = "ref"; ++ tx-fifo-resize; ++ snps,is-utmi-l1-suspend; ++ snps,hird-threshold = /bits/ 8 <0x0>; ++ snps,dis_u2_susphy_quirk; ++ snps,dis_u3_susphy_quirk; ++ dr_mode = "host"; ++ }; ++ }; ++ + intc: interrupt-controller@b000000 { + compatible = "qcom,msm-qgic2"; + #address-cells = <2>; +@@ -386,105 +582,6 @@ + }; + }; + +- pcie_phy: phy@84000 { +- compatible = "qcom,ipq6018-qmp-pcie-phy"; +- reg = <0x0 0x00084000 0x0 0x1bc>; /* Serdes PLL */ +- status = "disabled"; +- #address-cells = <2>; +- #size-cells = <2>; +- ranges; +- +- clocks = <&gcc GCC_PCIE0_AUX_CLK>, +- <&gcc GCC_PCIE0_AHB_CLK>; +- clock-names = "aux", "cfg_ahb"; +- +- resets = <&gcc GCC_PCIE0_PHY_BCR>, +- <&gcc GCC_PCIE0PHY_PHY_BCR>; +- reset-names = "phy", +- "common"; +- +- pcie_phy0: phy@84200 { +- reg = <0x0 0x00084200 0x0 0x16c>, /* Serdes Tx */ +- <0x0 0x00084400 0x0 0x200>, /* Serdes Rx */ +- <0x0 0x00084800 0x0 0x1f0>, /* PCS: Lane0, COM, PCIE */ +- <0x0 0x00084c00 0x0 0xf4>; /* pcs_misc */ +- #phy-cells = <0>; +- +- clocks = <&gcc GCC_PCIE0_PIPE_CLK>; +- clock-names = "pipe0"; +- clock-output-names = "gcc_pcie0_pipe_clk_src"; +- #clock-cells = <0>; +- }; +- }; +- +- pcie0: pci@20000000 { +- compatible = "qcom,pcie-ipq6018"; +- reg = <0x0 0x20000000 0x0 0xf1d>, +- <0x0 0x20000f20 0x0 0xa8>, +- <0x0 0x20001000 0x0 0x1000>, +- <0x0 0x80000 0x0 0x4000>, +- <0x0 0x20100000 0x0 0x1000>; +- reg-names = "dbi", "elbi", "atu", "parf", "config"; +- +- device_type = "pci"; +- linux,pci-domain = <0>; +- bus-range = <0x00 0xff>; +- num-lanes = <1>; +- max-link-speed = <3>; +- #address-cells = <3>; +- #size-cells = <2>; +- +- phys = <&pcie_phy0>; +- phy-names = "pciephy"; +- +- ranges = <0x81000000 0x0 0x00000000 0x0 0x20200000 0x0 0x10000>, +- <0x82000000 0x0 0x20220000 0x0 0x20220000 0x0 0xfde0000>; +- +- interrupts = ; +- interrupt-names = "msi"; +- +- #interrupt-cells = <1>; +- interrupt-map-mask = <0 0 0 0x7>; +- interrupt-map = <0 0 0 1 &intc 0 75 +- IRQ_TYPE_LEVEL_HIGH>, /* int_a */ +- <0 0 0 2 &intc 0 78 +- IRQ_TYPE_LEVEL_HIGH>, /* int_b */ +- <0 0 0 3 &intc 0 79 +- IRQ_TYPE_LEVEL_HIGH>, /* int_c */ +- <0 0 0 4 &intc 0 83 +- IRQ_TYPE_LEVEL_HIGH>; /* int_d */ +- +- clocks = <&gcc GCC_SYS_NOC_PCIE0_AXI_CLK>, +- <&gcc GCC_PCIE0_AXI_M_CLK>, +- <&gcc GCC_PCIE0_AXI_S_CLK>, +- <&gcc GCC_PCIE0_AXI_S_BRIDGE_CLK>, +- <&gcc PCIE0_RCHNG_CLK>; +- clock-names = "iface", +- "axi_m", +- "axi_s", +- "axi_bridge", +- "rchng"; +- +- resets = <&gcc GCC_PCIE0_PIPE_ARES>, +- <&gcc GCC_PCIE0_SLEEP_ARES>, +- <&gcc GCC_PCIE0_CORE_STICKY_ARES>, +- <&gcc GCC_PCIE0_AXI_MASTER_ARES>, +- <&gcc GCC_PCIE0_AXI_SLAVE_ARES>, +- <&gcc GCC_PCIE0_AHB_ARES>, +- <&gcc GCC_PCIE0_AXI_MASTER_STICKY_ARES>, +- <&gcc GCC_PCIE0_AXI_SLAVE_STICKY_ARES>; +- reset-names = "pipe", +- "sleep", +- "sticky", +- "axi_m", +- "axi_s", +- "ahb", +- "axi_m_sticky", +- "axi_s_sticky"; +- +- status = "disabled"; +- }; +- + watchdog@b017000 { + compatible = "qcom,kpss-wdt"; + interrupts = ; +@@ -617,147 +714,74 @@ + }; + }; + +- mdio: mdio@90000 { +- #address-cells = <1>; +- #size-cells = <0>; +- compatible = "qcom,ipq6018-mdio", "qcom,ipq4019-mdio"; +- reg = <0x0 0x00090000 0x0 0x64>; +- clocks = <&gcc GCC_MDIO_AHB_CLK>; +- clock-names = "gcc_mdio_ahb_clk"; +- status = "disabled"; +- }; +- +- qusb_phy_1: qusb@59000 { +- compatible = "qcom,ipq6018-qusb2-phy"; +- reg = <0x0 0x00059000 0x0 0x180>; +- #phy-cells = <0>; +- +- clocks = <&gcc GCC_USB1_PHY_CFG_AHB_CLK>, +- <&xo>; +- clock-names = "cfg_ahb", "ref"; +- +- resets = <&gcc GCC_QUSB2_1_PHY_BCR>; +- status = "disabled"; +- }; +- +- usb2: usb@70f8800 { +- compatible = "qcom,ipq6018-dwc3", "qcom,dwc3"; +- reg = <0x0 0x070F8800 0x0 0x400>; +- #address-cells = <2>; +- #size-cells = <2>; +- ranges; +- clocks = <&gcc GCC_USB1_MASTER_CLK>, +- <&gcc GCC_USB1_SLEEP_CLK>, +- <&gcc GCC_USB1_MOCK_UTMI_CLK>; +- clock-names = "core", +- "sleep", +- "mock_utmi"; +- +- assigned-clocks = <&gcc GCC_USB1_MASTER_CLK>, +- <&gcc GCC_USB1_MOCK_UTMI_CLK>; +- assigned-clock-rates = <133330000>, +- <24000000>; +- resets = <&gcc GCC_USB1_BCR>; +- status = "disabled"; +- +- dwc_1: usb@7000000 { +- compatible = "snps,dwc3"; +- reg = <0x0 0x07000000 0x0 0xcd00>; +- interrupts = ; +- phys = <&qusb_phy_1>; +- phy-names = "usb2-phy"; +- tx-fifo-resize; +- snps,is-utmi-l1-suspend; +- snps,hird-threshold = /bits/ 8 <0x0>; +- snps,dis_u2_susphy_quirk; +- snps,dis_u3_susphy_quirk; +- dr_mode = "host"; +- }; +- }; ++ pcie0: pci@20000000 { ++ compatible = "qcom,pcie-ipq6018"; ++ reg = <0x0 0x20000000 0x0 0xf1d>, ++ <0x0 0x20000f20 0x0 0xa8>, ++ <0x0 0x20001000 0x0 0x1000>, ++ <0x0 0x80000 0x0 0x4000>, ++ <0x0 0x20100000 0x0 0x1000>; ++ reg-names = "dbi", "elbi", "atu", "parf", "config"; + +- ssphy_0: ssphy@78000 { +- compatible = "qcom,ipq6018-qmp-usb3-phy"; +- reg = <0x0 0x00078000 0x0 0x1c4>; +- #address-cells = <2>; ++ device_type = "pci"; ++ linux,pci-domain = <0>; ++ bus-range = <0x00 0xff>; ++ num-lanes = <1>; ++ max-link-speed = <3>; ++ #address-cells = <3>; + #size-cells = <2>; +- ranges; +- +- clocks = <&gcc GCC_USB0_AUX_CLK>, +- <&gcc GCC_USB0_PHY_CFG_AHB_CLK>, <&xo>; +- clock-names = "aux", "cfg_ahb", "ref"; +- +- resets = <&gcc GCC_USB0_PHY_BCR>, +- <&gcc GCC_USB3PHY_0_PHY_BCR>; +- reset-names = "phy","common"; +- status = "disabled"; +- +- usb0_ssphy: phy@78200 { +- reg = <0x0 0x00078200 0x0 0x130>, /* Tx */ +- <0x0 0x00078400 0x0 0x200>, /* Rx */ +- <0x0 0x00078800 0x0 0x1f8>, /* PCS */ +- <0x0 0x00078600 0x0 0x044>; /* PCS misc */ +- #phy-cells = <0>; +- #clock-cells = <0>; +- clocks = <&gcc GCC_USB0_PIPE_CLK>; +- clock-names = "pipe0"; +- clock-output-names = "gcc_usb0_pipe_clk_src"; +- }; +- }; + +- qusb_phy_0: qusb@79000 { +- compatible = "qcom,ipq6018-qusb2-phy"; +- reg = <0x0 0x00079000 0x0 0x180>; +- #phy-cells = <0>; ++ phys = <&pcie_phy0>; ++ phy-names = "pciephy"; + +- clocks = <&gcc GCC_USB0_PHY_CFG_AHB_CLK>, +- <&xo>; +- clock-names = "cfg_ahb", "ref"; ++ ranges = <0x81000000 0 0x20200000 0 0x20200000 ++ 0 0x10000>, /* downstream I/O */ ++ <0x82000000 0 0x20220000 0 0x20220000 ++ 0 0xfde0000>; /* non-prefetchable memory */ + +- resets = <&gcc GCC_QUSB2_0_PHY_BCR>; +- status = "disabled"; +- }; ++ interrupts = ; ++ interrupt-names = "msi"; + +- usb3: usb@8af8800 { +- compatible = "qcom,ipq6018-dwc3", "qcom,dwc3"; +- reg = <0x0 0x8af8800 0x0 0x400>; +- #address-cells = <2>; +- #size-cells = <2>; +- ranges; ++ #interrupt-cells = <1>; ++ interrupt-map-mask = <0 0 0 0x7>; ++ interrupt-map = <0 0 0 1 &intc 0 75 ++ IRQ_TYPE_LEVEL_HIGH>, /* int_a */ ++ <0 0 0 2 &intc 0 78 ++ IRQ_TYPE_LEVEL_HIGH>, /* int_b */ ++ <0 0 0 3 &intc 0 79 ++ IRQ_TYPE_LEVEL_HIGH>, /* int_c */ ++ <0 0 0 4 &intc 0 83 ++ IRQ_TYPE_LEVEL_HIGH>; /* int_d */ + +- clocks = <&gcc GCC_SYS_NOC_USB0_AXI_CLK>, +- <&gcc GCC_USB0_MASTER_CLK>, +- <&gcc GCC_USB0_SLEEP_CLK>, +- <&gcc GCC_USB0_MOCK_UTMI_CLK>; +- clock-names = "cfg_noc", +- "core", +- "sleep", +- "mock_utmi"; ++ clocks = <&gcc GCC_SYS_NOC_PCIE0_AXI_CLK>, ++ <&gcc GCC_PCIE0_AXI_M_CLK>, ++ <&gcc GCC_PCIE0_AXI_S_CLK>, ++ <&gcc GCC_PCIE0_AXI_S_BRIDGE_CLK>, ++ <&gcc PCIE0_RCHNG_CLK>; ++ clock-names = "iface", ++ "axi_m", ++ "axi_s", ++ "axi_bridge", ++ "rchng"; + +- assigned-clocks = <&gcc GCC_SYS_NOC_USB0_AXI_CLK>, +- <&gcc GCC_USB0_MASTER_CLK>, +- <&gcc GCC_USB0_MOCK_UTMI_CLK>; +- assigned-clock-rates = <133330000>, +- <133330000>, +- <24000000>; ++ resets = <&gcc GCC_PCIE0_PIPE_ARES>, ++ <&gcc GCC_PCIE0_SLEEP_ARES>, ++ <&gcc GCC_PCIE0_CORE_STICKY_ARES>, ++ <&gcc GCC_PCIE0_AXI_MASTER_ARES>, ++ <&gcc GCC_PCIE0_AXI_SLAVE_ARES>, ++ <&gcc GCC_PCIE0_AHB_ARES>, ++ <&gcc GCC_PCIE0_AXI_MASTER_STICKY_ARES>, ++ <&gcc GCC_PCIE0_AXI_SLAVE_STICKY_ARES>; ++ reset-names = "pipe", ++ "sleep", ++ "sticky", ++ "axi_m", ++ "axi_s", ++ "ahb", ++ "axi_m_sticky", ++ "axi_s_sticky"; + +- resets = <&gcc GCC_USB0_BCR>; + status = "disabled"; +- +- dwc_0: usb@8a00000 { +- compatible = "snps,dwc3"; +- reg = <0x0 0x8a00000 0x0 0xcd00>; +- interrupts = ; +- phys = <&qusb_phy_0>, <&usb0_ssphy>; +- phy-names = "usb2-phy", "usb3-phy"; +- clocks = <&xo>; +- clock-names = "ref"; +- tx-fifo-resize; +- snps,is-utmi-l1-suspend; +- snps,hird-threshold = /bits/ 8 <0x0>; +- snps,dis_u2_susphy_quirk; +- snps,dis_u3_susphy_quirk; +- dr_mode = "host"; +- }; + }; + }; + +@@ -792,26 +816,4 @@ + #interrupt-cells = <2>; + }; + }; +- +- rpm-glink { +- compatible = "qcom,glink-rpm"; +- interrupts = ; +- qcom,rpm-msg-ram = <&rpm_msg_ram>; +- mboxes = <&apcs_glb 0>; +- +- rpm_requests: glink-channel { +- compatible = "qcom,rpm-ipq6018"; +- qcom,glink-channels = "rpm_requests"; +- +- regulators { +- compatible = "qcom,rpm-mp5496-regulators"; +- +- ipq6018_s2: s2 { +- regulator-min-microvolt = <725000>; +- regulator-max-microvolt = <1062500>; +- regulator-always-on; +- }; +- }; +- }; +- }; + }; diff --git a/target/linux/qualcommax/patches-6.1/0035-v6.3-arm64-dts-qcom-ipq6018-Add-remove-some-newlines.patch b/target/linux/qualcommax/patches-6.1/0035-v6.3-arm64-dts-qcom-ipq6018-Add-remove-some-newlines.patch new file mode 100644 index 000000000..a883e305d --- /dev/null +++ b/target/linux/qualcommax/patches-6.1/0035-v6.3-arm64-dts-qcom-ipq6018-Add-remove-some-newlines.patch @@ -0,0 +1,92 @@ +From 6db9ed9a128cbae1423d043f3debd8bfa77783fd Mon Sep 17 00:00:00 2001 +From: Konrad Dybcio +Date: Mon, 2 Jan 2023 10:46:29 +0100 +Subject: [PATCH] arm64: dts: qcom: ipq6018: Add/remove some newlines + +Some lines were broken very aggresively, presumably to fit under 80 chars +and some places could have used a newline, particularly between subsequent +nodes. Address all that and remove redundant comments near PCIe ranges +while at it so as not to exceed 100 chars needlessly. + +Signed-off-by: Konrad Dybcio +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20230102094642.74254-5-konrad.dybcio@linaro.org +--- + arch/arm64/boot/dts/qcom/ipq6018.dtsi | 26 ++++++++++++-------------- + 1 file changed, 12 insertions(+), 14 deletions(-) + +--- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi ++++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi +@@ -102,26 +102,31 @@ + opp-microvolt = <725000>; + clock-latency-ns = <200000>; + }; ++ + opp-1056000000 { + opp-hz = /bits/ 64 <1056000000>; + opp-microvolt = <787500>; + clock-latency-ns = <200000>; + }; ++ + opp-1320000000 { + opp-hz = /bits/ 64 <1320000000>; + opp-microvolt = <862500>; + clock-latency-ns = <200000>; + }; ++ + opp-1440000000 { + opp-hz = /bits/ 64 <1440000000>; + opp-microvolt = <925000>; + clock-latency-ns = <200000>; + }; ++ + opp-1608000000 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <987500>; + clock-latency-ns = <200000>; + }; ++ + opp-1800000000 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <1062500>; +@@ -131,8 +136,7 @@ + + pmuv8: pmu { + compatible = "arm,cortex-a53-pmu"; +- interrupts = ; ++ interrupts = ; + }; + + psci: psci { +@@ -734,24 +738,18 @@ + phys = <&pcie_phy0>; + phy-names = "pciephy"; + +- ranges = <0x81000000 0 0x20200000 0 0x20200000 +- 0 0x10000>, /* downstream I/O */ +- <0x82000000 0 0x20220000 0 0x20220000 +- 0 0xfde0000>; /* non-prefetchable memory */ ++ ranges = <0x81000000 0 0x20200000 0 0x20200000 0 0x10000>, ++ <0x82000000 0 0x20220000 0 0x20220000 0 0xfde0000>; + + interrupts = ; + interrupt-names = "msi"; + + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 0x7>; +- interrupt-map = <0 0 0 1 &intc 0 75 +- IRQ_TYPE_LEVEL_HIGH>, /* int_a */ +- <0 0 0 2 &intc 0 78 +- IRQ_TYPE_LEVEL_HIGH>, /* int_b */ +- <0 0 0 3 &intc 0 79 +- IRQ_TYPE_LEVEL_HIGH>, /* int_c */ +- <0 0 0 4 &intc 0 83 +- IRQ_TYPE_LEVEL_HIGH>; /* int_d */ ++ interrupt-map = <0 0 0 1 &intc 0 75 IRQ_TYPE_LEVEL_HIGH>, /* int_a */ ++ <0 0 0 2 &intc 0 78 IRQ_TYPE_LEVEL_HIGH>, /* int_b */ ++ <0 0 0 3 &intc 0 79 IRQ_TYPE_LEVEL_HIGH>, /* int_c */ ++ <0 0 0 4 &intc 0 83 IRQ_TYPE_LEVEL_HIGH>; /* int_d */ + + clocks = <&gcc GCC_SYS_NOC_PCIE0_AXI_CLK>, + <&gcc GCC_PCIE0_AXI_M_CLK>, diff --git a/target/linux/qualcommax/patches-6.1/0036-v6.3-arm64-dts-qcom-ipq6018-Use-lowercase-hex.patch b/target/linux/qualcommax/patches-6.1/0036-v6.3-arm64-dts-qcom-ipq6018-Use-lowercase-hex.patch new file mode 100644 index 000000000..35aa46bb1 --- /dev/null +++ b/target/linux/qualcommax/patches-6.1/0036-v6.3-arm64-dts-qcom-ipq6018-Use-lowercase-hex.patch @@ -0,0 +1,25 @@ +From 7356ae3e10abd1d71f06ff0b8a8e72aa7c955c57 Mon Sep 17 00:00:00 2001 +From: Konrad Dybcio +Date: Mon, 2 Jan 2023 10:46:30 +0100 +Subject: [PATCH] arm64: dts: qcom: ipq6018: Use lowercase hex + +One value escaped my previous lowercase hexification. Take care of it. + +Signed-off-by: Konrad Dybcio +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20230102094642.74254-6-konrad.dybcio@linaro.org +--- + arch/arm64/boot/dts/qcom/ipq6018.dtsi | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi ++++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi +@@ -381,7 +381,7 @@ + + usb2: usb@70f8800 { + compatible = "qcom,ipq6018-dwc3", "qcom,dwc3"; +- reg = <0x0 0x070F8800 0x0 0x400>; ++ reg = <0x0 0x070f8800 0x0 0x400>; + #address-cells = <2>; + #size-cells = <2>; + ranges; diff --git a/target/linux/qualcommax/patches-6.1/0037-v6.3-arm64-dts-qcom-ipq6018-align-RPM-G-Link-node-with.patch b/target/linux/qualcommax/patches-6.1/0037-v6.3-arm64-dts-qcom-ipq6018-align-RPM-G-Link-node-with.patch new file mode 100644 index 000000000..c939d126b --- /dev/null +++ b/target/linux/qualcommax/patches-6.1/0037-v6.3-arm64-dts-qcom-ipq6018-align-RPM-G-Link-node-with.patch @@ -0,0 +1,28 @@ +From 679ee73bbee28cab441008f8cca38160cc8f3d05 Mon Sep 17 00:00:00 2001 +From: Krzysztof Kozlowski +Date: Wed, 8 Feb 2023 11:15:39 +0100 +Subject: [PATCH] arm64: dts: qcom: ipq6018: align RPM G-Link node with + bindings + +Bindings expect (and most of DTS use) the RPM G-Link node name to be +"rpm-requests". + +Signed-off-by: Krzysztof Kozlowski +Reviewed-by: Dmitry Baryshkov +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20230208101545.45711-1-krzysztof.kozlowski@linaro.org +--- + arch/arm64/boot/dts/qcom/ipq6018.dtsi | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi ++++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi +@@ -176,7 +176,7 @@ + qcom,rpm-msg-ram = <&rpm_msg_ram>; + mboxes = <&apcs_glb 0>; + +- rpm_requests: glink-channel { ++ rpm_requests: rpm-requests { + compatible = "qcom,rpm-ipq6018"; + qcom,glink-channels = "rpm_requests"; + diff --git a/target/linux/qualcommax/patches-6.1/0038-v6.4-arm64-dts-qcom-ipq6018-cp01-c1-drop-SPI-cs-select.patch b/target/linux/qualcommax/patches-6.1/0038-v6.4-arm64-dts-qcom-ipq6018-cp01-c1-drop-SPI-cs-select.patch new file mode 100644 index 000000000..28688069b --- /dev/null +++ b/target/linux/qualcommax/patches-6.1/0038-v6.4-arm64-dts-qcom-ipq6018-cp01-c1-drop-SPI-cs-select.patch @@ -0,0 +1,27 @@ +From afa8eb675fc6dd606783ed2350de90927d6fb9d3 Mon Sep 17 00:00:00 2001 +From: Krzysztof Kozlowski +Date: Wed, 8 Mar 2023 13:59:01 +0100 +Subject: [PATCH] arm64: dts: qcom: ipq6018-cp01-c1: drop SPI cs-select + +The SPI controller nodes do not use/allow cs-select property: + + ipq6018-cp01-c1.dtb: spi@78b5000: Unevaluated properties are not allowed ('cs-select' was unexpected) + +Signed-off-by: Krzysztof Kozlowski +Reviewed-by: Konrad Dybcio +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20230308125906.236885-6-krzysztof.kozlowski@linaro.org +--- + arch/arm64/boot/dts/qcom/ipq6018-cp01-c1.dts | 1 - + 1 file changed, 1 deletion(-) + +--- a/arch/arm64/boot/dts/qcom/ipq6018-cp01-c1.dts ++++ b/arch/arm64/boot/dts/qcom/ipq6018-cp01-c1.dts +@@ -36,7 +36,6 @@ + }; + + &blsp1_spi1 { +- cs-select = <0>; + pinctrl-0 = <&spi_0_pins>; + pinctrl-names = "default"; + status = "okay"; diff --git a/target/linux/qualcommax/patches-6.1/0039-v6.5-arm64-dts-qcom-add-few-more-reserved-memory-region.patch b/target/linux/qualcommax/patches-6.1/0039-v6.5-arm64-dts-qcom-add-few-more-reserved-memory-region.patch new file mode 100644 index 000000000..d1280b528 --- /dev/null +++ b/target/linux/qualcommax/patches-6.1/0039-v6.5-arm64-dts-qcom-add-few-more-reserved-memory-region.patch @@ -0,0 +1,92 @@ +From 0cd4e90cb2dec02ff859f5c98f744f43a23aea65 Mon Sep 17 00:00:00 2001 +From: Vignesh Viswanathan +Date: Fri, 26 May 2023 16:36:53 +0530 +Subject: [PATCH] arm64: dts: qcom: add few more reserved memory region + +In IPQ SoCs, bootloader will collect the system RAM contents upon crash +for the post morterm analysis. If we don't reserve the memory region used +by bootloader, obviously linux will consume it and upon next boot on +crash, bootloader will be loaded in the same region, which will lead to +loose some of the data, sometimes we may miss out critical information. +So lets reserve the region used by the bootloader. + +Similarly SBL copies some data into the reserved region and it will be +used in the crash scenario. So reserve 1MB for SBL as well. + +While at it, drop the size padding in the reserved memory region, +wherever applicable. + +Signed-off-by: Vignesh Viswanathan +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20230526110653.27777-4-quic_viswanat@quicinc.com +--- + arch/arm64/boot/dts/qcom/ipq6018.dtsi | 16 +++++++++++++--- + arch/arm64/boot/dts/qcom/ipq8074.dtsi | 14 ++++++++++++-- + 2 files changed, 25 insertions(+), 5 deletions(-) + +--- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi ++++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi +@@ -154,18 +154,28 @@ + no-map; + }; + ++ bootloader@4a100000 { ++ reg = <0x0 0x4a100000 0x0 0x400000>; ++ no-map; ++ }; ++ ++ sbl@4a500000 { ++ reg = <0x0 0x4a500000 0x0 0x100000>; ++ no-map; ++ }; ++ + tz: memory@4a600000 { +- reg = <0x0 0x4a600000 0x0 0x00400000>; ++ reg = <0x0 0x4a600000 0x0 0x400000>; + no-map; + }; + + smem_region: memory@4aa00000 { +- reg = <0x0 0x4aa00000 0x0 0x00100000>; ++ reg = <0x0 0x4aa00000 0x0 0x100000>; + no-map; + }; + + q6_region: memory@4ab00000 { +- reg = <0x0 0x4ab00000 0x0 0x05500000>; ++ reg = <0x0 0x4ab00000 0x0 0x5500000>; + no-map; + }; + }; +--- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi ++++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi +@@ -85,17 +85,27 @@ + #size-cells = <2>; + ranges; + ++ bootloader@4a600000 { ++ reg = <0x0 0x4a600000 0x0 0x400000>; ++ no-map; ++ }; ++ ++ sbl@4aa00000 { ++ reg = <0x0 0x4aa00000 0x0 0x100000>; ++ no-map; ++ }; ++ + smem@4ab00000 { + compatible = "qcom,smem"; +- reg = <0x0 0x4ab00000 0x0 0x00100000>; ++ reg = <0x0 0x4ab00000 0x0 0x100000>; + no-map; + + hwlocks = <&tcsr_mutex 3>; + }; + + memory@4ac00000 { ++ reg = <0x0 0x4ac00000 0x0 0x400000>; + no-map; +- reg = <0x0 0x4ac00000 0x0 0x00400000>; + }; + }; + diff --git a/target/linux/qualcommax/patches-6.1/0040-v6.5-arm64-dts-qcom-enable-the-download-mode-support.patch b/target/linux/qualcommax/patches-6.1/0040-v6.5-arm64-dts-qcom-enable-the-download-mode-support.patch new file mode 100644 index 000000000..f9687994e --- /dev/null +++ b/target/linux/qualcommax/patches-6.1/0040-v6.5-arm64-dts-qcom-enable-the-download-mode-support.patch @@ -0,0 +1,49 @@ +From 9b2406aaba7841863ac041225316c1ec1c86ea36 Mon Sep 17 00:00:00 2001 +From: Vignesh Viswanathan +Date: Fri, 26 May 2023 16:36:52 +0530 +Subject: [PATCH] arm64: dts: qcom: enable the download mode support + +Like any other Qualcomm SoCs, IPQ8074 and IPQ6018 also supports the +download mode to collect the RAM dumps if system crashes, to perform +the post mortem analysis. Add support for the same. + +Signed-off-by: Vignesh Viswanathan +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20230526110653.27777-3-quic_viswanat@quicinc.com +--- + arch/arm64/boot/dts/qcom/ipq6018.dtsi | 1 + + arch/arm64/boot/dts/qcom/ipq8074.dtsi | 6 ++++++ + 2 files changed, 7 insertions(+) + +--- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi ++++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi +@@ -90,6 +90,7 @@ + firmware { + scm { + compatible = "qcom,scm-ipq6018", "qcom,scm"; ++ qcom,dload-mode = <&tcsr 0x6100>; + }; + }; + +--- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi ++++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi +@@ -112,6 +112,7 @@ + firmware { + scm { + compatible = "qcom,scm-ipq8074", "qcom,scm"; ++ qcom,dload-mode = <&tcsr 0x6100>; + }; + }; + +@@ -384,6 +385,11 @@ + #hwlock-cells = <1>; + }; + ++ tcsr: syscon@1937000 { ++ compatible = "qcom,tcsr-ipq8074", "syscon"; ++ reg = <0x01937000 0x21000>; ++ }; ++ + spmi_bus: spmi@200f000 { + compatible = "qcom,spmi-pmic-arb"; + reg = <0x0200f000 0x001000>, diff --git a/target/linux/qualcommax/patches-6.1/0041-v6.5-arm64-dts-qcom-ipq6018-correct-qrng-unit-address.patch b/target/linux/qualcommax/patches-6.1/0041-v6.5-arm64-dts-qcom-ipq6018-correct-qrng-unit-address.patch new file mode 100644 index 000000000..e9b92b596 --- /dev/null +++ b/target/linux/qualcommax/patches-6.1/0041-v6.5-arm64-dts-qcom-ipq6018-correct-qrng-unit-address.patch @@ -0,0 +1,29 @@ +From 085058786a7890dd44ec623fe5ac74db870f6b93 Mon Sep 17 00:00:00 2001 +From: Krzysztof Kozlowski +Date: Wed, 19 Apr 2023 23:18:39 +0200 +Subject: [PATCH] arm64: dts: qcom: ipq6018: correct qrng unit address + +Match unit-address to reg entry to fix dtbs W=1 warnings: + + Warning (simple_bus_reg): /soc/qrng@e1000: simple-bus unit address format error, expected "e3000" + +Fixes: 5bf635621245 ("arm64: dts: ipq6018: Add a few device nodes") +Signed-off-by: Krzysztof Kozlowski +Reviewed-by: Konrad Dybcio +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20230419211856.79332-1-krzysztof.kozlowski@linaro.org +--- + arch/arm64/boot/dts/qcom/ipq6018.dtsi | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi ++++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi +@@ -312,7 +312,7 @@ + status = "disabled"; + }; + +- prng: qrng@e1000 { ++ prng: qrng@e3000 { + compatible = "qcom,prng-ee"; + reg = <0x0 0x000e3000 0x0 0x1000>; + clocks = <&gcc GCC_PRNG_AHB_CLK>; diff --git a/target/linux/qualcommax/patches-6.1/0042-v6.5-arm64-dts-qcom-ipq6018-add-unit-address-to-soc-node.patch b/target/linux/qualcommax/patches-6.1/0042-v6.5-arm64-dts-qcom-ipq6018-add-unit-address-to-soc-node.patch new file mode 100644 index 000000000..821c9890c --- /dev/null +++ b/target/linux/qualcommax/patches-6.1/0042-v6.5-arm64-dts-qcom-ipq6018-add-unit-address-to-soc-node.patch @@ -0,0 +1,28 @@ +From 393595d4ffbd0a1fafd5548f8de1b8487a037cf2 Mon Sep 17 00:00:00 2001 +From: Krzysztof Kozlowski +Date: Thu, 20 Apr 2023 08:36:04 +0200 +Subject: [PATCH] arm64: dts: qcom: ipq6018: add unit address to soc node + +"soc" node is supposed to have unit address: + + Warning (unit_address_vs_reg): /soc: node has a reg or ranges property, but no unit name + +Signed-off-by: Krzysztof Kozlowski +Reviewed-by: Konrad Dybcio +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20230420063610.11068-1-krzysztof.kozlowski@linaro.org +--- + arch/arm64/boot/dts/qcom/ipq6018.dtsi | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi ++++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi +@@ -209,7 +209,7 @@ + hwlocks = <&tcsr_mutex 3>; + }; + +- soc: soc { ++ soc: soc@0 { + #address-cells = <2>; + #size-cells = <2>; + ranges = <0 0 0 0 0x0 0xffffffff>; diff --git a/target/linux/qualcommax/patches-6.1/0043-v6.5-arm64-dts-qcom-ipq6018-add-QFPROM-node.patch b/target/linux/qualcommax/patches-6.1/0043-v6.5-arm64-dts-qcom-ipq6018-add-QFPROM-node.patch new file mode 100644 index 000000000..68895c5c9 --- /dev/null +++ b/target/linux/qualcommax/patches-6.1/0043-v6.5-arm64-dts-qcom-ipq6018-add-QFPROM-node.patch @@ -0,0 +1,34 @@ +From 546f0617a22a481f3ca1f7e058aea0c40517c64e Mon Sep 17 00:00:00 2001 +From: Kathiravan T +Date: Fri, 26 May 2023 18:23:04 +0530 +Subject: [PATCH] arm64: dts: qcom: ipq6018: add QFPROM node + +IPQ6018 has efuse region to determine the various HW quirks. Lets +add the initial support and the individual fuses will be added as they +are required. + +Signed-off-by: Kathiravan T +Reviewed-by: Dmitry Baryshkov +Reviewed-by: Konrad Dybcio +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20230526125305.19626-4-quic_kathirav@quicinc.com +--- + arch/arm64/boot/dts/qcom/ipq6018.dtsi | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi ++++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi +@@ -312,6 +312,13 @@ + status = "disabled"; + }; + ++ qfprom: efuse@a4000 { ++ compatible = "qcom,ipq6018-qfprom", "qcom,qfprom"; ++ reg = <0x0 0x000a4000 0x0 0x2000>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ }; ++ + prng: qrng@e3000 { + compatible = "qcom,prng-ee"; + reg = <0x0 0x000e3000 0x0 0x1000>; diff --git a/target/linux/qualcommax/patches-6.1/0044-v6.5-arm64-dts-qcom-ipq6018-drop-incorrect-SPI-bus.patch b/target/linux/qualcommax/patches-6.1/0044-v6.5-arm64-dts-qcom-ipq6018-drop-incorrect-SPI-bus.patch new file mode 100644 index 000000000..b2057e588 --- /dev/null +++ b/target/linux/qualcommax/patches-6.1/0044-v6.5-arm64-dts-qcom-ipq6018-drop-incorrect-SPI-bus.patch @@ -0,0 +1,37 @@ +From b8420d478aa3fc739fcdba6b4b945850b356cb3b Mon Sep 17 00:00:00 2001 +From: Krzysztof Kozlowski +Date: Sun, 16 Apr 2023 14:37:25 +0200 +Subject: [PATCH] arm64: dts: qcom: ipq6018: drop incorrect SPI bus + spi-max-frequency + +The spi-max-frequency property belongs to SPI devices, not SPI +controller: + + ipq6018-cp01-c1.dtb: spi@78b5000: Unevaluated properties are not allowed ('spi-max-frequency' was unexpected) + +Signed-off-by: Krzysztof Kozlowski +Reviewed-by: Konrad Dybcio +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20230416123730.300863-1-krzysztof.kozlowski@linaro.org +--- + arch/arm64/boot/dts/qcom/ipq6018.dtsi | 2 -- + 1 file changed, 2 deletions(-) + +--- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi ++++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi +@@ -458,7 +458,6 @@ + #size-cells = <0>; + reg = <0x0 0x078b5000 0x0 0x600>; + interrupts = ; +- spi-max-frequency = <50000000>; + clocks = <&gcc GCC_BLSP1_QUP1_SPI_APPS_CLK>, + <&gcc GCC_BLSP1_AHB_CLK>; + clock-names = "core", "iface"; +@@ -473,7 +472,6 @@ + #size-cells = <0>; + reg = <0x0 0x078b6000 0x0 0x600>; + interrupts = ; +- spi-max-frequency = <50000000>; + clocks = <&gcc GCC_BLSP1_QUP2_SPI_APPS_CLK>, + <&gcc GCC_BLSP1_AHB_CLK>; + clock-names = "core", "iface"; diff --git a/target/linux/qualcommax/patches-6.1/0045-v6.5-arm64-dts-qcom-ipq8074-drop-incorrect-SPI-bus.patch b/target/linux/qualcommax/patches-6.1/0045-v6.5-arm64-dts-qcom-ipq8074-drop-incorrect-SPI-bus.patch new file mode 100644 index 000000000..45861e192 --- /dev/null +++ b/target/linux/qualcommax/patches-6.1/0045-v6.5-arm64-dts-qcom-ipq8074-drop-incorrect-SPI-bus.patch @@ -0,0 +1,29 @@ +From e6e0e706940b64e3a77e0a4840037692f109bd5f Mon Sep 17 00:00:00 2001 +From: Krzysztof Kozlowski +Date: Sun, 16 Apr 2023 14:37:26 +0200 +Subject: [PATCH] arm64: dts: qcom: ipq8074: drop incorrect SPI bus + spi-max-frequency + +The spi-max-frequency property belongs to SPI devices, not SPI +controller: + + ipq8074-hk01.dtb: spi@78b5000: Unevaluated properties are not allowed ('spi-max-frequency' was unexpected) + +Signed-off-by: Krzysztof Kozlowski +Reviewed-by: Konrad Dybcio +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20230416123730.300863-2-krzysztof.kozlowski@linaro.org +--- + arch/arm64/boot/dts/qcom/ipq8074.dtsi | 1 - + 1 file changed, 1 deletion(-) + +--- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi ++++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi +@@ -485,7 +485,6 @@ + #size-cells = <0>; + reg = <0x078b5000 0x600>; + interrupts = ; +- spi-max-frequency = <50000000>; + clocks = <&gcc GCC_BLSP1_QUP1_SPI_APPS_CLK>, + <&gcc GCC_BLSP1_AHB_CLK>; + clock-names = "core", "iface"; diff --git a/target/linux/qualcommax/patches-6.1/0046-v6.6-clk-qcom-gcc-ipq6018-Use-floor-ops-for-sdcc-clocks.patch b/target/linux/qualcommax/patches-6.1/0046-v6.6-clk-qcom-gcc-ipq6018-Use-floor-ops-for-sdcc-clocks.patch new file mode 100644 index 000000000..9ae72730d --- /dev/null +++ b/target/linux/qualcommax/patches-6.1/0046-v6.6-clk-qcom-gcc-ipq6018-Use-floor-ops-for-sdcc-clocks.patch @@ -0,0 +1,27 @@ +From 56e5ae0116aef87273cf1812d608645b076e4f02 Mon Sep 17 00:00:00 2001 +From: Mantas Pucka +Date: Tue, 25 Apr 2023 12:11:49 +0300 +Subject: [PATCH] clk: qcom: gcc-ipq6018: Use floor ops for sdcc clocks + +SDCC clocks must be rounded down to avoid overclocking the controller. + +Fixes: d9db07f088af ("clk: qcom: Add ipq6018 Global Clock Controller support") +Signed-off-by: Mantas Pucka +Reviewed-by: Konrad Dybcio +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/1682413909-24927-1-git-send-email-mantas@8devices.com +--- + drivers/clk/qcom/gcc-ipq6018.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/clk/qcom/gcc-ipq6018.c ++++ b/drivers/clk/qcom/gcc-ipq6018.c +@@ -1702,7 +1702,7 @@ static struct clk_rcg2 usb0_mock_utmi_cl + .name = "usb0_mock_utmi_clk_src", + .parent_data = gcc_xo_gpll6_gpll0_gpll0_out_main_div2, + .num_parents = 4, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_rcg2_floor_ops, + }, + }; + diff --git a/target/linux/qualcommax/patches-6.1/0047-v6.6-clk-qcom-gcc-ipq6018-drop-redundant-F-define.patch b/target/linux/qualcommax/patches-6.1/0047-v6.6-clk-qcom-gcc-ipq6018-drop-redundant-F-define.patch new file mode 100644 index 000000000..19dc9482e --- /dev/null +++ b/target/linux/qualcommax/patches-6.1/0047-v6.6-clk-qcom-gcc-ipq6018-drop-redundant-F-define.patch @@ -0,0 +1,27 @@ +From 923f7d678b2ae3d522543058514d5605c185633b Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Mon, 17 Apr 2023 19:44:07 +0200 +Subject: [PATCH] clk: qcom: gcc-ipq6018: drop redundant F define + +The same exact F frequency table entry is defined in clk-rcg.h +Drop the redundant define to cleanup code. + +Signed-off-by: Christian Marangi +Reviewed-by: Konrad Dybcio +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20230417174408.23722-1-ansuelsmth@gmail.com +--- + drivers/clk/qcom/gcc-ipq6018.c | 2 -- + 1 file changed, 2 deletions(-) + +--- a/drivers/clk/qcom/gcc-ipq6018.c ++++ b/drivers/clk/qcom/gcc-ipq6018.c +@@ -26,8 +26,6 @@ + #include "clk-regmap-mux.h" + #include "reset.h" + +-#define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) } +- + enum { + P_XO, + P_BIAS_PLL, diff --git a/target/linux/qualcommax/patches-6.1/0048-v6.6-clk-qcom-gcc-ipq6018-update-UBI32-PLL.patch b/target/linux/qualcommax/patches-6.1/0048-v6.6-clk-qcom-gcc-ipq6018-update-UBI32-PLL.patch new file mode 100644 index 000000000..e38b40278 --- /dev/null +++ b/target/linux/qualcommax/patches-6.1/0048-v6.6-clk-qcom-gcc-ipq6018-update-UBI32-PLL.patch @@ -0,0 +1,39 @@ +From f4f0c8acee0e41c5fbae7a7ad06087668ddce0d6 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Fri, 26 May 2023 21:08:54 +0200 +Subject: [PATCH] clk: qcom: gcc-ipq6018: update UBI32 PLL + +Update the UBI32 alpha PLL config to the latest values from the downstream +QCA 5.4 kernel. + +Signed-off-by: Robert Marko +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20230526190855.2941291-1-robimarko@gmail.com +--- + drivers/clk/qcom/gcc-ipq6018.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +--- a/drivers/clk/qcom/gcc-ipq6018.c ++++ b/drivers/clk/qcom/gcc-ipq6018.c +@@ -4143,15 +4143,20 @@ static struct clk_branch gcc_dcc_clk = { + + static const struct alpha_pll_config ubi32_pll_config = { + .l = 0x3e, +- .alpha = 0x57, ++ .alpha = 0x6667, + .config_ctl_val = 0x240d6aa8, + .config_ctl_hi_val = 0x3c2, ++ .config_ctl_val = 0x240d4828, ++ .config_ctl_hi_val = 0x6, + .main_output_mask = BIT(0), + .aux_output_mask = BIT(1), + .pre_div_val = 0x0, + .pre_div_mask = BIT(12), + .post_div_val = 0x0, + .post_div_mask = GENMASK(9, 8), ++ .alpha_en_mask = BIT(24), ++ .test_ctl_val = 0x1C0000C0, ++ .test_ctl_hi_val = 0x4000, + }; + + static const struct alpha_pll_config nss_crypto_pll_config = { diff --git a/target/linux/qualcommax/patches-6.1/0049-v6.6-clk-qcom-gcc-ipq6018-remove-duplicate-initializers.patch b/target/linux/qualcommax/patches-6.1/0049-v6.6-clk-qcom-gcc-ipq6018-remove-duplicate-initializers.patch new file mode 100644 index 000000000..e4faac1b6 --- /dev/null +++ b/target/linux/qualcommax/patches-6.1/0049-v6.6-clk-qcom-gcc-ipq6018-remove-duplicate-initializers.patch @@ -0,0 +1,38 @@ +From 5ae7899765607e97e5eb34486336898c8d9ec654 Mon Sep 17 00:00:00 2001 +From: Arnd Bergmann +Date: Thu, 1 Jun 2023 23:34:12 +0200 +Subject: [PATCH] clk: qcom: gcc-ipq6018: remove duplicate initializers + +A recent change added new initializers for .config_ctl_val and +.config_ctl_hi_val but left the old values in place: + +drivers/clk/qcom/gcc-ipq6018.c:4155:27: error: initialized field overwritten [-Werror=override-init] + 4155 | .config_ctl_val = 0x240d4828, + | ^~~~~~~~~~ +drivers/clk/qcom/gcc-ipq6018.c:4156:30: error: initialized field overwritten [-Werror=override-init] + 4156 | .config_ctl_hi_val = 0x6, + | ^~~ + +Remove the unused ones now to avoid confusion. + +Fixes: f4f0c8acee0e4 ("clk: qcom: gcc-ipq6018: update UBI32 PLL") +Signed-off-by: Arnd Bergmann +Reviewed-by: Robert Marko +Reviewed-by: Dmitry Baryshkov +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20230601213416.3373599-1-arnd@kernel.org +--- + drivers/clk/qcom/gcc-ipq6018.c | 2 -- + 1 file changed, 2 deletions(-) + +--- a/drivers/clk/qcom/gcc-ipq6018.c ++++ b/drivers/clk/qcom/gcc-ipq6018.c +@@ -4144,8 +4144,6 @@ static struct clk_branch gcc_dcc_clk = { + static const struct alpha_pll_config ubi32_pll_config = { + .l = 0x3e, + .alpha = 0x6667, +- .config_ctl_val = 0x240d6aa8, +- .config_ctl_hi_val = 0x3c2, + .config_ctl_val = 0x240d4828, + .config_ctl_hi_val = 0x6, + .main_output_mask = BIT(0), diff --git a/target/linux/qualcommax/patches-6.1/0050-v6.6-soc-qcom-Add-RPM-processor-subsystem-driver.patch b/target/linux/qualcommax/patches-6.1/0050-v6.6-soc-qcom-Add-RPM-processor-subsystem-driver.patch new file mode 100644 index 000000000..c2c26fb07 --- /dev/null +++ b/target/linux/qualcommax/patches-6.1/0050-v6.6-soc-qcom-Add-RPM-processor-subsystem-driver.patch @@ -0,0 +1,132 @@ +From 8ddfa81d090c71fd6cb3cb8ca1d420c0da33a575 Mon Sep 17 00:00:00 2001 +From: Stephan Gerhold +Date: Thu, 15 Jun 2023 18:50:42 +0200 +Subject: [PATCH] soc: qcom: Add RPM processor/subsystem driver + +Add a simple driver for the qcom,rpm-proc compatible that registers the +"smd-edge" and populates other children defined in the device tree. + +Note that the DT schema belongs to the remoteproc subsystem while this +driver is added inside soc/qcom. I argue that the RPM *is* a remoteproc, +but as an implementation detail in Linux it can currently not benefit +from anything provided by the remoteproc subsystem. The RPM firmware is +usually already loaded and started by earlier components in the boot +chain and is not meant to be ever restarted. + +To avoid breaking existing kernel configurations the driver is always +built when smd-rpm.c is also built. They belong closely together anyway. +To avoid build errors CONFIG_RPMSG_QCOM_SMD must be also built-in if +rpm-proc is. + +Reviewed-by: Konrad Dybcio +Signed-off-by: Stephan Gerhold +Link: https://lore.kernel.org/r/20230531-rpm-rproc-v3-9-a07dcdefd918@gerhold.net +Signed-off-by: Bjorn Andersson +--- + drivers/soc/qcom/Kconfig | 1 + + drivers/soc/qcom/Makefile | 2 +- + drivers/soc/qcom/rpm-proc.c | 77 +++++++++++++++++++++++++++++++++++++ + 3 files changed, 79 insertions(+), 1 deletion(-) + create mode 100644 drivers/soc/qcom/rpm-proc.c + +--- a/drivers/soc/qcom/Kconfig ++++ b/drivers/soc/qcom/Kconfig +@@ -153,6 +153,7 @@ config QCOM_SMD_RPM + tristate "Qualcomm Resource Power Manager (RPM) over SMD" + depends on ARCH_QCOM || COMPILE_TEST + depends on RPMSG ++ depends on RPMSG_QCOM_SMD || RPMSG_QCOM_SMD=n + help + If you say yes to this option, support will be included for the + Resource Power Manager system found in the Qualcomm 8974 based +--- a/drivers/soc/qcom/Makefile ++++ b/drivers/soc/qcom/Makefile +@@ -14,7 +14,7 @@ obj-$(CONFIG_QCOM_RMTFS_MEM) += rmtfs_me + obj-$(CONFIG_QCOM_RPMH) += qcom_rpmh.o + qcom_rpmh-y += rpmh-rsc.o + qcom_rpmh-y += rpmh.o +-obj-$(CONFIG_QCOM_SMD_RPM) += smd-rpm.o ++obj-$(CONFIG_QCOM_SMD_RPM) += rpm-proc.o smd-rpm.o + obj-$(CONFIG_QCOM_SMEM) += smem.o + obj-$(CONFIG_QCOM_SMEM_STATE) += smem_state.o + obj-$(CONFIG_QCOM_SMP2P) += smp2p.o +--- /dev/null ++++ b/drivers/soc/qcom/rpm-proc.c +@@ -0,0 +1,77 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* Copyright (c) 2021-2023, Stephan Gerhold */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++static int rpm_proc_probe(struct platform_device *pdev) ++{ ++ struct qcom_smd_edge *edge = NULL; ++ struct device *dev = &pdev->dev; ++ struct device_node *edge_node; ++ int ret; ++ ++ edge_node = of_get_child_by_name(dev->of_node, "smd-edge"); ++ if (edge_node) { ++ edge = qcom_smd_register_edge(dev, edge_node); ++ of_node_put(edge_node); ++ if (IS_ERR(edge)) ++ return dev_err_probe(dev, PTR_ERR(edge), ++ "Failed to register smd-edge\n"); ++ } ++ ++ ret = devm_of_platform_populate(dev); ++ if (ret) { ++ dev_err(dev, "Failed to populate child devices: %d\n", ret); ++ goto err; ++ } ++ ++ platform_set_drvdata(pdev, edge); ++ return 0; ++err: ++ if (edge) ++ qcom_smd_unregister_edge(edge); ++ return ret; ++} ++ ++static void rpm_proc_remove(struct platform_device *pdev) ++{ ++ struct qcom_smd_edge *edge = platform_get_drvdata(pdev); ++ ++ if (edge) ++ qcom_smd_unregister_edge(edge); ++} ++ ++static const struct of_device_id rpm_proc_of_match[] = { ++ { .compatible = "qcom,rpm-proc", }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, rpm_proc_of_match); ++ ++static struct platform_driver rpm_proc_driver = { ++ .probe = rpm_proc_probe, ++ .remove_new = rpm_proc_remove, ++ .driver = { ++ .name = "qcom-rpm-proc", ++ .of_match_table = rpm_proc_of_match, ++ }, ++}; ++ ++static int __init rpm_proc_init(void) ++{ ++ return platform_driver_register(&rpm_proc_driver); ++} ++arch_initcall(rpm_proc_init); ++ ++static void __exit rpm_proc_exit(void) ++{ ++ platform_driver_unregister(&rpm_proc_driver); ++} ++module_exit(rpm_proc_exit); ++ ++MODULE_DESCRIPTION("Qualcomm RPM processor/subsystem driver"); ++MODULE_AUTHOR("Stephan Gerhold "); ++MODULE_LICENSE("GPL"); diff --git a/target/linux/qualcommax/patches-6.1/0051-v6.6-arm64-dts-qcom-Add-rpm-proc-node-for-GLINK.patch b/target/linux/qualcommax/patches-6.1/0051-v6.6-arm64-dts-qcom-Add-rpm-proc-node-for-GLINK.patch new file mode 100644 index 000000000..746a391b4 --- /dev/null +++ b/target/linux/qualcommax/patches-6.1/0051-v6.6-arm64-dts-qcom-Add-rpm-proc-node-for-GLINK.patch @@ -0,0 +1,93 @@ +From 7e1acc8b92a3b67db1e5255adae2851d58d74434 Mon Sep 17 00:00:00 2001 +From: Stephan Gerhold +Date: Thu, 15 Jun 2023 18:50:44 +0200 +Subject: [PATCH] arm64: dts: qcom: Add rpm-proc node for GLINK gplatforms + +Rather than having the RPM GLINK channels as the only child of a dummy +top-level rpm-glink node, switch to representing the RPM as remoteproc +like all the other remoteprocs (modem DSP, ...). + +This allows assigning additional subdevices to it like the MPM +interrupt-controller or rpm-master-stats. + +Tested-by: Konrad Dybcio # SM6375 +Signed-off-by: Stephan Gerhold +Link: https://lore.kernel.org/r/20230531-rpm-rproc-v3-11-a07dcdefd918@gerhold.net +Signed-off-by: Bjorn Andersson +--- + arch/arm64/boot/dts/qcom/ipq6018.dtsi | 48 ++++---- + arch/arm64/boot/dts/qcom/ipq9574.dtsi | 28 +++-- + arch/arm64/boot/dts/qcom/msm8996.dtsi | 113 +++++++++---------- + arch/arm64/boot/dts/qcom/msm8998.dtsi | 102 ++++++++--------- + arch/arm64/boot/dts/qcom/qcm2290.dtsi | 126 ++++++++++----------- + arch/arm64/boot/dts/qcom/qcs404.dtsi | 152 +++++++++++++------------- + arch/arm64/boot/dts/qcom/sdm630.dtsi | 132 +++++++++++----------- + arch/arm64/boot/dts/qcom/sm6115.dtsi | 128 +++++++++++----------- + arch/arm64/boot/dts/qcom/sm6125.dtsi | 140 ++++++++++++------------ + arch/arm64/boot/dts/qcom/sm6375.dtsi | 126 ++++++++++----------- + 10 files changed, 566 insertions(+), 529 deletions(-) + +--- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi ++++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi +@@ -145,6 +145,32 @@ + method = "smc"; + }; + ++ rpm: remoteproc { ++ compatible = "qcom,ipq6018-rpm-proc", "qcom,rpm-proc"; ++ ++ glink-edge { ++ compatible = "qcom,glink-rpm"; ++ interrupts = ; ++ qcom,rpm-msg-ram = <&rpm_msg_ram>; ++ mboxes = <&apcs_glb 0>; ++ ++ rpm_requests: rpm-requests { ++ compatible = "qcom,rpm-ipq6018"; ++ qcom,glink-channels = "rpm_requests"; ++ ++ regulators { ++ compatible = "qcom,rpm-mp5496-regulators"; ++ ++ ipq6018_s2: s2 { ++ regulator-min-microvolt = <725000>; ++ regulator-max-microvolt = <1062500>; ++ regulator-always-on; ++ }; ++ }; ++ }; ++ }; ++ }; ++ + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; +@@ -181,28 +207,6 @@ + }; + }; + +- rpm-glink { +- compatible = "qcom,glink-rpm"; +- interrupts = ; +- qcom,rpm-msg-ram = <&rpm_msg_ram>; +- mboxes = <&apcs_glb 0>; +- +- rpm_requests: rpm-requests { +- compatible = "qcom,rpm-ipq6018"; +- qcom,glink-channels = "rpm_requests"; +- +- regulators { +- compatible = "qcom,rpm-mp5496-regulators"; +- +- ipq6018_s2: s2 { +- regulator-min-microvolt = <725000>; +- regulator-max-microvolt = <1062500>; +- regulator-always-on; +- }; +- }; +- }; +- }; +- + smem { + compatible = "qcom,smem"; + memory-region = <&smem_region>; diff --git a/target/linux/qualcommax/patches-6.1/0052-v6.7-arm64-dts-qcom-ipq6018-include-the-GPLL0-as.patch b/target/linux/qualcommax/patches-6.1/0052-v6.7-arm64-dts-qcom-ipq6018-include-the-GPLL0-as.patch new file mode 100644 index 000000000..b70d7bf69 --- /dev/null +++ b/target/linux/qualcommax/patches-6.1/0052-v6.7-arm64-dts-qcom-ipq6018-include-the-GPLL0-as.patch @@ -0,0 +1,35 @@ +From 0133c7af3aa0420778d106cb90db708cfa45f2c6 Mon Sep 17 00:00:00 2001 +From: Kathiravan Thirumoorthy +Date: Thu, 14 Sep 2023 12:29:59 +0530 +Subject: [PATCH] arm64: dts: qcom: ipq6018: include the GPLL0 as clock + provider for mailbox + +While the kernel is booting up, APSS clock / CPU clock will be running +at 800MHz with GPLL0 as source. Once the cpufreq driver is available, +APSS PLL will be configured to the rate based on the opp table and the +source also will be changed to APSS_PLL_EARLY. So allow the mailbox to +consume the GPLL0, with this inclusion, CPU Freq correctly reports that +CPU is running at 800MHz rather than 24MHz. + +Signed-off-by: Kathiravan Thirumoorthy +Reviewed-by: Konrad Dybcio +Link: https://lore.kernel.org/r/20230913-gpll_cleanup-v2-9-c8ceb1a37680@quicinc.com +[bjorn: Updated commit message, as requested by Kathiravan] +Signed-off-by: Bjorn Andersson +--- + arch/arm64/boot/dts/qcom/ipq6018.dtsi | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi ++++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi +@@ -618,8 +618,8 @@ + compatible = "qcom,ipq6018-apcs-apps-global"; + reg = <0x0 0x0b111000 0x0 0x1000>; + #clock-cells = <1>; +- clocks = <&a53pll>, <&xo>; +- clock-names = "pll", "xo"; ++ clocks = <&a53pll>, <&xo>, <&gcc GPLL0>; ++ clock-names = "pll", "xo", "gpll0"; + #mbox-cells = <1>; + }; + diff --git a/target/linux/qualcommax/patches-6.1/0053-v6.7-clk-qcom-gcc-ipq6018-add-QUP6-I2C-clock.patch b/target/linux/qualcommax/patches-6.1/0053-v6.7-clk-qcom-gcc-ipq6018-add-QUP6-I2C-clock.patch new file mode 100644 index 000000000..085852893 --- /dev/null +++ b/target/linux/qualcommax/patches-6.1/0053-v6.7-clk-qcom-gcc-ipq6018-add-QUP6-I2C-clock.patch @@ -0,0 +1,57 @@ +From 3dcf7b59393812a5fbd83f8cd8d34b94afb4c4d1 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Sat, 21 Oct 2023 13:55:18 +0200 +Subject: [PATCH] clk: qcom: gcc-ipq6018: add QUP6 I2C clock + +QUP6 I2C clock is listed in the dt bindings but it was never included in +the GCC driver. +So lets add support for it, it is marked as criticial as it is used by RPM +to communicate to the external PMIC over I2C so this clock must not be +disabled. + +Signed-off-by: Robert Marko +Reviewed-by: Kathiravan Thirumoorthy +Reviewed-by: Konrad Dybcio +Link: https://lore.kernel.org/r/20231021115545.229060-1-robimarko@gmail.com +Signed-off-by: Bjorn Andersson +--- + drivers/clk/qcom/gcc-ipq6018.c | 21 +++++++++++++++++++++ + 1 file changed, 21 insertions(+) + +--- a/drivers/clk/qcom/gcc-ipq6018.c ++++ b/drivers/clk/qcom/gcc-ipq6018.c +@@ -2120,6 +2120,26 @@ static struct clk_branch gcc_blsp1_qup5_ + }, + }; + ++static struct clk_branch gcc_blsp1_qup6_i2c_apps_clk = { ++ .halt_reg = 0x07010, ++ .clkr = { ++ .enable_reg = 0x07010, ++ .enable_mask = BIT(0), ++ .hw.init = &(struct clk_init_data){ ++ .name = "gcc_blsp1_qup6_i2c_apps_clk", ++ .parent_hws = (const struct clk_hw *[]){ ++ &blsp1_qup6_i2c_apps_clk_src.clkr.hw }, ++ .num_parents = 1, ++ /* ++ * RPM uses QUP6 I2C to communicate with the external ++ * PMIC so it must not be disabled. ++ */ ++ .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, ++ .ops = &clk_branch2_ops, ++ }, ++ }, ++}; ++ + static struct clk_branch gcc_blsp1_qup6_spi_apps_clk = { + .halt_reg = 0x0700c, + .clkr = { +@@ -4276,6 +4296,7 @@ static struct clk_regmap *gcc_ipq6018_cl + [GCC_BLSP1_QUP4_SPI_APPS_CLK] = &gcc_blsp1_qup4_spi_apps_clk.clkr, + [GCC_BLSP1_QUP5_I2C_APPS_CLK] = &gcc_blsp1_qup5_i2c_apps_clk.clkr, + [GCC_BLSP1_QUP5_SPI_APPS_CLK] = &gcc_blsp1_qup5_spi_apps_clk.clkr, ++ [GCC_BLSP1_QUP6_I2C_APPS_CLK] = &gcc_blsp1_qup6_i2c_apps_clk.clkr, + [GCC_BLSP1_QUP6_SPI_APPS_CLK] = &gcc_blsp1_qup6_spi_apps_clk.clkr, + [GCC_BLSP1_UART1_APPS_CLK] = &gcc_blsp1_uart1_apps_clk.clkr, + [GCC_BLSP1_UART2_APPS_CLK] = &gcc_blsp1_uart2_apps_clk.clkr, diff --git a/target/linux/qualcommax/patches-6.1/0054-v6.8-arm64-dts-qcom-ipq6018-use-CPUFreq-NVMEM.patch b/target/linux/qualcommax/patches-6.1/0054-v6.8-arm64-dts-qcom-ipq6018-use-CPUFreq-NVMEM.patch new file mode 100644 index 000000000..1369a90a8 --- /dev/null +++ b/target/linux/qualcommax/patches-6.1/0054-v6.8-arm64-dts-qcom-ipq6018-use-CPUFreq-NVMEM.patch @@ -0,0 +1,85 @@ +From 83afcf14edb9217e58837eb119da96d734a4b3b1 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Sat, 21 Oct 2023 14:00:07 +0200 +Subject: [PATCH] arm64: dts: qcom: ipq6018: use CPUFreq NVMEM + +IPQ6018 comes in multiple SKU-s and some of them dont support all of the +OPP-s that are current set, so lets utilize CPUFreq NVMEM to allow only +supported OPP-s based on the SoC dynamically. + +As an example, IPQ6018 is generaly rated at 1.8GHz but some silicon only +goes up to 1.5GHz and is marked as such via an eFuse. + +Signed-off-by: Robert Marko +Reviewed-by: Konrad Dybcio +Link: https://lore.kernel.org/r/20231021120048.231239-1-robimarko@gmail.com +Signed-off-by: Bjorn Andersson +--- + arch/arm64/boot/dts/qcom/ipq6018.dtsi | 14 +++++++++++++- + 1 file changed, 13 insertions(+), 1 deletion(-) + +--- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi ++++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi +@@ -95,42 +95,49 @@ + }; + + cpu_opp_table: opp-table-cpu { +- compatible = "operating-points-v2"; ++ compatible = "operating-points-v2-kryo-cpu"; ++ nvmem-cells = <&cpu_speed_bin>; + opp-shared; + + opp-864000000 { + opp-hz = /bits/ 64 <864000000>; + opp-microvolt = <725000>; ++ opp-supported-hw = <0xf>; + clock-latency-ns = <200000>; + }; + + opp-1056000000 { + opp-hz = /bits/ 64 <1056000000>; + opp-microvolt = <787500>; ++ opp-supported-hw = <0xf>; + clock-latency-ns = <200000>; + }; + + opp-1320000000 { + opp-hz = /bits/ 64 <1320000000>; + opp-microvolt = <862500>; ++ opp-supported-hw = <0x3>; + clock-latency-ns = <200000>; + }; + + opp-1440000000 { + opp-hz = /bits/ 64 <1440000000>; + opp-microvolt = <925000>; ++ opp-supported-hw = <0x3>; + clock-latency-ns = <200000>; + }; + + opp-1608000000 { + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <987500>; ++ opp-supported-hw = <0x1>; + clock-latency-ns = <200000>; + }; + + opp-1800000000 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <1062500>; ++ opp-supported-hw = <0x1>; + clock-latency-ns = <200000>; + }; + }; +@@ -321,6 +328,11 @@ + reg = <0x0 0x000a4000 0x0 0x2000>; + #address-cells = <1>; + #size-cells = <1>; ++ ++ cpu_speed_bin: cpu-speed-bin@135 { ++ reg = <0x135 0x1>; ++ bits = <7 1>; ++ }; + }; + + prng: qrng@e3000 { diff --git a/target/linux/qualcommax/patches-6.1/0102-arm64-dts-ipq8074-add-reserved-memory-nodes.patch b/target/linux/qualcommax/patches-6.1/0102-arm64-dts-ipq8074-add-reserved-memory-nodes.patch index af53c077f..3996d15d9 100644 --- a/target/linux/qualcommax/patches-6.1/0102-arm64-dts-ipq8074-add-reserved-memory-nodes.patch +++ b/target/linux/qualcommax/patches-6.1/0102-arm64-dts-ipq8074-add-reserved-memory-nodes.patch @@ -19,7 +19,7 @@ Signed-off-by: Robert Marko --- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi +++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -85,6 +85,26 @@ +@@ -85,6 +85,16 @@ #size-cells = <2>; ranges; @@ -33,22 +33,12 @@ Signed-off-by: Robert Marko + reg = <0x0 0x4a400000 0x0 0x00200000>; + }; + -+ uboot@4a600000 { -+ no-map; -+ reg = <0x0 0x4a600000 0x0 0x00400000>; -+ }; -+ -+ sbl@4aa00000 { -+ no-map; -+ reg = <0x0 0x4aa00000 0x0 0x00100000>; -+ }; -+ - smem@4ab00000 { - compatible = "qcom,smem"; - reg = <0x0 0x4ab00000 0x0 0x00100000>; -@@ -97,6 +117,21 @@ + bootloader@4a600000 { + reg = <0x0 0x4a600000 0x0 0x400000>; + no-map; +@@ -107,6 +117,21 @@ + reg = <0x0 0x4ac00000 0x0 0x400000>; no-map; - reg = <0x0 0x4ac00000 0x0 0x00400000>; }; + + q6_region: wcnss@4b000000 { diff --git a/target/linux/qualcommax/patches-6.1/0103-hwspinlock-qcom-Remove-IPQ6018-SOC-specific-.patch b/target/linux/qualcommax/patches-6.1/0103-hwspinlock-qcom-Remove-IPQ6018-SOC-specific-.patch new file mode 100644 index 000000000..c40330cfb --- /dev/null +++ b/target/linux/qualcommax/patches-6.1/0103-hwspinlock-qcom-Remove-IPQ6018-SOC-specific-.patch @@ -0,0 +1,30 @@ +From a120815200adaf3ac28ccf3a1813c78b4be02cc4 Mon Sep 17 00:00:00 2001 +From: Vignesh Viswanathan +Date: Tue, 5 Sep 2023 15:25:35 +0530 +Subject: [PATCH] hwspinlock: qcom: Remove IPQ6018 SOC specific compatible + +IPQ6018 has 32 tcsr_mutex hwlock registers with stride 0x1000. +The compatible string qcom,ipq6018-tcsr-mutex is mapped to +of_msm8226_tcsr_mutex which has 32 locks configured with stride of 0x80 +and doesn't match the HW present in IPQ6018. + +Remove IPQ6018 specific compatible string so that it fallsback to +of_tcsr_mutex data which maps to the correct configuration for IPQ6018. + +Cc: stable@vger.kernel.org +Fixes: 5d4753f741d8 ("hwspinlock: qcom: add support for MMIO on older SoCs") +Signed-off-by: Vignesh Viswanathan +--- + drivers/hwspinlock/qcom_hwspinlock.c | 1 - + 1 file changed, 1 deletion(-) + +--- a/drivers/hwspinlock/qcom_hwspinlock.c ++++ b/drivers/hwspinlock/qcom_hwspinlock.c +@@ -115,7 +115,6 @@ static const struct of_device_id qcom_hw + { .compatible = "qcom,sfpb-mutex", .data = &of_sfpb_mutex }, + { .compatible = "qcom,tcsr-mutex", .data = &of_tcsr_mutex }, + { .compatible = "qcom,apq8084-tcsr-mutex", .data = &of_msm8226_tcsr_mutex }, +- { .compatible = "qcom,ipq6018-tcsr-mutex", .data = &of_msm8226_tcsr_mutex }, + { .compatible = "qcom,msm8226-tcsr-mutex", .data = &of_msm8226_tcsr_mutex }, + { .compatible = "qcom,msm8974-tcsr-mutex", .data = &of_msm8226_tcsr_mutex }, + { .compatible = "qcom,msm8994-tcsr-mutex", .data = &of_msm8226_tcsr_mutex }, diff --git a/target/linux/qualcommax/patches-6.1/0104-pwm-driver-for-qualcomm-ipq6018-pwm-block.patch b/target/linux/qualcommax/patches-6.1/0104-pwm-driver-for-qualcomm-ipq6018-pwm-block.patch new file mode 100644 index 000000000..b47925f23 --- /dev/null +++ b/target/linux/qualcommax/patches-6.1/0104-pwm-driver-for-qualcomm-ipq6018-pwm-block.patch @@ -0,0 +1,337 @@ +From 823313068617bf2414c6067504b4e2ce5768e601 Mon Sep 17 00:00:00 2001 +From: Devi Priya +Date: Thu, 5 Oct 2023 21:35:47 +0530 +Subject: [PATCH] pwm: driver for qualcomm ipq6018 pwm block + +Driver for the PWM block in Qualcomm IPQ6018 line of SoCs. Based on +driver from downstream Codeaurora kernel tree. Removed support for +older (V1) variants because I have no access to that hardware. + +Tested on IPQ6010 based hardware. + +Co-developed-by: Baruch Siach +Signed-off-by: Baruch Siach +Signed-off-by: Devi Priya +--- + drivers/pwm/Kconfig | 12 ++ + drivers/pwm/Makefile | 1 + + drivers/pwm/pwm-ipq.c | 282 ++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 295 insertions(+) + create mode 100644 drivers/pwm/pwm-ipq.c + +--- a/drivers/pwm/Kconfig ++++ b/drivers/pwm/Kconfig +@@ -270,6 +270,18 @@ config PWM_INTEL_LGM + To compile this driver as a module, choose M here: the module + will be called pwm-intel-lgm. + ++config PWM_IPQ ++ tristate "IPQ PWM support" ++ depends on ARCH_QCOM || COMPILE_TEST ++ depends on HAVE_CLK && HAS_IOMEM ++ help ++ Generic PWM framework driver for IPQ PWM block which supports ++ 4 pwm channels. Each of the these channels can be configured ++ independent of each other. ++ ++ To compile this driver as a module, choose M here: the module ++ will be called pwm-ipq. ++ + config PWM_IQS620A + tristate "Azoteq IQS620A PWM support" + depends on MFD_IQS62X || COMPILE_TEST +--- a/drivers/pwm/Makefile ++++ b/drivers/pwm/Makefile +@@ -23,6 +23,7 @@ obj-$(CONFIG_PWM_IMX1) += pwm-imx1.o + obj-$(CONFIG_PWM_IMX27) += pwm-imx27.o + obj-$(CONFIG_PWM_IMX_TPM) += pwm-imx-tpm.o + obj-$(CONFIG_PWM_INTEL_LGM) += pwm-intel-lgm.o ++obj-$(CONFIG_PWM_IPQ) += pwm-ipq.o + obj-$(CONFIG_PWM_IQS620A) += pwm-iqs620a.o + obj-$(CONFIG_PWM_JZ4740) += pwm-jz4740.o + obj-$(CONFIG_PWM_KEEMBAY) += pwm-keembay.o +--- /dev/null ++++ b/drivers/pwm/pwm-ipq.c +@@ -0,0 +1,282 @@ ++// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 ++/* ++ * Copyright (c) 2016-2017, 2020 The Linux Foundation. All rights reserved. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* The frequency range supported is 1 Hz to clock rate */ ++#define IPQ_PWM_MAX_PERIOD_NS ((u64)NSEC_PER_SEC) ++ ++/* ++ * The max value specified for each field is based on the number of bits ++ * in the pwm control register for that field ++ */ ++#define IPQ_PWM_MAX_DIV 0xFFFF ++ ++/* ++ * Two 32-bit registers for each PWM: REG0, and REG1. ++ * Base offset for PWM #i is at 8 * #i. ++ */ ++#define IPQ_PWM_REG0 0 ++#define IPQ_PWM_REG0_PWM_DIV GENMASK(15, 0) ++#define IPQ_PWM_REG0_HI_DURATION GENMASK(31, 16) ++ ++#define IPQ_PWM_REG1 4 ++#define IPQ_PWM_REG1_PRE_DIV GENMASK(15, 0) ++/* ++ * Enable bit is set to enable output toggling in pwm device. ++ * Update bit is set to reflect the changed divider and high duration ++ * values in register. ++ */ ++#define IPQ_PWM_REG1_UPDATE BIT(30) ++#define IPQ_PWM_REG1_ENABLE BIT(31) ++ ++struct ipq_pwm_chip { ++ struct pwm_chip chip; ++ struct clk *clk; ++ void __iomem *mem; ++}; ++ ++static struct ipq_pwm_chip *ipq_pwm_from_chip(struct pwm_chip *chip) ++{ ++ return container_of(chip, struct ipq_pwm_chip, chip); ++} ++ ++static unsigned int ipq_pwm_reg_read(struct pwm_device *pwm, unsigned int reg) ++{ ++ struct ipq_pwm_chip *ipq_chip = ipq_pwm_from_chip(pwm->chip); ++ unsigned int off = 8 * pwm->hwpwm + reg; ++ ++ return readl(ipq_chip->mem + off); ++} ++ ++static void ipq_pwm_reg_write(struct pwm_device *pwm, unsigned int reg, ++ unsigned int val) ++{ ++ struct ipq_pwm_chip *ipq_chip = ipq_pwm_from_chip(pwm->chip); ++ unsigned int off = 8 * pwm->hwpwm + reg; ++ ++ writel(val, ipq_chip->mem + off); ++} ++ ++static void config_div_and_duty(struct pwm_device *pwm, unsigned int pre_div, ++ unsigned int pwm_div, unsigned long rate, u64 duty_ns, ++ bool enable) ++{ ++ unsigned long hi_dur; ++ unsigned long val = 0; ++ ++ /* ++ * high duration = pwm duty * (pwm div + 1) ++ * pwm duty = duty_ns / period_ns ++ */ ++ hi_dur = div64_u64(duty_ns * rate, (pre_div + 1) * NSEC_PER_SEC); ++ ++ val = FIELD_PREP(IPQ_PWM_REG0_HI_DURATION, hi_dur) | ++ FIELD_PREP(IPQ_PWM_REG0_PWM_DIV, pwm_div); ++ ipq_pwm_reg_write(pwm, IPQ_PWM_REG0, val); ++ ++ val = FIELD_PREP(IPQ_PWM_REG1_PRE_DIV, pre_div); ++ ipq_pwm_reg_write(pwm, IPQ_PWM_REG1, val); ++ ++ /* PWM enable toggle needs a separate write to REG1 */ ++ val |= IPQ_PWM_REG1_UPDATE; ++ if (enable) ++ val |= IPQ_PWM_REG1_ENABLE; ++ ipq_pwm_reg_write(pwm, IPQ_PWM_REG1, val); ++} ++ ++static int ipq_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, ++ const struct pwm_state *state) ++{ ++ struct ipq_pwm_chip *ipq_chip = ipq_pwm_from_chip(chip); ++ unsigned int pre_div, pwm_div, best_pre_div, best_pwm_div; ++ unsigned long rate = clk_get_rate(ipq_chip->clk); ++ u64 period_ns, duty_ns, period_rate; ++ u64 min_diff; ++ ++ if (state->polarity != PWM_POLARITY_NORMAL) ++ return -EINVAL; ++ ++ if (state->period < DIV64_U64_ROUND_UP(NSEC_PER_SEC, rate)) ++ return -ERANGE; ++ ++ period_ns = min(state->period, IPQ_PWM_MAX_PERIOD_NS); ++ duty_ns = min(state->duty_cycle, period_ns); ++ ++ /* ++ * period_ns is 1G or less. As long as rate is less than 16 GHz, ++ * period_rate does not overflow. Make that explicit. ++ */ ++ if ((unsigned long long)rate > 16ULL * GIGA) ++ return -EINVAL; ++ period_rate = period_ns * rate; ++ best_pre_div = IPQ_PWM_MAX_DIV; ++ best_pwm_div = IPQ_PWM_MAX_DIV; ++ /* ++ * We don't need to consider pre_div values smaller than ++ * ++ * period_rate ++ * pre_div_min := ------------------------------------ ++ * NSEC_PER_SEC * (IPQ_PWM_MAX_DIV + 1) ++ * ++ * because pre_div = pre_div_min results in a better ++ * approximation. ++ */ ++ pre_div = div64_u64(period_rate, ++ (u64)NSEC_PER_SEC * (IPQ_PWM_MAX_DIV + 1)); ++ min_diff = period_rate; ++ ++ for (; pre_div <= IPQ_PWM_MAX_DIV; pre_div++) { ++ u64 remainder; ++ ++ pwm_div = div64_u64_rem(period_rate, ++ (u64)NSEC_PER_SEC * (pre_div + 1), &remainder); ++ /* pwm_div is unsigned; the check below catches underflow */ ++ pwm_div--; ++ ++ /* ++ * Swapping values for pre_div and pwm_div produces the same ++ * period length. So we can skip all settings with pre_div > ++ * pwm_div which results in bigger constraints for selecting ++ * the duty_cycle than with the two values swapped. ++ */ ++ if (pre_div > pwm_div) ++ break; ++ ++ /* ++ * Make sure we can do 100% duty cycle where ++ * hi_dur == pwm_div + 1 ++ */ ++ if (pwm_div > IPQ_PWM_MAX_DIV - 1) ++ continue; ++ ++ if (remainder < min_diff) { ++ best_pre_div = pre_div; ++ best_pwm_div = pwm_div; ++ min_diff = remainder; ++ ++ if (min_diff == 0) /* bingo */ ++ break; ++ } ++ } ++ ++ /* config divider values for the closest possible frequency */ ++ config_div_and_duty(pwm, best_pre_div, best_pwm_div, ++ rate, duty_ns, state->enabled); ++ ++ return 0; ++} ++ ++static int ipq_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, ++ struct pwm_state *state) ++{ ++ struct ipq_pwm_chip *ipq_chip = ipq_pwm_from_chip(chip); ++ unsigned long rate = clk_get_rate(ipq_chip->clk); ++ unsigned int pre_div, pwm_div, hi_dur; ++ u64 effective_div, hi_div; ++ u32 reg0, reg1; ++ ++ reg0 = ipq_pwm_reg_read(pwm, IPQ_PWM_REG0); ++ reg1 = ipq_pwm_reg_read(pwm, IPQ_PWM_REG1); ++ ++ state->polarity = PWM_POLARITY_NORMAL; ++ state->enabled = reg1 & IPQ_PWM_REG1_ENABLE; ++ ++ pwm_div = FIELD_GET(IPQ_PWM_REG0_PWM_DIV, reg0); ++ hi_dur = FIELD_GET(IPQ_PWM_REG0_HI_DURATION, reg0); ++ pre_div = FIELD_GET(IPQ_PWM_REG1_PRE_DIV, reg1); ++ ++ /* No overflow here, both pre_div and pwm_div <= 0xffff */ ++ effective_div = (u64)(pre_div + 1) * (pwm_div + 1); ++ state->period = DIV64_U64_ROUND_UP(effective_div * NSEC_PER_SEC, rate); ++ ++ hi_div = hi_dur * (pre_div + 1); ++ state->duty_cycle = DIV64_U64_ROUND_UP(hi_div * NSEC_PER_SEC, rate); ++ ++ return 0; ++} ++ ++static const struct pwm_ops ipq_pwm_ops = { ++ .apply = ipq_pwm_apply, ++ .get_state = ipq_pwm_get_state, ++ .owner = THIS_MODULE, ++}; ++ ++static int ipq_pwm_probe(struct platform_device *pdev) ++{ ++ struct ipq_pwm_chip *pwm; ++ struct device *dev = &pdev->dev; ++ int ret; ++ ++ pwm = devm_kzalloc(dev, sizeof(*pwm), GFP_KERNEL); ++ if (!pwm) ++ return -ENOMEM; ++ ++ platform_set_drvdata(pdev, pwm); ++ ++ pwm->mem = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(pwm->mem)) ++ return dev_err_probe(dev, PTR_ERR(pwm->mem), ++ "regs map failed"); ++ ++ pwm->clk = devm_clk_get(dev, NULL); ++ if (IS_ERR(pwm->clk)) ++ return dev_err_probe(dev, PTR_ERR(pwm->clk), ++ "failed to get clock"); ++ ++ ret = clk_prepare_enable(pwm->clk); ++ if (ret) ++ return dev_err_probe(dev, ret, "clock enable failed"); ++ ++ pwm->chip.dev = dev; ++ pwm->chip.ops = &ipq_pwm_ops; ++ pwm->chip.npwm = 4; ++ ++ ret = pwmchip_add(&pwm->chip); ++ if (ret < 0) { ++ dev_err_probe(dev, ret, "pwmchip_add() failed\n"); ++ clk_disable_unprepare(pwm->clk); ++ } ++ ++ return ret; ++} ++ ++static int ipq_pwm_remove(struct platform_device *pdev) ++{ ++ struct ipq_pwm_chip *pwm = platform_get_drvdata(pdev); ++ ++ pwmchip_remove(&pwm->chip); ++ clk_disable_unprepare(pwm->clk); ++ ++ return 0; ++} ++ ++static const struct of_device_id pwm_ipq_dt_match[] = { ++ { .compatible = "qcom,ipq6018-pwm", }, ++ {} ++}; ++MODULE_DEVICE_TABLE(of, pwm_ipq_dt_match); ++ ++static struct platform_driver ipq_pwm_driver = { ++ .driver = { ++ .name = "ipq-pwm", ++ .of_match_table = pwm_ipq_dt_match, ++ }, ++ .probe = ipq_pwm_probe, ++ .remove = ipq_pwm_remove, ++}; ++ ++module_platform_driver(ipq_pwm_driver); ++ ++MODULE_LICENSE("Dual BSD/GPL"); diff --git a/target/linux/qualcommax/patches-6.1/0105-arm64-dts-qcom-ipq6018-add-pwm-node.patch b/target/linux/qualcommax/patches-6.1/0105-arm64-dts-qcom-ipq6018-add-pwm-node.patch new file mode 100644 index 000000000..66b41b835 --- /dev/null +++ b/target/linux/qualcommax/patches-6.1/0105-arm64-dts-qcom-ipq6018-add-pwm-node.patch @@ -0,0 +1,45 @@ +From b4a32d218d424b81a58fbd419e1114b1c1f76168 Mon Sep 17 00:00:00 2001 +From: Devi Priya +Date: Thu, 5 Oct 2023 21:35:50 +0530 +Subject: [PATCH] pwm: driver for qualcomm ipq6018 pwm block + +Describe the PWM block on IPQ6018. + +The PWM is in the TCSR area. Make &tcsr "simple-mfd" compatible, and add +&pwm as child of &tcsr. + +Add also ipq6018 specific compatible string. + +Reviewed-by: Krzysztof Kozlowski +Co-developed-by: Baruch Siach +Signed-off-by: Baruch Siach +Signed-off-by: Devi Priya +--- + arch/arm64/boot/dts/qcom/ipq6018.dtsi | 15 ++++++++++++++- + 1 file changed, 14 insertions(+), 1 deletion(-) + +--- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi ++++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi +@@ -409,8 +409,21 @@ + }; + + tcsr: syscon@1937000 { +- compatible = "qcom,tcsr-ipq6018", "syscon"; ++ compatible = "qcom,tcsr-ipq6018", "syscon", "simple-mfd"; + reg = <0x0 0x01937000 0x0 0x21000>; ++ ranges = <0x0 0x0 0x01937000 0x21000>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ pwm: pwm@a010 { ++ compatible = "qcom,ipq6018-pwm"; ++ reg = <0xa010 0x20>; ++ clocks = <&gcc GCC_ADSS_PWM_CLK>; ++ assigned-clocks = <&gcc GCC_ADSS_PWM_CLK>; ++ assigned-clock-rates = <100000000>; ++ #pwm-cells = <2>; ++ status = "disabled"; ++ }; + }; + + usb2: usb@70f8800 { diff --git a/target/linux/qualcommax/patches-6.1/0109-arm64-dts-ipq6018-Add-remaining-QUP-UART-node.patch b/target/linux/qualcommax/patches-6.1/0109-arm64-dts-ipq6018-Add-remaining-QUP-UART-node.patch new file mode 100644 index 000000000..0c958f0b5 --- /dev/null +++ b/target/linux/qualcommax/patches-6.1/0109-arm64-dts-ipq6018-Add-remaining-QUP-UART-node.patch @@ -0,0 +1,66 @@ +--- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi ++++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi +@@ -471,6 +471,26 @@ + qcom,ee = <0>; + }; + ++ blsp1_uart1: serial@78af000 { ++ compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm"; ++ reg = <0x0 0x78af000 0x0 0x200>; ++ interrupts = ; ++ clocks = <&gcc GCC_BLSP1_UART1_APPS_CLK>, ++ <&gcc GCC_BLSP1_AHB_CLK>; ++ clock-names = "core", "iface"; ++ status = "disabled"; ++ }; ++ ++ blsp1_uart2: serial@78b0000 { ++ compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm"; ++ reg = <0x0 0x78b0000 0x0 0x200>; ++ interrupts = ; ++ clocks = <&gcc GCC_BLSP1_UART2_APPS_CLK>, ++ <&gcc GCC_BLSP1_AHB_CLK>; ++ clock-names = "core", "iface"; ++ status = "disabled"; ++ }; ++ + blsp1_uart3: serial@78b1000 { + compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm"; + reg = <0x0 0x078b1000 0x0 0x200>; +@@ -479,6 +499,36 @@ + <&gcc GCC_BLSP1_AHB_CLK>; + clock-names = "core", "iface"; + status = "disabled"; ++ }; ++ ++ blsp1_uart4: serial@78b2000 { ++ compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm"; ++ reg = <0x0 0x078b2000 0x0 0x200>; ++ interrupts = ; ++ clocks = <&gcc GCC_BLSP1_UART4_APPS_CLK>, ++ <&gcc GCC_BLSP1_AHB_CLK>; ++ clock-names = "core", "iface"; ++ status = "disabled"; ++ }; ++ ++ blsp1_uart5: serial@78b3000 { ++ compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm"; ++ reg = <0x0 0x78b3000 0x0 0x200>; ++ interrupts = ; ++ clocks = <&gcc GCC_BLSP1_UART5_APPS_CLK>, ++ <&gcc GCC_BLSP1_AHB_CLK>; ++ clock-names = "core", "iface"; ++ status = "disabled"; ++ }; ++ ++ blsp1_uart6: serial@78b4000 { ++ compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm"; ++ reg = <0x0 0x078b4000 0x0 0x200>; ++ interrupts = ; ++ clocks = <&gcc GCC_BLSP1_UART6_APPS_CLK>, ++ <&gcc GCC_BLSP1_AHB_CLK>; ++ clock-names = "core", "iface"; ++ status = "disabled"; + }; + + blsp1_spi1: spi@78b5000 { diff --git a/target/linux/qualcommax/patches-6.1/0120-arm64-dts-qcom-Enable-Q6v5-WCSS-for-ipq8074-SoC.patch b/target/linux/qualcommax/patches-6.1/0120-arm64-dts-qcom-Enable-Q6v5-WCSS-for-ipq8074-SoC.patch index e37ba37e9..ffbd126c2 100644 --- a/target/linux/qualcommax/patches-6.1/0120-arm64-dts-qcom-Enable-Q6v5-WCSS-for-ipq8074-SoC.patch +++ b/target/linux/qualcommax/patches-6.1/0120-arm64-dts-qcom-Enable-Q6v5-WCSS-for-ipq8074-SoC.patch @@ -16,7 +16,7 @@ Signed-off-by: Robert Marko --- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi +++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -140,6 +140,32 @@ +@@ -141,6 +141,32 @@ }; }; @@ -49,8 +49,8 @@ Signed-off-by: Robert Marko soc: soc { #address-cells = <0x1>; #size-cells = <0x1>; -@@ -409,6 +435,11 @@ - #hwlock-cells = <1>; +@@ -415,6 +441,11 @@ + reg = <0x01937000 0x21000>; }; + tcsr_q6: syscon@1945000 { @@ -61,7 +61,7 @@ Signed-off-by: Robert Marko spmi_bus: spmi@200f000 { compatible = "qcom,spmi-pmic-arb"; reg = <0x0200f000 0x001000>, -@@ -913,6 +944,56 @@ +@@ -919,6 +950,56 @@ "axi_s_sticky"; status = "disabled"; }; diff --git a/target/linux/ipq60xx/patches-5.15/1008-remoteproc-wcss-Add-ipq6018-support-in-remoteproc.patch b/target/linux/qualcommax/patches-6.1/0131-remoteproc-wcss-Add-ipq6018-support-in-remoteproc.patch similarity index 71% rename from target/linux/ipq60xx/patches-5.15/1008-remoteproc-wcss-Add-ipq6018-support-in-remoteproc.patch rename to target/linux/qualcommax/patches-6.1/0131-remoteproc-wcss-Add-ipq6018-support-in-remoteproc.patch index 200a5dde5..9b499b7b6 100644 --- a/target/linux/ipq60xx/patches-5.15/1008-remoteproc-wcss-Add-ipq6018-support-in-remoteproc.patch +++ b/target/linux/qualcommax/patches-6.1/0131-remoteproc-wcss-Add-ipq6018-support-in-remoteproc.patch @@ -1,12 +1,12 @@ -From f277b1421cdc4d2a6ef4bbb6bcaeb07a099157a2 Mon Sep 17 00:00:00 2001 +From 071caeaca82d555eb8560612dfad16832d0d3066 Mon Sep 17 00:00:00 2001 From: anusha Date: Wed, 5 Aug 2020 11:01:41 +0530 -Subject: [PATCH 1008/1011] remoteproc: wcss: Add ipq6018 support in remoteproc +Subject: [PATCH] remoteproc: wcss: Add ipq6018 support in remoteproc Signed-off-by: anusha --- - drivers/remoteproc/qcom_q6v5_wcss.c | 20 ++++++++++++++++++-- - 1 file changed, 18 insertions(+), 2 deletions(-) + drivers/remoteproc/qcom_q6v5_wcss.c | 21 +++++++++++++++++++-- + 1 files changed, 20 insertions(+), 3 deletions(-) --- a/drivers/remoteproc/qcom_q6v5_wcss.c +++ b/drivers/remoteproc/qcom_q6v5_wcss.c @@ -28,9 +28,9 @@ Signed-off-by: anusha res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rmb"); wcss->rmb_base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(wcss->rmb_base)) -@@ -1177,6 +1177,21 @@ static int q6v5_wcss_remove(struct platf - return 0; - } +@@ -1193,6 +1193,21 @@ static const struct wcss_data wcss_ipq80 + .need_auto_boot = false, + }; +static const struct wcss_data wcss_ipq6018_res_init = { + .init_clock = ipq8074_init_clock, @@ -42,19 +42,19 @@ Signed-off-by: anusha + .bcr_reset_required = false, + .ssr_name = "q6wcss", + .ops = &q6v5_wcss_ipq8074_ops, -+ .requires_force_stop = false, ++ .requires_force_stop = true, + .need_mem_protection = true, + .need_auto_boot = false, +}; + - static const struct wcss_data wcss_ipq8074_res_init = { - .init_clock = ipq8074_init_clock, - .q6_firmware_name = "IPQ8074/q6_fw.mdt", -@@ -1210,6 +1225,7 @@ static const struct wcss_data wcss_qcs40 - }; + static const struct wcss_data wcss_qcs404_res_init = { + .init_clock = qcs404_init_clock, + .init_regulator = qcs404_init_regulator, +@@ -1212,6 +1227,7 @@ static const struct wcss_data wcss_qcs40 static const struct of_device_id q6v5_wcss_of_match[] = { -+ { .compatible = "qcom,ipq6018-wcss-pil", .data = &wcss_ipq6018_res_init }, { .compatible = "qcom,ipq8074-wcss-pil", .data = &wcss_ipq8074_res_init }, ++ { .compatible = "qcom,ipq6018-wcss-pil", .data = &wcss_ipq6018_res_init }, { .compatible = "qcom,qcs404-wcss-pil", .data = &wcss_qcs404_res_init }, { }, + }; diff --git a/target/linux/ipq60xx/patches-5.15/1009-ipq6018-rproc-Add-non-secure-Q6-bringup-sequence.patch b/target/linux/qualcommax/patches-6.1/0132-ipq6018-rproc-Add-non-secure-Q6-bringup-sequence.patch similarity index 73% rename from target/linux/ipq60xx/patches-5.15/1009-ipq6018-rproc-Add-non-secure-Q6-bringup-sequence.patch rename to target/linux/qualcommax/patches-6.1/0132-ipq6018-rproc-Add-non-secure-Q6-bringup-sequence.patch index c779eba19..b771c160c 100644 --- a/target/linux/ipq60xx/patches-5.15/1009-ipq6018-rproc-Add-non-secure-Q6-bringup-sequence.patch +++ b/target/linux/qualcommax/patches-6.1/0132-ipq6018-rproc-Add-non-secure-Q6-bringup-sequence.patch @@ -1,7 +1,7 @@ -From bbde72dea11689b21cc34f61f064d0e35b660fec Mon Sep 17 00:00:00 2001 +From 5b6c148bfb6c25449c59a0a87896a90f883307fd Mon Sep 17 00:00:00 2001 From: Manikanta Mylavarapu Date: Fri, 31 Dec 2021 17:13:59 +0530 -Subject: [PATCH 1009/1011] ipq6018: rproc: Add non secure Q6 bringup sequence +Subject: [PATCH] ipq6018: rproc: Add non secure Q6 bringup sequence This patch adds Q6 bring up sequence support. @@ -9,57 +9,65 @@ Change-Id: I28eee991168034cc240d863e736ed9c766ec4f33 Signed-off-by: Manikanta Mylavarapu --- arch/arm64/boot/dts/qcom/ipq6018.dtsi | 20 ++- - drivers/remoteproc/qcom_q6v5_wcss.c | 223 ++++++++++++++++++++++++-- - 2 files changed, 227 insertions(+), 16 deletions(-) + drivers/remoteproc/qcom_q6v5_wcss.c | 235 +++++++++++++++++++++++--- + 2 files changed, 232 insertions(+), 23 deletions(-) --- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi +++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi -@@ -663,8 +663,24 @@ +@@ -789,8 +789,24 @@ "wcss_reset", "wcss_q6_reset"; - clocks = <&gcc GCC_PRNG_AHB_CLK>; - clock-names = "prng"; + clocks = <&gcc GCC_PRNG_AHB_CLK>, -+ <&gcc GCC_SYS_NOC_WCSS_AHB_CLK>, -+ <&gcc GCC_Q6SS_ATBM_CLK>, -+ <&gcc GCC_Q6SS_PCLKDBG_CLK>, -+ <&gcc GCC_Q6_TSCTR_1TO2_CLK>; ++ <&gcc GCC_SYS_NOC_WCSS_AHB_CLK>, ++ <&gcc GCC_Q6SS_ATBM_CLK>, ++ <&gcc GCC_Q6SS_PCLKDBG_CLK>, ++ <&gcc GCC_Q6_TSCTR_1TO2_CLK>; + clock-names = "prng", -+ "gcc_sys_noc_wcss_ahb_clk", -+ "gcc_q6ss_atbm_clk", -+ "gcc_q6ss_pclkdbg_clk", -+ "gcc_q6_tsctr_1to2_clk"; ++ "gcc_sys_noc_wcss_ahb_clk", ++ "gcc_q6ss_atbm_clk", ++ "gcc_q6ss_pclkdbg_clk", ++ "gcc_q6_tsctr_1to2_clk"; + assigned-clocks = <&gcc GCC_SYS_NOC_WCSS_AHB_CLK>, + <&gcc GCC_Q6SS_PCLKDBG_CLK>, -+ <&gcc GCC_Q6_TSCTR_1TO2_CLK>, -+ <&gcc GCC_Q6SS_ATBM_CLK>; ++ <&gcc GCC_Q6_TSCTR_1TO2_CLK>, ++ <&gcc GCC_Q6SS_ATBM_CLK>; + assigned-clock-rates = <133333333>, -+ <600000000>, -+ <600000000>, -+ <240000000>; ++ <600000000>, ++ <600000000>, ++ <240000000>; qcom,halt-regs = <&tcsr 0x18000 0x1b000 0xe000>; --- a/drivers/remoteproc/qcom_q6v5_wcss.c +++ b/drivers/remoteproc/qcom_q6v5_wcss.c -@@ -27,6 +27,7 @@ +@@ -12,6 +12,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -27,6 +28,7 @@ /* Q6SS Register Offsets */ #define Q6SS_RESET_REG 0x014 -+#define Q6SS_DBG_CFG 0x018 ++#define Q6SS_DBG_CFG 0x018 #define Q6SS_GFMUX_CTL_REG 0x020 #define Q6SS_PWR_CTL_REG 0x030 #define Q6SS_MEM_PWR_CTL 0x0B0 -@@ -68,6 +69,7 @@ +@@ -68,6 +70,7 @@ #define HALT_CHECK_MAX_LOOPS 200 #define Q6SS_XO_CBCR GENMASK(5, 3) #define Q6SS_SLEEP_CBCR GENMASK(5, 2) -+#define Q6SS_TIMEOUT_US 1000 ++#define Q6SS_TIMEOUT_US 1000 /* Q6SS config/status registers */ #define TCSR_GLOBAL_CFG0 0x0 -@@ -78,6 +80,7 @@ +@@ -78,6 +81,7 @@ #define Q6SS_RST_EVB 0x10 #define BHS_EN_REST_ACK BIT(0) @@ -67,10 +75,20 @@ Signed-off-by: Manikanta Mylavarapu #define SSCAON_ENABLE BIT(13) #define SSCAON_BUS_EN BIT(15) #define SSCAON_BUS_MUX_MASK GENMASK(18, 16) -@@ -120,6 +123,11 @@ struct q6v5_wcss { +@@ -90,6 +94,8 @@ + + #define WCNSS_PAS_ID 6 + ++static const struct wcss_data wcss_ipq6018_res_init; ++ + enum { + WCSS_IPQ, + WCSS_QCS404, +@@ -120,6 +126,12 @@ struct q6v5_wcss { struct clk *qdsp6ss_core_gfmux; struct clk *lcc_bcr_sleep; struct clk *prng_clk; ++ + struct clk *gcc_sys_noc_wcss_ahb_clk; + struct clk *gcc_q6ss_atbm_clk; + struct clk *gcc_q6ss_pclkdbg_clk; @@ -79,12 +97,11 @@ Signed-off-by: Manikanta Mylavarapu struct regulator *cx_supply; struct qcom_sysmon *sysmon; -@@ -164,12 +172,77 @@ struct wcss_data { +@@ -164,12 +176,79 @@ struct wcss_data { bool need_auto_boot; }; -+static const struct wcss_data wcss_ipq6018_res_init; -+ +-static int q6v5_wcss_reset(struct q6v5_wcss *wcss) +static int ipq6018_clks_prepare_enable(struct q6v5_wcss *wcss) +{ + int ret; @@ -116,14 +133,16 @@ Signed-off-by: Manikanta Mylavarapu + clk_disable_unprepare(wcss->gcc_q6_tsctr_1to2_clk); +} + - static int q6v5_wcss_reset(struct q6v5_wcss *wcss) ++static int q6v5_wcss_reset(struct rproc *rproc) { -+ const struct wcss_data *desc; int ret; u32 val; int i; -+ desc = device_get_match_data(wcss->dev); ++ struct q6v5_wcss *wcss = rproc->priv; ++ const struct wcss_data *desc; ++ ++ desc = of_device_get_match_data(wcss->dev); + if (desc == &wcss_ipq6018_res_init) { + if (desc->aon_reset_required) { + /* Deassert wcss aon reset */ @@ -153,11 +172,22 @@ Signed-off-by: Manikanta Mylavarapu + val |= SSCAON_BUS_EN; + writel(val, wcss->rmb_base + SSCAON_CONFIG); + mdelay(1); ++ ++ writel(rproc->bootaddr >> 4, wcss->reg_base + Q6SS_RST_EVB); + /* Assert resets, stop core */ val = readl(wcss->reg_base + Q6SS_RESET_REG); val |= Q6SS_CORE_ARES | Q6SS_BUS_ARES_ENABLE | Q6SS_STOP_CORE; -@@ -195,7 +268,19 @@ static int q6v5_wcss_reset(struct q6v5_w +@@ -183,7 +262,7 @@ static int q6v5_wcss_reset(struct q6v5_w + /* Read CLKOFF bit to go low indicating CLK is enabled */ + ret = readl_poll_timeout(wcss->reg_base + Q6SS_XO_CBCR, + val, !(val & BIT(31)), 1, +- HALT_CHECK_MAX_LOOPS); ++ Q6SS_TIMEOUT_US); + if (ret) { + dev_err(wcss->dev, + "xo cbcr enabling timed out (rc:%d)\n", ret); +@@ -195,7 +274,19 @@ static int q6v5_wcss_reset(struct q6v5_w writel(val, wcss->reg_base + Q6SS_PWR_CTL_REG); udelay(1); @@ -177,7 +207,7 @@ Signed-off-by: Manikanta Mylavarapu val |= Q6SS_LDO_BYP; writel(val, wcss->reg_base + Q6SS_PWR_CTL_REG); -@@ -205,6 +290,7 @@ static int q6v5_wcss_reset(struct q6v5_w +@@ -205,6 +296,7 @@ static int q6v5_wcss_reset(struct q6v5_w writel(val, wcss->reg_base + Q6SS_PWR_CTL_REG); /* Deassert memory peripheral sleep and L2 memory standby */ @@ -185,7 +215,7 @@ Signed-off-by: Manikanta Mylavarapu val |= Q6SS_L2DATA_STBY_N | Q6SS_SLP_RET_N; writel(val, wcss->reg_base + Q6SS_PWR_CTL_REG); -@@ -219,7 +305,10 @@ static int q6v5_wcss_reset(struct q6v5_w +@@ -219,7 +311,10 @@ static int q6v5_wcss_reset(struct q6v5_w * array to turn on. */ val |= readl(wcss->reg_base + Q6SS_MEM_PWR_CTL); @@ -197,15 +227,7 @@ Signed-off-by: Manikanta Mylavarapu } /* Remove word line clamp */ val = readl(wcss->reg_base + Q6SS_PWR_CTL_REG); -@@ -227,6 +316,7 @@ static int q6v5_wcss_reset(struct q6v5_w - writel(val, wcss->reg_base + Q6SS_PWR_CTL_REG); - - /* Remove IO clamp */ -+ val = readl(wcss->reg_base + Q6SS_PWR_CTL_REG); - val &= ~Q6SS_CLAMP_IO; - writel(val, wcss->reg_base + Q6SS_PWR_CTL_REG); - -@@ -245,6 +335,16 @@ static int q6v5_wcss_reset(struct q6v5_w +@@ -245,6 +340,16 @@ static int q6v5_wcss_reset(struct q6v5_w val &= ~Q6SS_STOP_CORE; writel(val, wcss->reg_base + Q6SS_RESET_REG); @@ -222,20 +244,23 @@ Signed-off-by: Manikanta Mylavarapu return 0; } -@@ -376,7 +476,7 @@ static int q6v5_wcss_qcs404_power_on(str - /* Read CLKOFF bit to go low indicating CLK is enabled */ - ret = readl_poll_timeout(wcss->reg_base + Q6SS_XO_CBCR, - val, !(val & BIT(31)), 1, -- HALT_CHECK_MAX_LOOPS); -+ Q6SS_TIMEOUT_US); - if (ret) { - dev_err(wcss->dev, - "xo cbcr enabling timed out (rc:%d)\n", ret); -@@ -529,13 +629,18 @@ static void q6v5_wcss_halt_axi_port(stru +@@ -300,7 +405,7 @@ static int q6v5_wcss_start(struct rproc + /* Write bootaddr to EVB so that Q6WCSS will jump there after reset */ + writel(rproc->bootaddr >> 4, wcss->reg_base + Q6SS_RST_EVB); + +- ret = q6v5_wcss_reset(wcss); ++ ret = q6v5_wcss_reset(rproc); + if (ret) + goto wcss_q6_reset; + +@@ -526,16 +631,21 @@ static void q6v5_wcss_halt_axi_port(stru + struct regmap *halt_map, + u32 offset) + { ++ const struct wcss_data *desc = of_device_get_match_data(wcss->dev); unsigned long timeout; unsigned int val; int ret; -+ const struct wcss_data *desc = device_get_match_data(wcss->dev); - /* Check if we're already idle */ - ret = regmap_read(halt_map, offset + AXI_IDLE_REG, &val); @@ -254,7 +279,7 @@ Signed-off-by: Manikanta Mylavarapu regmap_write(halt_map, offset + AXI_HALTREQ_REG, 1); /* Wait for halt */ -@@ -548,12 +653,14 @@ static void q6v5_wcss_halt_axi_port(stru +@@ -548,12 +658,14 @@ static void q6v5_wcss_halt_axi_port(stru msleep(1); } @@ -274,15 +299,15 @@ Signed-off-by: Manikanta Mylavarapu } static int q6v5_qcs404_wcss_shutdown(struct q6v5_wcss *wcss) -@@ -622,6 +729,7 @@ static int q6v5_qcs404_wcss_shutdown(str +@@ -622,6 +734,7 @@ static int q6v5_qcs404_wcss_shutdown(str static int q6v5_wcss_powerdown(struct q6v5_wcss *wcss) { -+ const struct wcss_data *desc = device_get_match_data(wcss->dev); ++ const struct wcss_data *desc = of_device_get_match_data(wcss->dev); int ret; u32 val; -@@ -639,21 +747,26 @@ static int q6v5_wcss_powerdown(struct q6 +@@ -639,13 +752,14 @@ static int q6v5_wcss_powerdown(struct q6 writel(val, wcss->rmb_base + SSCAON_CONFIG); /* 4 - SSCAON_CONFIG 1 */ @@ -298,11 +323,8 @@ Signed-off-by: Manikanta Mylavarapu if (ret) { dev_err(wcss->dev, "can't get SSCAON_STATUS rc:%d)\n", ret); - return ret; - } +@@ -654,6 +768,8 @@ static int q6v5_wcss_powerdown(struct q6 -+ mdelay(2); -+ /* 6 - De-assert WCSS_AON reset */ reset_control_assert(wcss->wcss_aon_reset); + if (desc == &wcss_ipq6018_res_init) @@ -310,7 +332,7 @@ Signed-off-by: Manikanta Mylavarapu /* 7 - Disable WCSSAON_CONFIG 13 */ val = readl(wcss->rmb_base + SSCAON_CONFIG); -@@ -663,6 +776,13 @@ static int q6v5_wcss_powerdown(struct q6 +@@ -663,15 +779,28 @@ static int q6v5_wcss_powerdown(struct q6 /* 8 - De-assert WCSS/Q6 HALTREQ */ reset_control_assert(wcss->wcss_reset); @@ -324,20 +346,22 @@ Signed-off-by: Manikanta Mylavarapu return 0; } -@@ -671,6 +791,12 @@ static int q6v5_q6_powerdown(struct q6v5 + static int q6v5_q6_powerdown(struct q6v5_wcss *wcss) + { ++ const struct wcss_data *desc = of_device_get_match_data(wcss->dev); int ret; u32 val; int i; -+ const struct wcss_data *desc = device_get_match_data(wcss->dev); -+ + + if (desc == &wcss_ipq6018_res_init) { + /* To retain power domain after q6 powerdown */ + writel(0x1, wcss->reg_base + Q6SS_DBG_CFG); + } - ++ /* 1 - Halt Q6 bus interface */ q6v5_wcss_halt_axi_port(wcss, wcss->halt_map, wcss->halt_q6); -@@ -686,14 +812,17 @@ static int q6v5_q6_powerdown(struct q6v5 + +@@ -686,14 +815,17 @@ static int q6v5_q6_powerdown(struct q6v5 writel(val, wcss->reg_base + Q6SS_PWR_CTL_REG); /* 4 - Clamp WL */ @@ -355,7 +379,7 @@ Signed-off-by: Manikanta Mylavarapu val &= ~Q6SS_SLP_RET_N; writel(val, wcss->reg_base + Q6SS_PWR_CTL_REG); -@@ -711,6 +840,7 @@ static int q6v5_q6_powerdown(struct q6v5 +@@ -711,6 +843,7 @@ static int q6v5_q6_powerdown(struct q6v5 writel(val, wcss->reg_base + Q6SS_PWR_CTL_REG); /* 9 - Turn off BHS */ @@ -363,7 +387,7 @@ Signed-off-by: Manikanta Mylavarapu val &= ~Q6SS_BHS_ON; writel(val, wcss->reg_base + Q6SS_PWR_CTL_REG); udelay(1); -@@ -718,7 +848,7 @@ static int q6v5_q6_powerdown(struct q6v5 +@@ -718,7 +851,7 @@ static int q6v5_q6_powerdown(struct q6v5 /* 10 - Wait till BHS Reset is done */ ret = readl_poll_timeout(wcss->reg_base + Q6SS_BHS_STATUS, val, !(val & BHS_EN_REST_ACK), 1000, @@ -372,7 +396,7 @@ Signed-off-by: Manikanta Mylavarapu if (ret) { dev_err(wcss->dev, "BHS_STATUS not OFF (rc:%d)\n", ret); return ret; -@@ -726,9 +856,23 @@ static int q6v5_q6_powerdown(struct q6v5 +@@ -726,9 +859,23 @@ static int q6v5_q6_powerdown(struct q6v5 /* 11 - Assert WCSS reset */ reset_control_assert(wcss->wcss_reset); @@ -396,7 +420,7 @@ Signed-off-by: Manikanta Mylavarapu return 0; } -@@ -970,6 +1114,57 @@ static int q6v5_alloc_memory_region(stru +@@ -984,6 +1131,57 @@ static int ipq8074_init_clock(struct q6v return 0; } @@ -413,7 +437,7 @@ Signed-off-by: Manikanta Mylavarapu + } + + wcss->gcc_sys_noc_wcss_ahb_clk = -+ devm_clk_get(wcss->dev, "gcc_sys_noc_wcss_ahb_clk"); ++ devm_clk_get(wcss->dev, "gcc_sys_noc_wcss_ahb_clk"); + if (IS_ERR(wcss->gcc_sys_noc_wcss_ahb_clk)) { + ret = PTR_ERR(wcss->gcc_sys_noc_wcss_ahb_clk); + if (ret != -EPROBE_DEFER) @@ -422,7 +446,7 @@ Signed-off-by: Manikanta Mylavarapu + } + + wcss->gcc_q6ss_atbm_clk = -+ devm_clk_get(wcss->dev, "gcc_q6ss_atbm_clk"); ++ devm_clk_get(wcss->dev, "gcc_q6ss_atbm_clk"); + if (IS_ERR(wcss->gcc_q6ss_atbm_clk)) { + ret = PTR_ERR(wcss->gcc_q6ss_atbm_clk); + if (ret != -EPROBE_DEFER) @@ -431,7 +455,7 @@ Signed-off-by: Manikanta Mylavarapu + } + + wcss->gcc_q6ss_pclkdbg_clk = -+ devm_clk_get(wcss->dev, "gcc_q6ss_pclkdbg_clk"); ++ devm_clk_get(wcss->dev, "gcc_q6ss_pclkdbg_clk"); + if (IS_ERR(wcss->gcc_q6ss_pclkdbg_clk)) { + ret = PTR_ERR(wcss->gcc_q6ss_pclkdbg_clk); + if (ret != -EPROBE_DEFER) @@ -440,7 +464,7 @@ Signed-off-by: Manikanta Mylavarapu + } + + wcss->gcc_q6_tsctr_1to2_clk = -+ devm_clk_get(wcss->dev, "gcc_q6_tsctr_1to2_clk"); ++ devm_clk_get(wcss->dev, "gcc_q6_tsctr_1to2_clk"); + if (IS_ERR(wcss->gcc_q6_tsctr_1to2_clk)) { + ret = PTR_ERR(wcss->gcc_q6_tsctr_1to2_clk); + if (ret != -EPROBE_DEFER) @@ -451,11 +475,21 @@ Signed-off-by: Manikanta Mylavarapu + return 0; +} + - static int ipq8074_init_clock(struct q6v5_wcss *wcss) + static int qcs404_init_clock(struct q6v5_wcss *wcss) { int ret; -@@ -1178,7 +1373,7 @@ static int q6v5_wcss_remove(struct platf - } +@@ -1115,6 +1313,9 @@ static int q6v5_wcss_probe(struct platfo + wcss->need_mem_protection = desc->need_mem_protection; + wcss->m3_firmware_name = desc->m3_firmware_name; + ++ if (of_property_read_bool(pdev->dev.of_node, "qcom,nosecure")) ++ wcss->need_mem_protection = false; ++ + ret = q6v5_wcss_init_mmio(wcss, pdev); + if (ret) + goto free_rproc; +@@ -1194,7 +1395,7 @@ static const struct wcss_data wcss_ipq80 + }; static const struct wcss_data wcss_ipq6018_res_init = { - .init_clock = ipq8074_init_clock, @@ -463,3 +497,12 @@ Signed-off-by: Manikanta Mylavarapu .q6_firmware_name = "IPQ6018/q6_fw.mdt", .m3_firmware_name = "IPQ6018/m3_fw.mdt", .crash_reason_smem = WCSS_CRASH_REASON, +@@ -1203,7 +1404,7 @@ static const struct wcss_data wcss_ipq60 + .bcr_reset_required = false, + .ssr_name = "q6wcss", + .ops = &q6v5_wcss_ipq8074_ops, +- .requires_force_stop = true, ++ .requires_force_stop = false, + .need_mem_protection = true, + .need_auto_boot = false, + }; diff --git a/target/linux/qualcommax/patches-6.1/0133-arm64-dts-ipq6018-Add-WLAN-node.patch b/target/linux/qualcommax/patches-6.1/0133-arm64-dts-ipq6018-Add-WLAN-node.patch new file mode 100644 index 000000000..8b127cff4 --- /dev/null +++ b/target/linux/qualcommax/patches-6.1/0133-arm64-dts-ipq6018-Add-WLAN-node.patch @@ -0,0 +1,122 @@ +--- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi ++++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi +@@ -764,6 +764,119 @@ + }; + }; + ++ wifi: wifi@c000000 { ++ compatible = "qcom,ipq6018-wifi"; ++ reg = <0x0 0xc000000 0x0 0x1000000>; ++ ++ interrupts = <0 320 IRQ_TYPE_EDGE_RISING>, ++ <0 319 IRQ_TYPE_EDGE_RISING>, ++ <0 318 IRQ_TYPE_EDGE_RISING>, ++ <0 316 IRQ_TYPE_EDGE_RISING>, ++ <0 315 IRQ_TYPE_EDGE_RISING>, ++ <0 314 IRQ_TYPE_EDGE_RISING>, ++ <0 311 IRQ_TYPE_EDGE_RISING>, ++ <0 310 IRQ_TYPE_EDGE_RISING>, ++ <0 411 IRQ_TYPE_EDGE_RISING>, ++ <0 410 IRQ_TYPE_EDGE_RISING>, ++ <0 40 IRQ_TYPE_EDGE_RISING>, ++ <0 39 IRQ_TYPE_EDGE_RISING>, ++ <0 302 IRQ_TYPE_EDGE_RISING>, ++ <0 301 IRQ_TYPE_EDGE_RISING>, ++ <0 37 IRQ_TYPE_EDGE_RISING>, ++ <0 36 IRQ_TYPE_EDGE_RISING>, ++ <0 296 IRQ_TYPE_EDGE_RISING>, ++ <0 295 IRQ_TYPE_EDGE_RISING>, ++ <0 294 IRQ_TYPE_EDGE_RISING>, ++ <0 293 IRQ_TYPE_EDGE_RISING>, ++ <0 292 IRQ_TYPE_EDGE_RISING>, ++ <0 291 IRQ_TYPE_EDGE_RISING>, ++ <0 290 IRQ_TYPE_EDGE_RISING>, ++ <0 289 IRQ_TYPE_EDGE_RISING>, ++ <0 288 IRQ_TYPE_EDGE_RISING>, ++ <0 239 IRQ_TYPE_EDGE_RISING>, ++ <0 236 IRQ_TYPE_EDGE_RISING>, ++ <0 235 IRQ_TYPE_EDGE_RISING>, ++ <0 234 IRQ_TYPE_EDGE_RISING>, ++ <0 233 IRQ_TYPE_EDGE_RISING>, ++ <0 232 IRQ_TYPE_EDGE_RISING>, ++ <0 231 IRQ_TYPE_EDGE_RISING>, ++ <0 230 IRQ_TYPE_EDGE_RISING>, ++ <0 229 IRQ_TYPE_EDGE_RISING>, ++ <0 228 IRQ_TYPE_EDGE_RISING>, ++ <0 224 IRQ_TYPE_EDGE_RISING>, ++ <0 223 IRQ_TYPE_EDGE_RISING>, ++ <0 203 IRQ_TYPE_EDGE_RISING>, ++ <0 183 IRQ_TYPE_EDGE_RISING>, ++ <0 180 IRQ_TYPE_EDGE_RISING>, ++ <0 179 IRQ_TYPE_EDGE_RISING>, ++ <0 178 IRQ_TYPE_EDGE_RISING>, ++ <0 177 IRQ_TYPE_EDGE_RISING>, ++ <0 176 IRQ_TYPE_EDGE_RISING>, ++ <0 163 IRQ_TYPE_EDGE_RISING>, ++ <0 162 IRQ_TYPE_EDGE_RISING>, ++ <0 160 IRQ_TYPE_EDGE_RISING>, ++ <0 414 IRQ_TYPE_EDGE_RISING>, ++ <0 159 IRQ_TYPE_EDGE_RISING>, ++ <0 158 IRQ_TYPE_EDGE_RISING>, ++ <0 157 IRQ_TYPE_EDGE_RISING>, ++ <0 156 IRQ_TYPE_EDGE_RISING>; ++ ++ interrupt-names = "misc-pulse1", ++ "misc-latch", ++ "sw-exception", ++ "ce0", ++ "ce1", ++ "ce2", ++ "ce3", ++ "ce4", ++ "ce5", ++ "ce6", ++ "ce7", ++ "ce8", ++ "ce9", ++ "ce10", ++ "ce11", ++ "host2wbm-desc-feed", ++ "host2reo-re-injection", ++ "host2reo-command", ++ "host2rxdma-monitor-ring3", ++ "host2rxdma-monitor-ring2", ++ "host2rxdma-monitor-ring1", ++ "reo2ost-exception", ++ "wbm2host-rx-release", ++ "reo2host-status", ++ "reo2host-destination-ring4", ++ "reo2host-destination-ring3", ++ "reo2host-destination-ring2", ++ "reo2host-destination-ring1", ++ "rxdma2host-monitor-destination-mac3", ++ "rxdma2host-monitor-destination-mac2", ++ "rxdma2host-monitor-destination-mac1", ++ "ppdu-end-interrupts-mac3", ++ "ppdu-end-interrupts-mac2", ++ "ppdu-end-interrupts-mac1", ++ "rxdma2host-monitor-status-ring-mac3", ++ "rxdma2host-monitor-status-ring-mac2", ++ "rxdma2host-monitor-status-ring-mac1", ++ "host2rxdma-host-buf-ring-mac3", ++ "host2rxdma-host-buf-ring-mac2", ++ "host2rxdma-host-buf-ring-mac1", ++ "rxdma2host-destination-ring-mac3", ++ "rxdma2host-destination-ring-mac2", ++ "rxdma2host-destination-ring-mac1", ++ "host2tcl-input-ring4", ++ "host2tcl-input-ring3", ++ "host2tcl-input-ring2", ++ "host2tcl-input-ring1", ++ "wbm2host-tx-completions-ring4", ++ "wbm2host-tx-completions-ring3", ++ "wbm2host-tx-completions-ring2", ++ "wbm2host-tx-completions-ring1", ++ "tcl2host-status-ring"; ++ qcom,rproc = <&q6v5_wcss>; ++ status = "disabled"; ++ }; ++ + q6v5_wcss: remoteproc@cd00000 { + compatible = "qcom,ipq6018-wcss-pil"; + reg = <0x0 0x0cd00000 0x0 0x4040>, diff --git a/target/linux/qualcommax/patches-6.1/0133-arm64-dts-ipq6018-add-reserved-memory-nodes.patch b/target/linux/qualcommax/patches-6.1/0133-arm64-dts-ipq6018-add-reserved-memory-nodes.patch new file mode 100644 index 000000000..5ec7ec9ce --- /dev/null +++ b/target/linux/qualcommax/patches-6.1/0133-arm64-dts-ipq6018-add-reserved-memory-nodes.patch @@ -0,0 +1,19 @@ +--- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi ++++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi +@@ -212,6 +212,16 @@ + reg = <0x0 0x4ab00000 0x0 0x5500000>; + no-map; + }; ++ ++ q6_etr_region: q6_etr_dump@50000000 { ++ reg = <0x0 0x50000000 0x0 0x100000>; ++ no-map; ++ }; ++ ++ m3_dump_region: m3_dump@50100000 { ++ reg = <0x0 0x50100000 0x0 0x100000>; ++ no-map; ++ }; + }; + + smem { diff --git a/target/linux/qualcommax/patches-6.1/0134-arm64-dts-qcom-ipq6018-add-LDOA2-regulator.patch b/target/linux/qualcommax/patches-6.1/0134-arm64-dts-qcom-ipq6018-add-LDOA2-regulator.patch new file mode 100644 index 000000000..dfcce21e8 --- /dev/null +++ b/target/linux/qualcommax/patches-6.1/0134-arm64-dts-qcom-ipq6018-add-LDOA2-regulator.patch @@ -0,0 +1,15 @@ +--- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi ++++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi +@@ -173,6 +173,12 @@ + regulator-max-microvolt = <1062500>; + regulator-always-on; + }; ++ ++ ipq6018_l2: l2 { ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-always-on; ++ }; + }; + }; + }; diff --git a/target/linux/qualcommax/patches-6.1/0135-arm64-dts-qcom-ipq6018-enable-sdhci-node.patch b/target/linux/qualcommax/patches-6.1/0135-arm64-dts-qcom-ipq6018-enable-sdhci-node.patch new file mode 100644 index 000000000..c9b6e9e13 --- /dev/null +++ b/target/linux/qualcommax/patches-6.1/0135-arm64-dts-qcom-ipq6018-enable-sdhci-node.patch @@ -0,0 +1,29 @@ +--- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi ++++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi +@@ -477,6 +477,26 @@ + }; + }; + ++ sdhc: mmc@7804000 { ++ compatible = "qcom,ipq6018-sdhci", "qcom,sdhci-msm-v5"; ++ reg = <0x0 0x7804000 0x0 0x1000>, ++ <0x0 0x7805000 0x0 0x1000>; ++ reg-names = "hc", "cqhci"; ++ ++ interrupts = , ++ ; ++ 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>; diff --git a/target/linux/qualcommax/patches-6.1/0136-arm64-dts-qcom-ipq6018-add-thermal-nodes.patch b/target/linux/qualcommax/patches-6.1/0136-arm64-dts-qcom-ipq6018-add-thermal-nodes.patch new file mode 100644 index 000000000..b5b994559 --- /dev/null +++ b/target/linux/qualcommax/patches-6.1/0136-arm64-dts-qcom-ipq6018-add-thermal-nodes.patch @@ -0,0 +1,146 @@ +From d2e727bd0a259de2d6d329e3c659b8a1b6fbbc8b Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Sun, 15 Oct 2023 22:55:43 +0200 +Subject: [PATCH] arm64: dts: qcom: ipq6018: add thermal nodes + +IPQ6018 has a tsens v2.3.1 peripheral which monitors temperatures around +the various subsystems on the die. + +Signed-off-by: Robert Marko +--- + arch/arm64/boot/dts/qcom/ipq6018.dtsi | 117 ++++++++++++++++++++++++++ + 1 file changed, 117 insertions(+) + +--- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi ++++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi +@@ -358,6 +358,16 @@ + clock-names = "core"; + }; + ++ tsens: thermal-sensor@4a9000 { ++ compatible = "qcom,ipq6018-tsens", "qcom,ipq8074-tsens"; ++ reg = <0x0 0x4a9000 0x0 0x1000>, /* TM */ ++ <0x0 0x4a8000 0x0 0x1000>; /* SROT */ ++ interrupts = ; ++ interrupt-names = "combined"; ++ #qcom,sensors = <16>; ++ #thermal-sensor-cells = <1>; ++ }; ++ + cryptobam: dma-controller@704000 { + compatible = "qcom,bam-v1.7.0"; + reg = <0x0 0x00704000 0x0 0x20000>; +@@ -1043,6 +1053,113 @@ + }; + }; + ++ thermal-zones { ++ nss-top-thermal { ++ polling-delay-passive = <250>; ++ polling-delay = <1000>; ++ ++ thermal-sensors = <&tsens 4>; ++ ++ trips { ++ nss-top-crit { ++ temperature = <110000>; ++ hysteresis = <1000>; ++ type = "critical"; ++ }; ++ }; ++ }; ++ ++ nss0-thermal { ++ polling-delay-passive = <250>; ++ polling-delay = <1000>; ++ ++ thermal-sensors = <&tsens 5>; ++ ++ trips { ++ nss-0-crit { ++ temperature = <110000>; ++ hysteresis = <1000>; ++ type = "critical"; ++ }; ++ }; ++ }; ++ ++ wcss-phya0-thermal { ++ polling-delay-passive = <250>; ++ polling-delay = <1000>; ++ ++ thermal-sensors = <&tsens 7>; ++ ++ trips { ++ wcss-phya0-crit { ++ temperature = <110000>; ++ hysteresis = <1000>; ++ type = "critical"; ++ }; ++ }; ++ }; ++ ++ wcss-phya1-thermal { ++ polling-delay-passive = <250>; ++ polling-delay = <1000>; ++ ++ thermal-sensors = <&tsens 8>; ++ ++ trips { ++ wcss-phya1-crit { ++ temperature = <110000>; ++ hysteresis = <1000>; ++ type = "critical"; ++ }; ++ }; ++ }; ++ ++ cluster_thermal: cluster-thermal { ++ polling-delay-passive = <250>; ++ polling-delay = <1000>; ++ ++ thermal-sensors = <&tsens 13>; ++ ++ trips { ++ cluster-crit { ++ temperature = <110000>; ++ hysteresis = <1000>; ++ type = "critical"; ++ }; ++ }; ++ }; ++ ++ lpass-qsdp6-thermal { ++ polling-delay-passive = <250>; ++ polling-delay = <1000>; ++ ++ thermal-sensors = <&tsens 14>; ++ ++ trips { ++ lpass-qsdp6-crit { ++ temperature = <110000>; ++ hysteresis = <1000>; ++ type = "critical"; ++ }; ++ }; ++ }; ++ ++ package-top-thermal { ++ polling-delay-passive = <250>; ++ polling-delay = <1000>; ++ ++ thermal-sensors = <&tsens 15>; ++ ++ trips { ++ package-top-crit { ++ temperature = <110000>; ++ hysteresis = <1000>; ++ type = "critical"; ++ }; ++ }; ++ }; ++ }; ++ + timer { + compatible = "arm,armv8-timer"; + interrupts = , diff --git a/target/linux/qualcommax/patches-6.1/0137-arm64-dts-qcom-ipq6018-rework-cpufreq.patch b/target/linux/qualcommax/patches-6.1/0137-arm64-dts-qcom-ipq6018-rework-cpufreq.patch new file mode 100644 index 000000000..5ad0bcd51 --- /dev/null +++ b/target/linux/qualcommax/patches-6.1/0137-arm64-dts-qcom-ipq6018-rework-cpufreq.patch @@ -0,0 +1,216 @@ +--- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi ++++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi +@@ -41,8 +41,6 @@ + next-level-cache = <&L2_0>; + clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>; + clock-names = "cpu"; +- operating-points-v2 = <&cpu_opp_table>; +- cpu-supply = <&ipq6018_s2>; + }; + + CPU1: cpu@1 { +@@ -53,8 +51,6 @@ + next-level-cache = <&L2_0>; + clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>; + clock-names = "cpu"; +- operating-points-v2 = <&cpu_opp_table>; +- cpu-supply = <&ipq6018_s2>; + }; + + CPU2: cpu@2 { +@@ -65,8 +61,6 @@ + next-level-cache = <&L2_0>; + clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>; + clock-names = "cpu"; +- operating-points-v2 = <&cpu_opp_table>; +- cpu-supply = <&ipq6018_s2>; + }; + + CPU3: cpu@3 { +@@ -77,8 +71,6 @@ + next-level-cache = <&L2_0>; + clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>; + clock-names = "cpu"; +- operating-points-v2 = <&cpu_opp_table>; +- cpu-supply = <&ipq6018_s2>; + }; + + L2_0: l2-cache { +@@ -94,54 +86,6 @@ + }; + }; + +- cpu_opp_table: opp-table-cpu { +- compatible = "operating-points-v2-kryo-cpu"; +- nvmem-cells = <&cpu_speed_bin>; +- opp-shared; +- +- opp-864000000 { +- opp-hz = /bits/ 64 <864000000>; +- opp-microvolt = <725000>; +- opp-supported-hw = <0xf>; +- clock-latency-ns = <200000>; +- }; +- +- opp-1056000000 { +- opp-hz = /bits/ 64 <1056000000>; +- opp-microvolt = <787500>; +- opp-supported-hw = <0xf>; +- clock-latency-ns = <200000>; +- }; +- +- opp-1320000000 { +- opp-hz = /bits/ 64 <1320000000>; +- opp-microvolt = <862500>; +- opp-supported-hw = <0x3>; +- clock-latency-ns = <200000>; +- }; +- +- opp-1440000000 { +- opp-hz = /bits/ 64 <1440000000>; +- opp-microvolt = <925000>; +- opp-supported-hw = <0x3>; +- clock-latency-ns = <200000>; +- }; +- +- opp-1608000000 { +- opp-hz = /bits/ 64 <1608000000>; +- opp-microvolt = <987500>; +- opp-supported-hw = <0x1>; +- clock-latency-ns = <200000>; +- }; +- +- opp-1800000000 { +- opp-hz = /bits/ 64 <1800000000>; +- opp-microvolt = <1062500>; +- opp-supported-hw = <0x1>; +- clock-latency-ns = <200000>; +- }; +- }; +- + pmuv8: pmu { + compatible = "arm,cortex-a53-pmu"; + interrupts = ; +--- /dev/null ++++ b/arch/arm64/boot/dts/qcom/ipq6000-opp.dtsi +@@ -0,0 +1,46 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++ ++/ { ++ cpu_opp_table: opp-table-cpu { ++ compatible = "operating-points-v2-kryo-cpu"; ++ nvmem-cells = <&cpu_speed_bin>; ++ opp-shared; ++ ++ opp-864000000 { ++ opp-hz = /bits/ 64 <864000000>; ++ opp-microvolt = <725000>; ++ opp-supported-hw = <0xf>; ++ clock-latency-ns = <200000>; ++ }; ++ ++ opp-1056000000 { ++ opp-hz = /bits/ 64 <1056000000>; ++ opp-microvolt = <787500>; ++ opp-supported-hw = <0xf>; ++ clock-latency-ns = <200000>; ++ }; ++ ++ opp-1200000000 { ++ opp-hz = /bits/ 64 <1200000000>; ++ opp-microvolt = <862500>; ++ opp-supported-hw = <0x4>; ++ clock-latency-ns = <200000>; ++ }; ++ }; ++}; ++ ++&CPU0 { ++ operating-points-v2 = <&cpu_opp_table>; ++}; ++ ++&CPU1 { ++ operating-points-v2 = <&cpu_opp_table>; ++}; ++ ++&CPU2 { ++ operating-points-v2 = <&cpu_opp_table>; ++}; ++ ++&CPU3 { ++ operating-points-v2 = <&cpu_opp_table>; ++}; +--- /dev/null ++++ b/arch/arm64/boot/dts/qcom/ipq6018-opp.dtsi +@@ -0,0 +1,71 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++ ++/ { ++ cpu_opp_table: opp-table-cpu { ++ compatible = "operating-points-v2-kryo-cpu"; ++ nvmem-cells = <&cpu_speed_bin>; ++ opp-shared; ++ ++ opp-864000000 { ++ opp-hz = /bits/ 64 <864000000>; ++ opp-microvolt = <725000>; ++ opp-supported-hw = <0xf>; ++ clock-latency-ns = <200000>; ++ }; ++ ++ opp-1056000000 { ++ opp-hz = /bits/ 64 <1056000000>; ++ opp-microvolt = <787500>; ++ opp-supported-hw = <0xf>; ++ clock-latency-ns = <200000>; ++ }; ++ ++ opp-1320000000 { ++ opp-hz = /bits/ 64 <1320000000>; ++ opp-microvolt = <862500>; ++ opp-supported-hw = <0x3>; ++ clock-latency-ns = <200000>; ++ }; ++ ++ opp-1440000000 { ++ opp-hz = /bits/ 64 <1440000000>; ++ opp-microvolt = <925000>; ++ opp-supported-hw = <0x3>; ++ clock-latency-ns = <200000>; ++ }; ++ ++ opp-1608000000 { ++ opp-hz = /bits/ 64 <1608000000>; ++ opp-microvolt = <987500>; ++ opp-supported-hw = <0x1>; ++ clock-latency-ns = <200000>; ++ }; ++ ++ opp-1800000000 { ++ opp-hz = /bits/ 64 <1800000000>; ++ opp-microvolt = <1062500>; ++ opp-supported-hw = <0x1>; ++ clock-latency-ns = <200000>; ++ }; ++ }; ++}; ++ ++&CPU0 { ++ operating-points-v2 = <&cpu_opp_table>; ++ cpu-supply = <&ipq6018_s2>; ++}; ++ ++&CPU1 { ++ operating-points-v2 = <&cpu_opp_table>; ++ cpu-supply = <&ipq6018_s2>; ++}; ++ ++&CPU2 { ++ operating-points-v2 = <&cpu_opp_table>; ++ cpu-supply = <&ipq6018_s2>; ++}; ++ ++&CPU3 { ++ operating-points-v2 = <&cpu_opp_table>; ++ cpu-supply = <&ipq6018_s2>; ++}; diff --git a/target/linux/ipq60xx/patches-5.15/1006-clk-qcom-pq6018-workaround-networking-clock-parenting.patch b/target/linux/qualcommax/patches-6.1/0138-clk-qcom-gcc-ipq6018-workaround-ssdk.patch similarity index 57% rename from target/linux/ipq60xx/patches-5.15/1006-clk-qcom-pq6018-workaround-networking-clock-parenting.patch rename to target/linux/qualcommax/patches-6.1/0138-clk-qcom-gcc-ipq6018-workaround-ssdk.patch index 8af6549a8..3d449b33b 100644 --- a/target/linux/ipq60xx/patches-5.15/1006-clk-qcom-pq6018-workaround-networking-clock-parenting.patch +++ b/target/linux/qualcommax/patches-6.1/0138-clk-qcom-gcc-ipq6018-workaround-ssdk.patch @@ -1,34 +1,6 @@ -From e09c2545447f9ff9fbcd3fab90c3a5cab57b51bf Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Tue, 11 Oct 2022 23:38:45 +0200 -Subject: [PATCH] clk: qcom: ipq6018: workaround networking clock parenting - -Currently, networking clocks are only looked up by fw_name however, -these are registered and setup by SSDK and are not available to the -GCC driver at all, so work around that by providing a global name -fallback. - -While we are here, provide global fallback for bias_pll_cc_clk and -bias_pll_nss_noc_clk as well as these are fixed clocks also not available -to the driver. - -Signed-off-by: Robert Marko ---- - drivers/clk/qcom/gcc-ipq6018.c | 39 +++++++++++++++++----------------- - 1 file changed, 19 insertions(+), 20 deletions(-) - --- a/drivers/clk/qcom/gcc-ipq6018.c +++ b/drivers/clk/qcom/gcc-ipq6018.c -@@ -381,7 +381,7 @@ static const struct freq_tbl ftbl_nss_pp - - static const struct clk_parent_data gcc_xo_bias_gpll0_gpll4_nss_ubi32[] = { - { .fw_name = "xo" }, -- { .fw_name = "bias_pll_cc_clk" }, -+ { .fw_name = "bias_pll_cc_clk", .name = "bias_pll_cc_clk" }, - { .hw = &gpll0.clkr.hw }, - { .hw = &gpll4.clkr.hw }, - { .hw = &nss_crypto_pll.clkr.hw }, -@@ -561,12 +561,12 @@ static const struct freq_tbl ftbl_nss_po +@@ -527,12 +527,12 @@ static const struct freq_tbl ftbl_nss_po static const struct clk_parent_data gcc_xo_uniphy0_rx_tx_uniphy1_rx_tx_ubi32_bias[] = { { .fw_name = "xo" }, @@ -46,7 +18,7 @@ Signed-off-by: Robert Marko }; static const struct parent_map -@@ -608,12 +608,12 @@ static const struct freq_tbl ftbl_nss_po +@@ -574,12 +574,12 @@ static const struct freq_tbl ftbl_nss_po static const struct clk_parent_data gcc_xo_uniphy0_tx_rx_uniphy1_tx_rx_ubi32_bias[] = { { .fw_name = "xo" }, @@ -64,7 +36,7 @@ Signed-off-by: Robert Marko }; static const struct parent_map -@@ -749,10 +749,10 @@ static const struct freq_tbl ftbl_nss_po +@@ -715,10 +715,10 @@ static const struct freq_tbl ftbl_nss_po static const struct clk_parent_data gcc_xo_uniphy0_rx_tx_ubi32_bias[] = { { .fw_name = "xo" }, @@ -78,7 +50,7 @@ Signed-off-by: Robert Marko }; static const struct parent_map gcc_xo_uniphy0_rx_tx_ubi32_bias_map[] = { -@@ -785,10 +785,10 @@ static const struct freq_tbl ftbl_nss_po +@@ -751,10 +751,10 @@ static const struct freq_tbl ftbl_nss_po static const struct clk_parent_data gcc_xo_uniphy0_tx_rx_ubi32_bias[] = { { .fw_name = "xo" }, @@ -92,18 +64,3 @@ Signed-off-by: Robert Marko }; static const struct parent_map gcc_xo_uniphy0_tx_rx_ubi32_bias_map[] = { -@@ -1949,12 +1949,11 @@ static const struct freq_tbl ftbl_ubi32_ - { } - }; - --static const struct clk_parent_data -- gcc_xo_gpll0_gpll2_bias_pll_nss_noc_clk[] = { -+static const struct clk_parent_data gcc_xo_gpll0_gpll2_bias_pll_nss_noc_clk[] = { - { .fw_name = "xo" }, - { .hw = &gpll0.clkr.hw }, - { .hw = &gpll2.clkr.hw }, -- { .fw_name = "bias_pll_nss_noc_clk" }, -+ { .fw_name = "bias_pll_nss_noc_clk", .name = "bias_pll_nss_noc_clk" }, - }; - - static const struct parent_map gcc_xo_gpll0_gpll2_bias_pll_nss_noc_clk_map[] = { diff --git a/target/linux/ipq60xx/patches-5.15/1004-clk-qcom-ipq6018-add-missing-clocks.patch b/target/linux/qualcommax/patches-6.1/0139-clk-ipq6018-Add-missing-clocks.patch similarity index 87% rename from target/linux/ipq60xx/patches-5.15/1004-clk-qcom-ipq6018-add-missing-clocks.patch rename to target/linux/qualcommax/patches-6.1/0139-clk-ipq6018-Add-missing-clocks.patch index 54ae9ac33..1d092e7ca 100644 --- a/target/linux/ipq60xx/patches-5.15/1004-clk-qcom-ipq6018-add-missing-clocks.patch +++ b/target/linux/qualcommax/patches-6.1/0139-clk-ipq6018-Add-missing-clocks.patch @@ -1,20 +1,17 @@ -From 0c07b4b2683c327c6a7f9012fa0880ddac257514 Mon Sep 17 00:00:00 2001 +From 714e6b9ab711846cd09b94f83436e23932dd2814 Mon Sep 17 00:00:00 2001 From: anusha Date: Wed, 19 Aug 2020 17:59:22 +0530 -Subject: [PATCH 1004/1011] clk: qcom: ipq6018: add missing clocks - -A large number of clocks are missing for the IPQ6018. Add those clocks -from the downstream QCA 5.4 kernel. +Subject: [PATCH] clk: ipq6018: Add missing clocks Signed-off-by: anusha -Signed-off-by: Alexandru Gagniuc +Change-Id: I85bb1c127a4794ae9347d5babbbfd6490f6abcc7 --- - drivers/clk/qcom/gcc-ipq6018.c | 619 ++++++++++++++++++++++++++++++++- - 1 file changed, 603 insertions(+), 16 deletions(-) + drivers/clk/qcom/gcc-ipq6018.c | 633 ++++++++++++++++++++++++++++++++- + 1 file changed, 616 insertions(+), 17 deletions(-) --- a/drivers/clk/qcom/gcc-ipq6018.c +++ b/drivers/clk/qcom/gcc-ipq6018.c -@@ -219,6 +219,19 @@ static struct clk_rcg2 pcnoc_bfdcd_clk_s +@@ -213,6 +213,19 @@ static struct clk_rcg2 pcnoc_bfdcd_clk_s }, }; @@ -34,7 +31,7 @@ Signed-off-by: Alexandru Gagniuc static struct clk_alpha_pll gpll2_main = { .offset = 0x4a000, .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], -@@ -499,6 +512,19 @@ static struct clk_rcg2 snoc_nssnoc_bfdcd +@@ -491,6 +504,19 @@ static struct clk_rcg2 snoc_nssnoc_bfdcd }, }; @@ -54,7 +51,7 @@ Signed-off-by: Alexandru Gagniuc static const struct freq_tbl ftbl_apss_ahb_clk_src[] = { F(24000000, P_XO, 1, 0, 0), F(25000000, P_GPLL0_DIV2, 16, 0, 0), -@@ -1903,6 +1929,19 @@ static struct clk_rcg2 system_noc_bfdcd_ +@@ -1891,6 +1917,19 @@ static struct clk_rcg2 system_noc_bfdcd_ }, }; @@ -74,7 +71,7 @@ Signed-off-by: Alexandru Gagniuc static const struct freq_tbl ftbl_ubi32_mem_noc_bfdcd_clk_src[] = { F(24000000, P_XO, 1, 0, 0), F(307670000, P_BIAS_PLL_NSS_NOC, 1.5, 0, 0), -@@ -1938,6 +1977,19 @@ static struct clk_rcg2 ubi32_mem_noc_bfd +@@ -1926,6 +1965,19 @@ static struct clk_rcg2 ubi32_mem_noc_bfd }, }; @@ -94,30 +91,7 @@ Signed-off-by: Alexandru Gagniuc static struct clk_branch gcc_apss_axi_clk = { .halt_reg = 0x46020, .halt_check = BRANCH_HALT_VOTED, -@@ -2132,6 +2184,22 @@ static struct clk_branch gcc_blsp1_qup5_ - }, - }; - -+static struct clk_branch gcc_blsp1_qup6_i2c_apps_clk = { -+ .halt_reg = 0x07010, -+ .clkr = { -+ .enable_reg = 0x07010, -+ .enable_mask = BIT(0), -+ .hw.init = &(struct clk_init_data){ -+ .name = "gcc_blsp1_qup6_i2c_apps_clk", -+ .parent_hws = (const struct clk_hw *[]){ -+ &blsp1_qup6_i2c_apps_clk_src.clkr.hw }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ - static struct clk_branch gcc_blsp1_qup6_spi_apps_clk = { - .halt_reg = 0x0700c, - .clkr = { -@@ -2675,6 +2743,454 @@ static struct clk_rcg2 lpass_q6_axim_clk +@@ -2683,6 +2735,454 @@ static struct clk_rcg2 lpass_q6_axim_clk }, }; @@ -572,7 +546,7 @@ Signed-off-by: Alexandru Gagniuc static struct freq_tbl ftbl_rbcpr_wcss_clk_src[] = { F(24000000, P_XO, 1, 0, 0), F(50000000, P_GPLL0, 16, 0, 0), -@@ -2694,6 +3210,23 @@ static struct clk_rcg2 rbcpr_wcss_clk_sr +@@ -2702,6 +3202,22 @@ static struct clk_rcg2 rbcpr_wcss_clk_sr }, }; @@ -591,12 +565,11 @@ Signed-off-by: Alexandru Gagniuc + }, + }, +}; -+ + static struct clk_branch gcc_lpass_core_axim_clk = { .halt_reg = 0x1F028, .clkr = { -@@ -3516,6 +4049,22 @@ static struct clk_branch gcc_prng_ahb_cl +@@ -3523,6 +4039,22 @@ static struct clk_branch gcc_prng_ahb_cl }, }; @@ -619,7 +592,16 @@ Signed-off-by: Alexandru Gagniuc static struct clk_branch gcc_qdss_dap_clk = { .halt_reg = 0x29084, .clkr = { -@@ -4189,6 +4738,9 @@ static struct clk_hw *gcc_ipq6018_hws[] +@@ -3533,7 +4065,7 @@ static struct clk_branch gcc_qdss_dap_cl + .parent_hws = (const struct clk_hw *[]){ + &qdss_dap_sync_clk_src.hw }, + .num_parents = 1, +- .flags = CLK_SET_RATE_PARENT, ++ .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, + .ops = &clk_branch2_ops, + }, + }, +@@ -4199,6 +4731,9 @@ static struct clk_hw *gcc_ipq6018_hws[] &gpll6_out_main_div2.hw, &qdss_dap_sync_clk_src.hw, &qdss_tsctr_div2_clk_src.hw, @@ -629,15 +611,7 @@ Signed-off-by: Alexandru Gagniuc }; static struct clk_regmap *gcc_ipq6018_clks[] = { -@@ -4286,6 +4838,7 @@ static struct clk_regmap *gcc_ipq6018_cl - [GCC_BLSP1_QUP4_SPI_APPS_CLK] = &gcc_blsp1_qup4_spi_apps_clk.clkr, - [GCC_BLSP1_QUP5_I2C_APPS_CLK] = &gcc_blsp1_qup5_i2c_apps_clk.clkr, - [GCC_BLSP1_QUP5_SPI_APPS_CLK] = &gcc_blsp1_qup5_spi_apps_clk.clkr, -+ [GCC_BLSP1_QUP6_I2C_APPS_CLK] = &gcc_blsp1_qup6_i2c_apps_clk.clkr, - [GCC_BLSP1_QUP6_SPI_APPS_CLK] = &gcc_blsp1_qup6_spi_apps_clk.clkr, - [GCC_BLSP1_UART1_APPS_CLK] = &gcc_blsp1_uart1_apps_clk.clkr, - [GCC_BLSP1_UART2_APPS_CLK] = &gcc_blsp1_uart2_apps_clk.clkr, -@@ -4351,6 +4904,7 @@ static struct clk_regmap *gcc_ipq6018_cl +@@ -4362,6 +4897,7 @@ static struct clk_regmap *gcc_ipq6018_cl [GCC_SYS_NOC_PCIE0_AXI_CLK] = &gcc_sys_noc_pcie0_axi_clk.clkr, [GCC_PCIE0_PIPE_CLK] = &gcc_pcie0_pipe_clk.clkr, [GCC_PRNG_AHB_CLK] = &gcc_prng_ahb_clk.clkr, @@ -645,7 +619,7 @@ Signed-off-by: Alexandru Gagniuc [GCC_QDSS_DAP_CLK] = &gcc_qdss_dap_clk.clkr, [GCC_QPIC_AHB_CLK] = &gcc_qpic_ahb_clk.clkr, [GCC_QPIC_CLK] = &gcc_qpic_clk.clkr, -@@ -4392,9 +4946,35 @@ static struct clk_regmap *gcc_ipq6018_cl +@@ -4403,9 +4939,35 @@ static struct clk_regmap *gcc_ipq6018_cl [PCIE0_RCHNG_CLK_SRC] = &pcie0_rchng_clk_src.clkr, [GCC_PCIE0_AXI_S_BRIDGE_CLK] = &gcc_pcie0_axi_s_bridge_clk.clkr, [PCIE0_RCHNG_CLK] = &gcc_pcie0_rchng_clk.clkr, @@ -681,7 +655,7 @@ Signed-off-by: Alexandru Gagniuc [GCC_LPASS_CORE_AXIM_CLK] = &gcc_lpass_core_axim_clk.clkr, [LPASS_CORE_AXIM_CLK_SRC] = &lpass_core_axim_clk_src.clkr, [GCC_LPASS_SNOC_CFG_CLK] = &gcc_lpass_snoc_cfg_clk.clkr, -@@ -4410,6 +4990,9 @@ static struct clk_regmap *gcc_ipq6018_cl +@@ -4421,6 +4983,9 @@ static struct clk_regmap *gcc_ipq6018_cl [GCC_MEM_NOC_UBI32_CLK] = &gcc_mem_noc_ubi32_clk.clkr, [GCC_MEM_NOC_LPASS_CLK] = &gcc_mem_noc_lpass_clk.clkr, [GCC_SNOC_LPASS_CFG_CLK] = &gcc_snoc_lpass_cfg_clk.clkr, @@ -691,14 +665,3 @@ Signed-off-by: Alexandru Gagniuc [QDSS_STM_CLK_SRC] = &qdss_stm_clk_src.clkr, [QDSS_TRACECLKIN_CLK_SRC] = &qdss_traceclkin_clk_src.clkr, }; -@@ -4591,6 +5174,10 @@ static const struct qcom_cc_desc gcc_ipq - static int gcc_ipq6018_probe(struct platform_device *pdev) - { - struct regmap *regmap; -+ struct device *dev = &pdev->dev; -+ -+ clk_register_fixed_rate(dev, "pcie20_phy0_pipe_clk", NULL, 0, -+ 250000000); - - regmap = qcom_cc_map(pdev, &gcc_ipq6018_desc); - if (IS_ERR(regmap)) diff --git a/target/linux/qualcommax/patches-6.1/0903-arm64-dts-ipq6018-add-label-to-clocks.patch b/target/linux/qualcommax/patches-6.1/0903-arm64-dts-ipq6018-add-label-to-clocks.patch new file mode 100644 index 000000000..75c45a2ce --- /dev/null +++ b/target/linux/qualcommax/patches-6.1/0903-arm64-dts-ipq6018-add-label-to-clocks.patch @@ -0,0 +1,11 @@ +--- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi ++++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi +@@ -15,7 +15,7 @@ + #size-cells = <2>; + interrupt-parent = <&intc>; + +- clocks { ++ clocks: clocks { + sleep_clk: sleep-clk { + compatible = "fixed-clock"; + clock-frequency = <32000>; diff --git a/target/linux/ipq60xx/patches-5.15/1013-psci-dont-advertise-OSI-support-for-IPQ6018.patch b/target/linux/qualcommax/patches-6.1/0910-psci-dont-advertise-OSI-support-for-IPQ6018.patch similarity index 85% rename from target/linux/ipq60xx/patches-5.15/1013-psci-dont-advertise-OSI-support-for-IPQ6018.patch rename to target/linux/qualcommax/patches-6.1/0910-psci-dont-advertise-OSI-support-for-IPQ6018.patch index b3b6764ff..5fcb90098 100644 --- a/target/linux/ipq60xx/patches-5.15/1013-psci-dont-advertise-OSI-support-for-IPQ6018.patch +++ b/target/linux/qualcommax/patches-6.1/0910-psci-dont-advertise-OSI-support-for-IPQ6018.patch @@ -1,7 +1,7 @@ -From 3d28dcdffb3642010a6a8f28e384baf95003e798 Mon Sep 17 00:00:00 2001 +From 563db68137475d011b355bfe674d1b7a24778091 Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Sat, 8 Oct 2022 22:26:31 +0200 -Subject: [PATCH 1013/1013] psci: dont advertise OSI support for IPQ6018 +Subject: [PATCH] psci: dont advertise OSI support for IPQ6018 Some older IPQ60xx SoC series boards ship with TrustZone/QSEE firmware older than TZ.WNS.5.1-00084 which will advertise OSI[1] but are broken @@ -19,7 +19,7 @@ Signed-off-by: Robert Marko --- a/drivers/firmware/psci/psci.c +++ b/drivers/firmware/psci/psci.c -@@ -86,6 +86,18 @@ static inline bool psci_has_ext_power_st +@@ -87,6 +87,18 @@ static inline bool psci_has_ext_power_st bool psci_has_osi_support(void) {