From 8fcf7f0915e622426ab3cdf01dba70f9e9d64826 Mon Sep 17 00:00:00 2001 From: coolsnowwolf Date: Tue, 30 Jan 2024 11:00:16 +0800 Subject: [PATCH] ipq807x: rename target to qualcommax --- target/linux/ipq807x/Makefile | 26 - .../ipq807x/base-files/etc/board.d/01_leds | 30 - .../ipq807x/base-files/etc/board.d/02_network | 63 - .../etc/hotplug.d/firmware/11-ath10k-caldata | 20 - .../etc/hotplug.d/firmware/11-ath11k-caldata | 30 - .../ipq807x/base-files/etc/init.d/bootcount | 34 - .../etc/sysctl.d/99-bridge-nf-call.conf | 6 - .../base-files/lib/upgrade/platform.sh | 58 - target/linux/ipq807x/config-5.10 | 518 - .../boot/dts/qcom/ipq8070-tl-er2260t.dts | 665 - .../arm64/boot/dts/qcom/ipq8071-ax3600.dtsi | 498 - .../arm64/boot/dts/qcom/ipq8071-mf269.dts | 539 - .../arch/arm64/boot/dts/qcom/ipq8072-301w.dts | 819 -- .../arm64/boot/dts/qcom/ipq8074-ac-cpu.dtsi | 173 - .../arm64/boot/dts/qcom/ipq8074-ac-nss.dtsi | 256 - .../arm64/boot/dts/qcom/ipq8074-hk-cpu.dtsi | 258 - .../boot/dts/qcom/ipq8074-memory-512m.dtsi | 51 - .../arm64/boot/dts/qcom/ipq8074-nbg7815.dts | 741 - .../arm64/boot/dts/qcom/ipq8078-xtr10890.dts | 969 -- .../files-5.10/drivers/hwmon/emc2305.c | 376 - .../boot/dts/qcom/ipq8070-tl-er2260t.dts | 666 - .../arm64/boot/dts/qcom/ipq8071-ax3600.dts | 71 - .../arm64/boot/dts/qcom/ipq8071-ax3600.dtsi | 494 - .../arch/arm64/boot/dts/qcom/ipq8071-ax6.dts | 39 - .../arm64/boot/dts/qcom/ipq8071-mf269.dts | 587 - .../arch/arm64/boot/dts/qcom/ipq8072-301w.dts | 820 -- .../arm64/boot/dts/qcom/ipq8074-ac-nss.dtsi | 256 - .../arch/arm64/boot/dts/qcom/ipq8074-ess.dtsi | 170 - .../arm64/boot/dts/qcom/ipq8078-xtr10890.dts | 543 - .../files-5.15/drivers/power/qcom/Kconfig | 7 - .../files-5.15/drivers/power/qcom/Makefile | 1 - .../files-5.15/drivers/power/qcom/apm.c | 944 -- .../drivers/regulator/cpr3-npu-regulator.c | 695 - .../drivers/regulator/cpr3-regulator.c | 5112 ------- .../drivers/regulator/cpr3-regulator.h | 1211 -- .../files-5.15/drivers/regulator/cpr3-util.c | 2750 ---- .../drivers/regulator/cpr4-apss-regulator.c | 1819 --- .../files-5.15/include/linux/power/qcom/apm.h | 48 - .../files-5.15/include/soc/qcom/socinfo.h | 463 - target/linux/ipq807x/generic/target.mk | 1 - target/linux/ipq807x/image/generic.mk | 111 - ...oc-sysmon-Expose-the-shutdown-result.patch | 222 - ...q6v5-Query-sysmon-before-graceful-sh.patch | 120 - ...wcss-populate-hardcoded-param-using-.patch | 104 - ...wcss-Add-non-pas-wcss-Q6-support-for.patch | 764 - ...wcss-explicitly-request-exclusive-re.patch | 43 - ...wcss-Fix-return-value-check-in-q6v5_.patch | 32 - ...wcss-Fix-wrong-pointer-passed-to-PTR.patch | 32 - ...qcom-wcss-Remove-unnecessary-PTR_ERR.patch | 89 - ....12-mtd-parsers-Add-Qcom-SMEM-parser.patch | 217 - ...wc-Drop-the-.set_num_vectors-host-op.patch | 120 - ...-interrupt-setup-into-DWC-common-cod.patch | 288 - ...11-PCI-dwc-Rework-MSI-initialization.patch | 199 - ...-Move-link-handling-into-common-code.patch | 603 - ...-dwc-Move-dw_pcie_msi_init-into-core.patch | 272 - ...1-arm64-dts-ipq8074-add-crypto-nodes.patch | 48 - .../102-arm64-dts-ipq8074-add-PRNG-node.patch | 30 - ...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 - ...ngs-clock-qcom-Add-reset-for-WCSSAON.patch | 25 - .../109-clk-qcom-Add-WCSSAON-reset.patch | 25 - ...-Add-support-for-scm-on-IPQ8074-SoCs.patch | 28 - ...com-Enable-Q6v5-WCSS-for-ipq8074-SoC.patch | 158 - ...-socinfo-Add-IPQ8074-SoC-family-ID-s.patch | 35 - ...-net-mdio-ipq4019-add-clock-handling.patch | 49 - ...4-arm64-dts-ipq8074-Add-MDIO-support.patch | 34 - ...dd-IPQ8074-PCIe-Gen3-QMP-PHY-support.patch | 369 - ...ve-GEN3_RELATED-DBI-register-to-comm.patch | 44 - ...-support-for-IPQ60xx-PCIe-controller.patch | 230 - .../119-qcom-backport-register-define.patch | 26 - ...I-qcom-Add-IPQ8074-PCIe-Gen3-support.patch | 48 - ...22-arm64-uaccess-include-scheduler.h.patch | 27 - ...m64-dts-ipq8074-add-networking-nodes.patch | 170 - ...074-gcc-Added-support-for-NSS-clocks.patch | 79 - ...ort-added-for-necessary-clocks-and-r.patch | 352 - ...-Fix-gcc_snoc_bus_timeout_ahb_clk-of.patch | 44 - .../131-arm64-dts-ipq8074-add-SPMI-bus.patch | 41 - ...qcom_spmi-Add-PMD9655-SPMI-regulator.patch | 38 - ...pmi-SMPS-range-is-added-to-support-P.patch | 22 - ...pmi-Initialize-slew-rate-only-if-req.patch | 35 - ...pmi-Add-support-for-VMPWM_CTL-subtyp.patch | 159 - ...dhc-Fixed-SDR104-mode-card-detection.patch | 53 - ...ulator-Add-separate-voltage-range-fo.patch | 49 - ...dts-ipq8074-add-SPMI-PMIC-regulators.patch | 84 - ...074-clk-apss-Added-APSS-clock-driver.patch | 328 - ...-make-apss-clock-as-child-of-mailbox.patch | 105 - ...arm64-dts-ipq8074-add-APPS-CPU-clock.patch | 70 - ...-arm64-dts-ipq8074-add-label-to-cpus.patch | 26 - .../143-arm64-dts-ipq8074-Add-WLAN-node.patch | 133 - ...ipq8074-add-NSS-reserved-memory-node.patch | 28 - ...-disable-SW_COLLAPSE-for-USB-GDSCR-s.patch | 29 - ...q8074-SW-workaround-for-UBI-PLL-lock.patch | 46 - ...074-fix-gcc_blsp1_ahb_clk-properties.patch | 41 - ...c-wcss-disable-auto-boot-for-IPQ8074.patch | 47 - ...74-add-missing-reserved-memory-nodes.patch | 65 - ...4-add-q6_etr-memory-region-to-remote.patch | 24 - ...ermal-qcom-tsens-Add-IPQ8074-support.patch | 99 - ...tsens-add-timeout-to-get_tem_tsens_v.patch | 55 - ...-arm64-dts-ipq8074-add-thermal-nodes.patch | 167 - ...s-ipq8074-disable-USB-phy-by-default.patch | 27 - ...-arm64-dts-ipq8074-Add-QUP6-I2C-node.patch | 41 - ...-EMC2301-2-3-5-fan-controller-driver.patch | 51 - .../600-qca-nss-ecm-support-CORE.patch | 741 - .../602-qca-add-pppoe-offload-support.patch | 588 - ...-identify-ingress-shaping-done-for-e.patch | 74 - ...ore-Replace-nss-keyword-with-offload.patch | 76 - ...5-qca-add-add-nss-bridge-mgr-support.patch | 97 - ...-qca-nss-ecm-bonding-add-bond_get_id.patch | 74 - ...dd-bridge-join-and-leave-netdev-cmds.patch | 11 - .../720-net-phy-add-aqr-phys.patch | 142 - ...hy-aquantia-enable-AQR112-and-AQR412.patch | 154 - ...aquantia-fix-system-side-protocol-mi.patch | 34 - ...y-aquantia-Add-AQR113-driver-support.patch | 43 - ...ntia-add-PHY_IDs-for-AQR112-variants.patch | 63 - .../900-arm64-dts-add-OpenWrt-DTS-files.patch | 28 - ...com-Make-QMI-Helpers-user-selectable.patch | 28 - ...a-cache-routines-with-same-API-as-32.patch | 56 - ...-__dma_inv_area-and-__dma_clean_area.patch | 58 - ...om-add-support-for-hw-controlled-RCG.patch | 136 - ...-qcom-ipq8074-add-hw-controlled-flag.patch | 38 - ...egulator-add-Qualcomm-CPR-regulators.patch | 466 - ...s-ssdk-delete-fdb-entry-using-netdev.patch | 32 - ...-arm64-dts-qcom-ipq8074-add-SPMI-bus.patch | 43 - ...4-dts-qcom-ipq8074-Add-QUP5-I2C-node.patch | 40 - ...sm8996-Move-clock-cells-to-QMP-PHY-c.patch | 134 - ...-arm64-dts-qcom-ipq8074-add-MDIO-bus.patch | 36 - ...qcom-socinfo-Add-IPQ8074-family-ID-s.patch | 50 - ...8-arm64-dts-ipq8074-add-SMEM-support.patch | 49 - ...dd-IPQ8074-PCIe-Gen3-QMP-PHY-support.patch | 369 - ...om-ipq8074-enable-the-GICv2m-support.patch | 34 - ...ve-GEN3_RELATED-DBI-register-to-comm.patch | 45 - ...slot-capabilities-using-PCI_EXP_SLTC.patch | 45 - .../0107-PCI-qcom-Add-IPQ60xx-support.patch | 212 - ...08-PCI-qcom-add-IPQ8074-Gen3-support.patch | 45 - ...ermal-qcom-tsens-Add-IPQ8074-support.patch | 99 - ...qcom_spmi-Add-PMD9655-SPMI-regulator.patch | 38 - ...pmi-SMPS-range-is-added-to-support-P.patch | 22 - ...pmi-Initialize-slew-rate-only-if-req.patch | 34 - ...pmi-Add-support-for-VMPWM_CTL-subtyp.patch | 159 - ...dhc-Fixed-SDR104-mode-card-detection.patch | 42 - ...ulator-Add-separate-voltage-range-fo.patch | 48 - ...dts-ipq8074-add-SPMI-PMIC-regulators.patch | 65 - ...k-alpha-pll-add-support-for-APSS-PLL.patch | 47 - ...bindings-for-IPQ8074-APSS-clock-cont.patch | 30 - ...om-Add-IPQ8074-APSS-clock-controller.patch | 220 - ...s-ipc-add-IPQ8074-APSS-clock-control.patch | 39 - ...4-update-APCS-node-due-to-clock-supp.patch | 28 - ...-arm64-dts-ipq8074-add-label-to-cpus.patch | 25 - ...pq8074-add-missing-networking-resets.patch | 62 - ...q8074-disable-USB-GDSC-s-SW_COLLAPSE.patch | 30 - ...074-SW-workaround-for-UBI32-PLL-lock.patch | 31 - ...lk-qcom-ipq8074-add-PPE-crypto-clock.patch | 61 - ...egulator-add-Qualcomm-CPR-regulators.patch | 66 - .../0301-power-Add-Qualcomm-APM.patch | 27 - .../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 - ...0900-arm64-dts-add-OpenWrt-DTS-files.patch | 28 - ...a-cache-routines-with-same-API-as-32.patch | 29 - ...-__dma_inv_area-and-__dma_clean_area.patch | 56 - .../ipq807x/patches-5.15/0905-export-ns.patch | 37 - target/linux/qualcommax/Makefile | 21 + .../config-5.15 => qualcommax/config-6.1} | 194 +- .../arm64/boot/dts/qcom/ipq8070-cax1800.dts | 322 + .../arm64/boot/dts/qcom/ipq8070-rm2-6.dts | 250 + .../arm64/boot/dts/qcom/ipq8071-ax3600.dts | 0 .../arm64/boot/dts/qcom/ipq8071-ax3600.dtsi | 190 + .../arch/arm64/boot/dts/qcom/ipq8071-ax6.dts | 0 .../arm64/boot/dts/qcom/ipq8071-eap102.dts | 389 + .../arm64/boot/dts/qcom/ipq8071-mf269.dts | 432 + .../arch/arm64/boot/dts/qcom/ipq8072-301w.dts | 409 + .../arm64/boot/dts/qcom/ipq8072-aw1000.dts | 352 + .../arm64/boot/dts/qcom/ipq8072-ax9000.dts | 343 + .../arm64/boot/dts/qcom/ipq8072-dl-wrx36.dts | 243 + .../arch/arm64/boot/dts/qcom/ipq8072-haze.dts | 307 + .../arm64/boot/dts/qcom/ipq8072-wax218.dts | 191 + .../arm64/boot/dts/qcom/ipq8072-wax620.dts | 200 + .../arm64/boot/dts/qcom/ipq8072-wpq873.dts | 486 + .../arm64/boot/dts/qcom/ipq8074-512m.dtsi | 0 .../arm64/boot/dts/qcom/ipq8074-ac-cpu.dtsi | 52 - .../boot/dts/qcom/ipq8074-cpr-regulator.dtsi | 2 + .../arch/arm64/boot/dts/qcom/ipq8074-ess.dtsi | 531 + .../arm64/boot/dts/qcom/ipq8074-hk-cpu.dtsi | 72 - .../arm64/boot/dts/qcom/ipq8074-nbg7815.dts | 101 +- .../arm64/boot/dts/qcom/ipq8074-rax120v2.dts | 552 + .../arm64/boot/dts/qcom/ipq8074-wax630.dts | 252 + .../boot/dts/qcom/ipq8074-wxr-5950ax12.dts | 376 + .../{ipq807x => qualcommax}/image/Makefile | 1 - target/linux/qualcommax/image/ipq807x.mk | 271 + .../ipq807x/base-files/etc/board.d/01_leds | 47 + .../ipq807x/base-files/etc/board.d/02_network | 66 + .../etc/hotplug.d/firmware/11-ath11k-caldata | 50 + .../etc/hotplug.d/ieee80211/11_fix_wifi_mac | 22 + .../ipq807x/base-files/etc/init.d/bootcount | 13 + .../ipq807x/base-files/lib/upgrade/buffalo.sh | 55 + .../ipq807x/base-files/lib/upgrade/mmc.sh | 16 +- .../base-files/lib/upgrade/platform.sh | 69 + .../linux/qualcommax/ipq807x/config-default | 30 + target/linux/qualcommax/ipq807x/target.mk | 7 + ...64-dts-qcom-ipq8074-add-A53-PLL-node.patch | 32 + ...tsens-Add-support-for-combined-inter.patch | 134 + ...tsens-Allow-configuring-min-and-max-.patch | 101 + ...al-drivers-tsens-Add-IPQ8074-support.patch | 74 + ...-dts-qcom-ipq8074-add-thermal-nodes.patch} | 20 +- ...-dts-qcom-ipq8074-add-clocks-to-APCS.patch | 29 + ...-qcom-ipq8074-convert-to-parent-data.patch | 3601 +++++ ...k-qcom-ipq8074-add-missing-networkin.patch | 39 + ...pq8074-add-missing-networking-resets.patch | 41 + ...074-populate-fw_name-for-all-parents.patch | 152 + ...pq8074-pass-XO-and-sleep-clocks-to-G.patch | 36 + ...v6.2-arm64-dts-qcom-add-PMP8074-DTSI.patch | 149 + ...s-qcom-ipq8074-hk01-add-VQMMC-supply.patch | 37 + ...ts-qcom-hk01-use-GPIO-flags-for-tlmm.patch | 42 + ...m64-dts-qcom-ipq8074-Fix-up-comments.patch | 82 + ...pq8074-align-TLMM-pin-configuration-.patch | 60 + ...pq8074-set-Gen2-PCIe-pcie-max-link-s.patch | 24 + ...om-Add-support-for-IPQ8074-Gen3-port.patch | 26 + ...q8074-populate-fw_name-for-usb3phy-s.patch | 38 + ...m-ipq8074-add-critical-thermal-trips.patch | 199 + ...-qcom-ids-Add-IDs-for-IPQ8174-family.patch | 29 + ...q-qcom-nvmem-add-support-for-IPQ8074.patch | 112 + ...q6018-add-the-GPLL0-clock-also-as-cl.patch | 43 + ...pq8074-include-the-GPLL0-as-clock-pr.patch | 32 + ...2-introduce-support-for-multiple-con.patch | 203 + ...8074-rework-nss_port5-6-clock-to-mul.patch | 129 + ...s-ipq8074-add-reserved-memory-nodes.patch} | 19 +- ...pq8074-pass-QMP-PCI-PHY-PIPE-clocks-.patch | 30 + ...qcom-ipq8074-use-msi-parent-for-PCIe.patch | 43 + ...emoteproc-qcom-Add-PRNG-proxy-clock.patch} | 6 +- ...oteproc-qcom-Add-secure-PIL-support.patch} | 4 +- ...dd-support-for-split-q6-m3-wlan-fir.patch} | 6 +- ...c-qcom-Add-ssr-subdevice-identifier.patch} | 4 +- ...pdate-regmap-offsets-for-halt-regis.patch} | 6 +- ...gs-clock-qcom-Add-reset-for-WCSSAON.patch} | 15 +- .../0118-clk-qcom-Add-WCSSAON-reset.patch} | 12 +- ...-wcss-disable-auto-boot-for-IPQ8074.patch} | 13 +- ...om-Enable-Q6v5-WCSS-for-ipq8074-SoC.patch} | 22 +- ...121-arm64-dts-ipq8074-Add-WLAN-node.patch} | 7 +- ...122-arm64-dts-ipq8074-add-CPU-clock.patch} | 35 +- ...8074-add-cooling-cells-to-CPU-nodes.patch} | 16 +- ...64-dts-qcom-ipq8074-add-QFPROM-fuses.patch | 128 + ...4-dts-qcom-ipq8074-add-CPU-OPP-table.patch | 102 + .../0900-power-Add-Qualcomm-APM.patch | 1047 ++ ...egulator-add-Qualcomm-CPR-regulators.patch | 12144 ++++++++++++++++ ...m64-dts-ipq8074-add-label-to-clocks.patch} | 6 +- 252 files changed, 25634 insertions(+), 37520 deletions(-) delete mode 100644 target/linux/ipq807x/Makefile delete mode 100644 target/linux/ipq807x/base-files/etc/board.d/01_leds delete mode 100644 target/linux/ipq807x/base-files/etc/board.d/02_network delete mode 100644 target/linux/ipq807x/base-files/etc/hotplug.d/firmware/11-ath10k-caldata delete mode 100644 target/linux/ipq807x/base-files/etc/hotplug.d/firmware/11-ath11k-caldata delete mode 100755 target/linux/ipq807x/base-files/etc/init.d/bootcount delete mode 100644 target/linux/ipq807x/base-files/etc/sysctl.d/99-bridge-nf-call.conf delete mode 100644 target/linux/ipq807x/base-files/lib/upgrade/platform.sh delete mode 100644 target/linux/ipq807x/config-5.10 delete mode 100644 target/linux/ipq807x/files-5.10/arch/arm64/boot/dts/qcom/ipq8070-tl-er2260t.dts delete mode 100644 target/linux/ipq807x/files-5.10/arch/arm64/boot/dts/qcom/ipq8071-ax3600.dtsi delete mode 100644 target/linux/ipq807x/files-5.10/arch/arm64/boot/dts/qcom/ipq8071-mf269.dts delete mode 100644 target/linux/ipq807x/files-5.10/arch/arm64/boot/dts/qcom/ipq8072-301w.dts delete mode 100644 target/linux/ipq807x/files-5.10/arch/arm64/boot/dts/qcom/ipq8074-ac-cpu.dtsi delete mode 100644 target/linux/ipq807x/files-5.10/arch/arm64/boot/dts/qcom/ipq8074-ac-nss.dtsi delete mode 100644 target/linux/ipq807x/files-5.10/arch/arm64/boot/dts/qcom/ipq8074-hk-cpu.dtsi delete mode 100644 target/linux/ipq807x/files-5.10/arch/arm64/boot/dts/qcom/ipq8074-memory-512m.dtsi delete mode 100644 target/linux/ipq807x/files-5.10/arch/arm64/boot/dts/qcom/ipq8074-nbg7815.dts delete mode 100644 target/linux/ipq807x/files-5.10/arch/arm64/boot/dts/qcom/ipq8078-xtr10890.dts delete mode 100644 target/linux/ipq807x/files-5.10/drivers/hwmon/emc2305.c delete mode 100644 target/linux/ipq807x/files-5.15/arch/arm64/boot/dts/qcom/ipq8070-tl-er2260t.dts delete mode 100644 target/linux/ipq807x/files-5.15/arch/arm64/boot/dts/qcom/ipq8071-ax3600.dts delete mode 100644 target/linux/ipq807x/files-5.15/arch/arm64/boot/dts/qcom/ipq8071-ax3600.dtsi delete mode 100644 target/linux/ipq807x/files-5.15/arch/arm64/boot/dts/qcom/ipq8071-ax6.dts delete mode 100644 target/linux/ipq807x/files-5.15/arch/arm64/boot/dts/qcom/ipq8071-mf269.dts delete mode 100644 target/linux/ipq807x/files-5.15/arch/arm64/boot/dts/qcom/ipq8072-301w.dts delete mode 100644 target/linux/ipq807x/files-5.15/arch/arm64/boot/dts/qcom/ipq8074-ac-nss.dtsi delete mode 100644 target/linux/ipq807x/files-5.15/arch/arm64/boot/dts/qcom/ipq8074-ess.dtsi delete mode 100644 target/linux/ipq807x/files-5.15/arch/arm64/boot/dts/qcom/ipq8078-xtr10890.dts delete mode 100644 target/linux/ipq807x/files-5.15/drivers/power/qcom/Kconfig delete mode 100644 target/linux/ipq807x/files-5.15/drivers/power/qcom/Makefile delete mode 100644 target/linux/ipq807x/files-5.15/drivers/power/qcom/apm.c delete mode 100644 target/linux/ipq807x/files-5.15/drivers/regulator/cpr3-npu-regulator.c delete mode 100644 target/linux/ipq807x/files-5.15/drivers/regulator/cpr3-regulator.c delete mode 100644 target/linux/ipq807x/files-5.15/drivers/regulator/cpr3-regulator.h delete mode 100644 target/linux/ipq807x/files-5.15/drivers/regulator/cpr3-util.c delete mode 100644 target/linux/ipq807x/files-5.15/drivers/regulator/cpr4-apss-regulator.c delete mode 100644 target/linux/ipq807x/files-5.15/include/linux/power/qcom/apm.h delete mode 100644 target/linux/ipq807x/files-5.15/include/soc/qcom/socinfo.h delete mode 100644 target/linux/ipq807x/generic/target.mk delete mode 100644 target/linux/ipq807x/image/generic.mk delete mode 100644 target/linux/ipq807x/patches-5.10/001-v5.11-remoteproc-sysmon-Expose-the-shutdown-result.patch delete mode 100644 target/linux/ipq807x/patches-5.10/002-v5.11-remoteproc-qcom-q6v5-Query-sysmon-before-graceful-sh.patch delete mode 100644 target/linux/ipq807x/patches-5.10/003-v5.13-remoteproc-qcom-wcss-populate-hardcoded-param-using-.patch delete mode 100644 target/linux/ipq807x/patches-5.10/004-v5.13-remoteproc-qcom-wcss-Add-non-pas-wcss-Q6-support-for.patch delete mode 100644 target/linux/ipq807x/patches-5.10/005-v5.13-remoteproc-qcom-wcss-explicitly-request-exclusive-re.patch delete mode 100644 target/linux/ipq807x/patches-5.10/006-v5.13-remoteproc-qcom-wcss-Fix-return-value-check-in-q6v5_.patch delete mode 100644 target/linux/ipq807x/patches-5.10/007-v5.13-remoteproc-qcom-wcss-Fix-wrong-pointer-passed-to-PTR.patch delete mode 100644 target/linux/ipq807x/patches-5.10/008-v5.13-remoteproc-qcom-wcss-Remove-unnecessary-PTR_ERR.patch delete mode 100644 target/linux/ipq807x/patches-5.10/009-5.12-mtd-parsers-Add-Qcom-SMEM-parser.patch delete mode 100644 target/linux/ipq807x/patches-5.10/010-v5.11-PCI-dwc-Drop-the-.set_num_vectors-host-op.patch delete mode 100644 target/linux/ipq807x/patches-5.10/011-v5.11-PCI-dwc-Move-MSI-interrupt-setup-into-DWC-common-cod.patch delete mode 100644 target/linux/ipq807x/patches-5.10/012-v5.11-PCI-dwc-Rework-MSI-initialization.patch delete mode 100644 target/linux/ipq807x/patches-5.10/013-v5.11-PCI-dwc-Move-link-handling-into-common-code.patch delete mode 100644 target/linux/ipq807x/patches-5.10/014-v5.11-PCI-dwc-Move-dw_pcie_msi_init-into-core.patch delete mode 100644 target/linux/ipq807x/patches-5.10/101-arm64-dts-ipq8074-add-crypto-nodes.patch delete mode 100644 target/linux/ipq807x/patches-5.10/102-arm64-dts-ipq8074-add-PRNG-node.patch delete mode 100644 target/linux/ipq807x/patches-5.10/103-remoteproc-qcom-Add-PRNG-proxy-clock.patch delete mode 100644 target/linux/ipq807x/patches-5.10/104-remoteproc-qcom-Add-secure-PIL-support.patch delete mode 100644 target/linux/ipq807x/patches-5.10/105-remoteproc-qcom-Add-support-for-split-q6-m3-wlan-fir.patch delete mode 100644 target/linux/ipq807x/patches-5.10/106-remoteproc-qcom-Add-ssr-subdevice-identifier.patch delete mode 100644 target/linux/ipq807x/patches-5.10/107-remoteproc-qcom-Update-regmap-offsets-for-halt-regis.patch delete mode 100644 target/linux/ipq807x/patches-5.10/108-dt-bindings-clock-qcom-Add-reset-for-WCSSAON.patch delete mode 100644 target/linux/ipq807x/patches-5.10/109-clk-qcom-Add-WCSSAON-reset.patch delete mode 100644 target/linux/ipq807x/patches-5.10/110-arm64-dts-Add-support-for-scm-on-IPQ8074-SoCs.patch delete mode 100644 target/linux/ipq807x/patches-5.10/111-arm64-dts-qcom-Enable-Q6v5-WCSS-for-ipq8074-SoC.patch delete mode 100644 target/linux/ipq807x/patches-5.10/112-qcom-socinfo-Add-IPQ8074-SoC-family-ID-s.patch delete mode 100644 target/linux/ipq807x/patches-5.10/113-net-mdio-ipq4019-add-clock-handling.patch delete mode 100644 target/linux/ipq807x/patches-5.10/114-arm64-dts-ipq8074-Add-MDIO-support.patch delete mode 100644 target/linux/ipq807x/patches-5.10/115-phy-qcom-qmp-Add-IPQ8074-PCIe-Gen3-QMP-PHY-support.patch delete mode 100644 target/linux/ipq807x/patches-5.10/116-PCI-dwc-tegra-move-GEN3_RELATED-DBI-register-to-comm.patch delete mode 100644 target/linux/ipq807x/patches-5.10/117-PCI-qcom-add-support-for-IPQ60xx-PCIe-controller.patch delete mode 100644 target/linux/ipq807x/patches-5.10/119-qcom-backport-register-define.patch delete mode 100644 target/linux/ipq807x/patches-5.10/120-PCI-qcom-Add-IPQ8074-PCIe-Gen3-support.patch delete mode 100644 target/linux/ipq807x/patches-5.10/122-arm64-uaccess-include-scheduler.h.patch delete mode 100644 target/linux/ipq807x/patches-5.10/123-arm64-dts-ipq8074-add-networking-nodes.patch delete mode 100644 target/linux/ipq807x/patches-5.10/125-ipq8074-gcc-Added-support-for-NSS-clocks.patch delete mode 100644 target/linux/ipq807x/patches-5.10/126-clk-ipq8074-Support-added-for-necessary-clocks-and-r.patch delete mode 100644 target/linux/ipq807x/patches-5.10/127-clk-qcom-ipq8074-Fix-gcc_snoc_bus_timeout_ahb_clk-of.patch delete mode 100644 target/linux/ipq807x/patches-5.10/131-arm64-dts-ipq8074-add-SPMI-bus.patch delete mode 100644 target/linux/ipq807x/patches-5.10/132-regulator-qcom_spmi-Add-PMD9655-SPMI-regulator.patch delete mode 100644 target/linux/ipq807x/patches-5.10/133-regulator-qcom_spmi-SMPS-range-is-added-to-support-P.patch delete mode 100644 target/linux/ipq807x/patches-5.10/134-regulator-qcom_spmi-Initialize-slew-rate-only-if-req.patch delete mode 100644 target/linux/ipq807x/patches-5.10/135-regulator-qcom_spmi-Add-support-for-VMPWM_CTL-subtyp.patch delete mode 100644 target/linux/ipq807x/patches-5.10/136-ipq807x-sdhc-Fixed-SDR104-mode-card-detection.patch delete mode 100644 target/linux/ipq807x/patches-5.10/137-ipq807x-spmi-regulator-Add-separate-voltage-range-fo.patch delete mode 100644 target/linux/ipq807x/patches-5.10/138-arm64-dts-ipq8074-add-SPMI-PMIC-regulators.patch delete mode 100644 target/linux/ipq807x/patches-5.10/139-ipq8074-clk-apss-Added-APSS-clock-driver.patch delete mode 100644 target/linux/ipq807x/patches-5.10/140-clk-qcom-ipq8074-make-apss-clock-as-child-of-mailbox.patch delete mode 100644 target/linux/ipq807x/patches-5.10/141-arm64-dts-ipq8074-add-APPS-CPU-clock.patch delete mode 100644 target/linux/ipq807x/patches-5.10/142-arm64-dts-ipq8074-add-label-to-cpus.patch delete mode 100644 target/linux/ipq807x/patches-5.10/143-arm64-dts-ipq8074-Add-WLAN-node.patch delete mode 100644 target/linux/ipq807x/patches-5.10/144-arm64-dts-ipq8074-add-NSS-reserved-memory-node.patch delete mode 100644 target/linux/ipq807x/patches-5.10/145-clk-qcom-ipq8074-disable-SW_COLLAPSE-for-USB-GDSCR-s.patch delete mode 100644 target/linux/ipq807x/patches-5.10/146-clk-qcom-ipq8074-SW-workaround-for-UBI-PLL-lock.patch delete mode 100644 target/linux/ipq807x/patches-5.10/148-clk-ipq8074-fix-gcc_blsp1_ahb_clk-properties.patch delete mode 100644 target/linux/ipq807x/patches-5.10/149-remoteproc-wcss-disable-auto-boot-for-IPQ8074.patch delete mode 100644 target/linux/ipq807x/patches-5.10/150-arm64-dts-ipq8074-add-missing-reserved-memory-nodes.patch delete mode 100644 target/linux/ipq807x/patches-5.10/151-arm64-dts-ipq8074-add-q6_etr-memory-region-to-remote.patch delete mode 100644 target/linux/ipq807x/patches-5.10/152-thermal-qcom-tsens-Add-IPQ8074-support.patch delete mode 100644 target/linux/ipq807x/patches-5.10/154-drivers-thermal-tsens-add-timeout-to-get_tem_tsens_v.patch delete mode 100644 target/linux/ipq807x/patches-5.10/155-arm64-dts-ipq8074-add-thermal-nodes.patch delete mode 100644 target/linux/ipq807x/patches-5.10/156-arm64-dts-ipq8074-disable-USB-phy-by-default.patch delete mode 100644 target/linux/ipq807x/patches-5.10/157-arm64-dts-ipq8074-Add-QUP6-I2C-node.patch delete mode 100644 target/linux/ipq807x/patches-5.10/158-hwmon-Add-SMSC-EMC2301-2-3-5-fan-controller-driver.patch delete mode 100644 target/linux/ipq807x/patches-5.10/600-qca-nss-ecm-support-CORE.patch delete mode 100644 target/linux/ipq807x/patches-5.10/602-qca-add-pppoe-offload-support.patch delete mode 100644 target/linux/ipq807x/patches-5.10/603-net-core-Flag-to-identify-ingress-shaping-done-for-e.patch delete mode 100644 target/linux/ipq807x/patches-5.10/604-net-core-Replace-nss-keyword-with-offload.patch delete mode 100644 target/linux/ipq807x/patches-5.10/605-qca-add-add-nss-bridge-mgr-support.patch delete mode 100644 target/linux/ipq807x/patches-5.10/606-qca-nss-ecm-bonding-add-bond_get_id.patch delete mode 100644 target/linux/ipq807x/patches-5.10/607-qca-nss-ecm-Add-bridge-join-and-leave-netdev-cmds.patch delete mode 100644 target/linux/ipq807x/patches-5.10/720-net-phy-add-aqr-phys.patch delete mode 100644 target/linux/ipq807x/patches-5.10/722-net-phy-aquantia-enable-AQR112-and-AQR412.patch delete mode 100644 target/linux/ipq807x/patches-5.10/723-net-phy-aquantia-fix-system-side-protocol-mi.patch delete mode 100644 target/linux/ipq807x/patches-5.10/724-net-phy-aquantia-Add-AQR113-driver-support.patch delete mode 100644 target/linux/ipq807x/patches-5.10/725-net-phy-aquantia-add-PHY_IDs-for-AQR112-variants.patch delete mode 100644 target/linux/ipq807x/patches-5.10/900-arm64-dts-add-OpenWrt-DTS-files.patch delete mode 100644 target/linux/ipq807x/patches-5.10/901-soc-qcom-Make-QMI-Helpers-user-selectable.patch delete mode 100644 target/linux/ipq807x/patches-5.10/902-arm64-provide-dma-cache-routines-with-same-API-as-32.patch delete mode 100644 target/linux/ipq807x/patches-5.10/903-arm64-mm-export-__dma_inv_area-and-__dma_clean_area.patch delete mode 100644 target/linux/ipq807x/patches-5.10/991-clk-qcom-add-support-for-hw-controlled-RCG.patch delete mode 100644 target/linux/ipq807x/patches-5.10/992-clk-qcom-ipq8074-add-hw-controlled-flag.patch delete mode 100644 target/linux/ipq807x/patches-5.10/998-regulator-add-Qualcomm-CPR-regulators.patch delete mode 100644 target/linux/ipq807x/patches-5.10/999-5.10-qca-nss-ssdk-delete-fdb-entry-using-netdev.patch delete mode 100644 target/linux/ipq807x/patches-5.15/0001-v5.16-arm64-dts-qcom-ipq8074-add-SPMI-bus.patch delete mode 100644 target/linux/ipq807x/patches-5.15/0002-v5.16-arm64-dts-qcom-ipq8074-Add-QUP5-I2C-node.patch delete mode 100644 target/linux/ipq807x/patches-5.15/0003-v5.16-arm64-dts-qcom-msm8996-Move-clock-cells-to-QMP-PHY-c.patch delete mode 100644 target/linux/ipq807x/patches-5.15/0006-v5.17-arm64-dts-qcom-ipq8074-add-MDIO-bus.patch delete mode 100644 target/linux/ipq807x/patches-5.15/0007-v5.16-soc-qcom-socinfo-Add-IPQ8074-family-ID-s.patch delete mode 100644 target/linux/ipq807x/patches-5.15/0011-v5.18-arm64-dts-ipq8074-add-SMEM-support.patch delete mode 100644 target/linux/ipq807x/patches-5.15/0103-phy-qcom-qmp-Add-IPQ8074-PCIe-Gen3-QMP-PHY-support.patch delete mode 100644 target/linux/ipq807x/patches-5.15/0104-arm64-dts-qcom-ipq8074-enable-the-GICv2m-support.patch delete mode 100644 target/linux/ipq807x/patches-5.15/0105-PCI-dwc-tegra-move-GEN3_RELATED-DBI-register-to-comm.patch delete mode 100644 target/linux/ipq807x/patches-5.15/0106-PCI-qcom-Define-slot-capabilities-using-PCI_EXP_SLTC.patch delete mode 100644 target/linux/ipq807x/patches-5.15/0107-PCI-qcom-Add-IPQ60xx-support.patch delete mode 100644 target/linux/ipq807x/patches-5.15/0108-PCI-qcom-add-IPQ8074-Gen3-support.patch delete mode 100644 target/linux/ipq807x/patches-5.15/0121-thermal-qcom-tsens-Add-IPQ8074-support.patch delete mode 100644 target/linux/ipq807x/patches-5.15/0123-regulator-qcom_spmi-Add-PMD9655-SPMI-regulator.patch delete mode 100644 target/linux/ipq807x/patches-5.15/0124-regulator-qcom_spmi-SMPS-range-is-added-to-support-P.patch delete mode 100644 target/linux/ipq807x/patches-5.15/0125-regulator-qcom_spmi-Initialize-slew-rate-only-if-req.patch delete mode 100644 target/linux/ipq807x/patches-5.15/0126-regulator-qcom_spmi-Add-support-for-VMPWM_CTL-subtyp.patch delete mode 100644 target/linux/ipq807x/patches-5.15/0127-ipq807x-sdhc-Fixed-SDR104-mode-card-detection.patch delete mode 100644 target/linux/ipq807x/patches-5.15/0128-ipq807x-spmi-regulator-Add-separate-voltage-range-fo.patch delete mode 100644 target/linux/ipq807x/patches-5.15/0129-arm64-dts-ipq8074-add-SPMI-PMIC-regulators.patch delete mode 100644 target/linux/ipq807x/patches-5.15/0130-clk-qcom-clk-alpha-pll-add-support-for-APSS-PLL.patch delete mode 100644 target/linux/ipq807x/patches-5.15/0131-clk-qcom-Add-DT-bindings-for-IPQ8074-APSS-clock-cont.patch delete mode 100644 target/linux/ipq807x/patches-5.15/0132-clk-qcom-Add-IPQ8074-APSS-clock-controller.patch delete mode 100644 target/linux/ipq807x/patches-5.15/0133-mailbox-qcom-apcs-ipc-add-IPQ8074-APSS-clock-control.patch delete mode 100644 target/linux/ipq807x/patches-5.15/0134-arm64-dts-ipq8074-update-APCS-node-due-to-clock-supp.patch delete mode 100644 target/linux/ipq807x/patches-5.15/0136-arm64-dts-ipq8074-add-label-to-cpus.patch delete mode 100644 target/linux/ipq807x/patches-5.15/0139-clk-qcom-ipq8074-add-missing-networking-resets.patch delete mode 100644 target/linux/ipq807x/patches-5.15/0141-clk-qcom-ipq8074-disable-USB-GDSC-s-SW_COLLAPSE.patch delete mode 100644 target/linux/ipq807x/patches-5.15/0142-clk-qcom-ipq8074-SW-workaround-for-UBI32-PLL-lock.patch delete mode 100644 target/linux/ipq807x/patches-5.15/0145-clk-qcom-ipq8074-add-PPE-crypto-clock.patch delete mode 100644 target/linux/ipq807x/patches-5.15/0300-regulator-add-Qualcomm-CPR-regulators.patch delete mode 100644 target/linux/ipq807x/patches-5.15/0301-power-Add-Qualcomm-APM.patch delete mode 100644 target/linux/ipq807x/patches-5.15/0600-5.15-qca-nss-ecm-support-CORE.patch delete mode 100644 target/linux/ipq807x/patches-5.15/0601-5.15-netfilter-export-udp_get_timeouts-function.patch delete mode 100644 target/linux/ipq807x/patches-5.15/0602-5.15-qca-add-pppoe-offload-support.patch delete mode 100644 target/linux/ipq807x/patches-5.15/0603-net-core-Flag-to-identify-ingress-shaping-done-for-e.patch delete mode 100644 target/linux/ipq807x/patches-5.15/0605-5.15-qca-add-add-nss-bridge-mgr-support.patch delete mode 100644 target/linux/ipq807x/patches-5.15/0606-5.15-qca-nss-ecm-bonding-add-bond_get_id.patch delete mode 100644 target/linux/ipq807x/patches-5.15/0607-5.15-qca-nss-ecm-Add-bridge-join-and-leave-netdev-cmds.patch delete mode 100644 target/linux/ipq807x/patches-5.15/0900-arm64-dts-add-OpenWrt-DTS-files.patch delete mode 100644 target/linux/ipq807x/patches-5.15/0902-5.15-arm64-provide-dma-cache-routines-with-same-API-as-32.patch delete mode 100644 target/linux/ipq807x/patches-5.15/0903-5.15-arm64-mm-export-__dma_inv_area-and-__dma_clean_area.patch delete mode 100644 target/linux/ipq807x/patches-5.15/0905-export-ns.patch create mode 100644 target/linux/qualcommax/Makefile rename target/linux/{ipq807x/config-5.15 => qualcommax/config-6.1} (79%) create mode 100644 target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8070-cax1800.dts create mode 100644 target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8070-rm2-6.dts rename target/linux/{ipq807x/files-5.10 => qualcommax/files}/arch/arm64/boot/dts/qcom/ipq8071-ax3600.dts (100%) create mode 100644 target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8071-ax3600.dtsi rename target/linux/{ipq807x/files-5.10 => qualcommax/files}/arch/arm64/boot/dts/qcom/ipq8071-ax6.dts (100%) create mode 100644 target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8071-eap102.dts create mode 100644 target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8071-mf269.dts create mode 100644 target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8072-301w.dts create mode 100644 target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8072-aw1000.dts create mode 100644 target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8072-ax9000.dts create mode 100644 target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8072-dl-wrx36.dts create mode 100644 target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8072-haze.dts create mode 100644 target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8072-wax218.dts create mode 100644 target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8072-wax620.dts create mode 100644 target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8072-wpq873.dts rename target/linux/{ipq807x/files-5.15 => qualcommax/files}/arch/arm64/boot/dts/qcom/ipq8074-512m.dtsi (100%) rename target/linux/{ipq807x/files-5.15 => qualcommax/files}/arch/arm64/boot/dts/qcom/ipq8074-ac-cpu.dtsi (70%) rename target/linux/{ipq807x/files-5.15 => qualcommax/files}/arch/arm64/boot/dts/qcom/ipq8074-cpr-regulator.dtsi (99%) create mode 100644 target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8074-ess.dtsi rename target/linux/{ipq807x/files-5.15 => qualcommax/files}/arch/arm64/boot/dts/qcom/ipq8074-hk-cpu.dtsi (74%) rename target/linux/{ipq807x/files-5.15 => qualcommax/files}/arch/arm64/boot/dts/qcom/ipq8074-nbg7815.dts (80%) create mode 100644 target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8074-rax120v2.dts create mode 100644 target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8074-wax630.dts create mode 100644 target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8074-wxr-5950ax12.dts rename target/linux/{ipq807x => qualcommax}/image/Makefile (87%) create mode 100644 target/linux/qualcommax/image/ipq807x.mk create mode 100644 target/linux/qualcommax/ipq807x/base-files/etc/board.d/01_leds create mode 100644 target/linux/qualcommax/ipq807x/base-files/etc/board.d/02_network create mode 100644 target/linux/qualcommax/ipq807x/base-files/etc/hotplug.d/firmware/11-ath11k-caldata create mode 100644 target/linux/qualcommax/ipq807x/base-files/etc/hotplug.d/ieee80211/11_fix_wifi_mac create mode 100755 target/linux/qualcommax/ipq807x/base-files/etc/init.d/bootcount create mode 100644 target/linux/qualcommax/ipq807x/base-files/lib/upgrade/buffalo.sh rename target/linux/{ => qualcommax}/ipq807x/base-files/lib/upgrade/mmc.sh (80%) create mode 100644 target/linux/qualcommax/ipq807x/base-files/lib/upgrade/platform.sh create mode 100644 target/linux/qualcommax/ipq807x/config-default create mode 100644 target/linux/qualcommax/ipq807x/target.mk create mode 100644 target/linux/qualcommax/patches-6.1/0001-v6.2-arm64-dts-qcom-ipq8074-add-A53-PLL-node.patch create mode 100644 target/linux/qualcommax/patches-6.1/0002-v6.2-thermal-drivers-tsens-Add-support-for-combined-inter.patch create mode 100644 target/linux/qualcommax/patches-6.1/0003-v6.2-thermal-drivers-tsens-Allow-configuring-min-and-max-.patch create mode 100644 target/linux/qualcommax/patches-6.1/0004-v6.2-thermal-drivers-tsens-Add-IPQ8074-support.patch rename target/linux/{ipq807x/patches-5.15/0122-arm64-dts-ipq8074-add-thermal-nodes.patch => qualcommax/patches-6.1/0005-v6.2-arm64-dts-qcom-ipq8074-add-thermal-nodes.patch} (82%) create mode 100644 target/linux/qualcommax/patches-6.1/0006-v6.2-arm64-dts-qcom-ipq8074-add-clocks-to-APCS.patch create mode 100644 target/linux/qualcommax/patches-6.1/0007-v6.2-clk-qcom-ipq8074-convert-to-parent-data.patch create mode 100644 target/linux/qualcommax/patches-6.1/0009-v6.2-dt-bindings-clock-qcom-ipq8074-add-missing-networkin.patch create mode 100644 target/linux/qualcommax/patches-6.1/0010-v6.2-clk-qcom-ipq8074-add-missing-networking-resets.patch create mode 100644 target/linux/qualcommax/patches-6.1/0011-v6.2-clk-qcom-ipq8074-populate-fw_name-for-all-parents.patch create mode 100644 target/linux/qualcommax/patches-6.1/0012-v6.2-arm64-dts-qcom-ipq8074-pass-XO-and-sleep-clocks-to-G.patch create mode 100644 target/linux/qualcommax/patches-6.1/0013-v6.2-arm64-dts-qcom-add-PMP8074-DTSI.patch create mode 100644 target/linux/qualcommax/patches-6.1/0014-v6.2-arm64-dts-qcom-ipq8074-hk01-add-VQMMC-supply.patch create mode 100644 target/linux/qualcommax/patches-6.1/0015-v6.2-arm64-dts-qcom-hk01-use-GPIO-flags-for-tlmm.patch create mode 100644 target/linux/qualcommax/patches-6.1/0016-v6.2-arm64-dts-qcom-ipq8074-Fix-up-comments.patch create mode 100644 target/linux/qualcommax/patches-6.1/0017-v6.2-arm64-dts-qcom-ipq8074-align-TLMM-pin-configuration-.patch create mode 100644 target/linux/qualcommax/patches-6.1/0019-v6.3-arm64-dts-qcom-ipq8074-set-Gen2-PCIe-pcie-max-link-s.patch create mode 100644 target/linux/qualcommax/patches-6.1/0020-v6.3-PCI-qcom-Add-support-for-IPQ8074-Gen3-port.patch create mode 100644 target/linux/qualcommax/patches-6.1/0021-v6.3-clk-qcom-ipq8074-populate-fw_name-for-usb3phy-s.patch create mode 100644 target/linux/qualcommax/patches-6.1/0023-v6.5-arm64-dts-qcom-ipq8074-add-critical-thermal-trips.patch create mode 100644 target/linux/qualcommax/patches-6.1/0024-v6.7-dt-bindings-arm-qcom-ids-Add-IDs-for-IPQ8174-family.patch create mode 100644 target/linux/qualcommax/patches-6.1/0025-v6.7-cpufreq-qcom-nvmem-add-support-for-IPQ8074.patch create mode 100644 target/linux/qualcommax/patches-6.1/0027-v6.7-clk-qcom-apss-ipq6018-add-the-GPLL0-clock-also-as-cl.patch create mode 100644 target/linux/qualcommax/patches-6.1/0028-v6.7-arm64-dts-qcom-ipq8074-include-the-GPLL0-as-clock-pr.patch create mode 100644 target/linux/qualcommax/patches-6.1/0100-clk-qcom-clk-rcg2-introduce-support-for-multiple-con.patch create mode 100644 target/linux/qualcommax/patches-6.1/0101-clk-qcom-gcc-ipq8074-rework-nss_port5-6-clock-to-mul.patch rename target/linux/{ipq807x/patches-5.15/0101-arm64-dts-ipq8074-add-reserved-memory-nodes.patch => qualcommax/patches-6.1/0102-arm64-dts-ipq8074-add-reserved-memory-nodes.patch} (82%) create mode 100644 target/linux/qualcommax/patches-6.1/0110-arm64-dts-qcom-ipq8074-pass-QMP-PCI-PHY-PIPE-clocks-.patch create mode 100644 target/linux/qualcommax/patches-6.1/0111-arm64-dts-qcom-ipq8074-use-msi-parent-for-PCIe.patch rename target/linux/{ipq807x/patches-5.15/0111-remoteproc-qcom-Add-PRNG-proxy-clock.patch => qualcommax/patches-6.1/0112-remoteproc-qcom-Add-PRNG-proxy-clock.patch} (95%) rename target/linux/{ipq807x/patches-5.15/0112-remoteproc-qcom-Add-secure-PIL-support.patch => qualcommax/patches-6.1/0113-remoteproc-qcom-Add-secure-PIL-support.patch} (96%) rename target/linux/{ipq807x/patches-5.15/0113-remoteproc-qcom-Add-support-for-split-q6-m3-wlan-fir.patch => qualcommax/patches-6.1/0114-remoteproc-qcom-Add-support-for-split-q6-m3-wlan-fir.patch} (94%) rename target/linux/{ipq807x/patches-5.15/0114-remoteproc-qcom-Add-ssr-subdevice-identifier.patch => qualcommax/patches-6.1/0115-remoteproc-qcom-Add-ssr-subdevice-identifier.patch} (85%) rename target/linux/{ipq807x/patches-5.15/0115-remoteproc-qcom-Update-regmap-offsets-for-halt-regis.patch => qualcommax/patches-6.1/0116-remoteproc-qcom-Update-regmap-offsets-for-halt-regis.patch} (92%) rename target/linux/{ipq807x/patches-5.15/0116-dt-bindings-clock-qcom-Add-reset-for-WCSSAON.patch => qualcommax/patches-6.1/0117-dt-bindings-clock-qcom-Add-reset-for-WCSSAON.patch} (72%) rename target/linux/{ipq807x/patches-5.15/0117-clk-qcom-Add-WCSSAON-reset.patch => qualcommax/patches-6.1/0118-clk-qcom-Add-WCSSAON-reset.patch} (59%) rename target/linux/{ipq807x/patches-5.15/0118-remoteproc-wcss-disable-auto-boot-for-IPQ8074.patch => qualcommax/patches-6.1/0119-remoteproc-wcss-disable-auto-boot-for-IPQ8074.patch} (73%) rename target/linux/{ipq807x/patches-5.15/0119-arm64-dts-qcom-Enable-Q6v5-WCSS-for-ipq8074-SoC.patch => qualcommax/patches-6.1/0120-arm64-dts-qcom-Enable-Q6v5-WCSS-for-ipq8074-SoC.patch} (87%) rename target/linux/{ipq807x/patches-5.15/0120-arm64-dts-ipq8074-Add-WLAN-node.patch => qualcommax/patches-6.1/0121-arm64-dts-ipq8074-Add-WLAN-node.patch} (97%) rename target/linux/{ipq807x/patches-5.15/0135-arm64-dts-ipq8074-add-CPU-clock-and-regulator.patch => qualcommax/patches-6.1/0122-arm64-dts-ipq8074-add-CPU-clock.patch} (59%) rename target/linux/{ipq807x/patches-5.15/0137-arm64-dts-ipq8074-add-cooling-cells-to-CPU-nodes.patch => qualcommax/patches-6.1/0123-arm64-dts-ipq8074-add-cooling-cells-to-CPU-nodes.patch} (81%) create mode 100644 target/linux/qualcommax/patches-6.1/0129-arm64-dts-qcom-ipq8074-add-QFPROM-fuses.patch create mode 100644 target/linux/qualcommax/patches-6.1/0130-arm64-dts-qcom-ipq8074-add-CPU-OPP-table.patch create mode 100644 target/linux/qualcommax/patches-6.1/0900-power-Add-Qualcomm-APM.patch create mode 100644 target/linux/qualcommax/patches-6.1/0901-regulator-add-Qualcomm-CPR-regulators.patch rename target/linux/{ipq807x/patches-5.15/0901-arm64-dts-ipq8074-add-label-to-clocks.patch => qualcommax/patches-6.1/0902-arm64-dts-ipq8074-add-label-to-clocks.patch} (83%) diff --git a/target/linux/ipq807x/Makefile b/target/linux/ipq807x/Makefile deleted file mode 100644 index 4fad49310..000000000 --- a/target/linux/ipq807x/Makefile +++ /dev/null @@ -1,26 +0,0 @@ -include $(TOPDIR)/rules.mk - -ARCH:=aarch64 -BOARD:=ipq807x -BOARDNAME:=Qualcomm Atheros IPQ807x -FEATURES:=squashfs ramdisk fpu nand rtc emmc -KERNELNAME:=Image dtbs -CPU_TYPE:=cortex-a53 -SUBTARGETS:=generic - -KERNEL_PATCHVER:=5.10 -KERNEL_TESTING_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 \ - ath11k-firmware-ipq8074 kmod-ath11k-ahb \ - autocore-arm htop wpad-openssl uboot-envtools \ - kmod-qca-nss-dp kmod-qca-nss-drv-64 \ - kmod-qca-nss-drv-pppoe-64 kmod-qca-nss-ecm-64 \ - kmod-qca-nss-drv-bridge-mgr-64 kmod-qca-nss-drv-vlan-mgr-64 \ - nss-firmware-ipq8074 luci-app-ipsec-vpnd \ - luci-app-unblockmusic luci-app-zerotier - -$(eval $(call BuildTarget)) diff --git a/target/linux/ipq807x/base-files/etc/board.d/01_leds b/target/linux/ipq807x/base-files/etc/board.d/01_leds deleted file mode 100644 index fd998f0b3..000000000 --- a/target/linux/ipq807x/base-files/etc/board.d/01_leds +++ /dev/null @@ -1,30 +0,0 @@ - -. /lib/functions/leds.sh -. /lib/functions/uci-defaults.sh - -board=$(board_name) - -board_config_update - -case $board in -xiaomi,ax3600|\ -redmi,ax6) - ucidef_set_led_netdev "wan" "WAN" "blue:network" "eth0" - ;; -tplink,tl-er2260t) - ucidef_set_led_netdev "SFP1_active" "SFP1_ACTIVE" "green:sfp1" "eth5" - ucidef_set_led_netdev "SFP2_active" "SFP2_ACTIVE" "green:sfp2" "eth4" - ;; -qnap,301w) - ucidef_set_led_netdev "lan1" "LAN1" "green:lan1" "eth0" - ucidef_set_led_netdev "lan2" "LAN2" "green:lan2" "eth1" - ucidef_set_led_netdev "lan3" "LAN3" "green:lan3" "eth2" - ucidef_set_led_netdev "lan4" "LAN4" "green:lan4" "eth3" - ucidef_set_led_netdev "10G_1" "10G_1" "green:10g_1" "eth4" - ucidef_set_led_netdev "10G_2" "10G_2" "green:10g_2" "eth5" - ;; -esac - -board_config_flush - -exit 0 diff --git a/target/linux/ipq807x/base-files/etc/board.d/02_network b/target/linux/ipq807x/base-files/etc/board.d/02_network deleted file mode 100644 index 34874cb42..000000000 --- a/target/linux/ipq807x/base-files/etc/board.d/02_network +++ /dev/null @@ -1,63 +0,0 @@ -# -# Copyright (c) 2015 The Linux Foundation. All rights reserved. -# Copyright (c) 2011-2015 OpenWrt.org -# - -. /lib/functions/uci-defaults.sh -. /lib/functions/system.sh - -ipq807x_setup_interfaces() -{ - local board="$1" - - case "$board" in - zyxel,nbg7815|\ - qnap,301w) - ucidef_set_interfaces_lan_wan "eth0 eth1 eth2 eth3 eth4" "eth5" - ;; - redmi,ax6|\ - xiaomi,ax3600) - ucidef_set_interfaces_lan_wan "eth1 eth2 eth3" "eth0" - ;; - zte,mf269) - ucidef_set_interfaces_lan_wan "eth0" "eth1" - ;; - tplink,tl-er2260t) - ucidef_set_interfaces_lan_wan "eth0 eth1 eth2 eth3 eth5" "eth4" - ;; - tplink,xtr10890) - ucidef_set_interfaces_lan_wan "eth0 eth1 eth2 eth3 eth4" "eth5" - ;; - *) - echo "Unsupported hardware. Network interfaces not initialized" - ;; - esac -} - -ipq807x_setup_macs() -{ - local board="$1" - local lan_mac="" - local wan_mac="" - local label_mac="" - - case "$board" in - zte,mf269) - wan_mac=$(mtd_get_mac_binary mac 0x0) - lan_mac=$(macaddr_add "$wan_mac" 1) - label_mac=$wan_mac - ;; - 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) -ipq807x_setup_interfaces $board -ipq807x_setup_macs $board -board_config_flush - -exit 0 diff --git a/target/linux/ipq807x/base-files/etc/hotplug.d/firmware/11-ath10k-caldata b/target/linux/ipq807x/base-files/etc/hotplug.d/firmware/11-ath10k-caldata deleted file mode 100644 index e5daf2dba..000000000 --- a/target/linux/ipq807x/base-files/etc/hotplug.d/firmware/11-ath10k-caldata +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/sh - -[ -e /lib/firmware/$FIRMWARE ] && exit 0 - -. /lib/functions/caldata.sh - -board=$(board_name) - -case "$FIRMWARE" in -"ath10k/cal-pci-0000:01:00.0.bin") - case "$board" in - xiaomi,ax3600) - caldata_extract "0:art" 0x33000 0x844 - ;; - esac - ;; -*) - exit 1 - ;; -esac diff --git a/target/linux/ipq807x/base-files/etc/hotplug.d/firmware/11-ath11k-caldata b/target/linux/ipq807x/base-files/etc/hotplug.d/firmware/11-ath11k-caldata deleted file mode 100644 index cfa197454..000000000 --- a/target/linux/ipq807x/base-files/etc/hotplug.d/firmware/11-ath11k-caldata +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/sh - -[ -e /lib/firmware/$FIRMWARE ] && exit 0 - -. /lib/functions/caldata.sh - -board=$(board_name) - -case "$FIRMWARE" in -"ath11k/IPQ8074/hw2.0/cal-ahb-c000000.wifi.bin") - case "$board" in - qnap,301w|\ - redmi,ax6|\ - xiaomi,ax3600|\ - xiaomi,ax9000|\ - zyxel,nbg7815) - caldata_extract "0:art" 0x1000 0x20000 - ;; - zte,mf269) - caldata_extract "0:ART" 0x1000 0x20000 - ;; - tplink,xtr10890) - caldata_extract "0:ART" 0x1000 0x20000 - ;; - esac - ;; -*) - exit 1 - ;; -esac diff --git a/target/linux/ipq807x/base-files/etc/init.d/bootcount b/target/linux/ipq807x/base-files/etc/init.d/bootcount deleted file mode 100755 index d018b9af5..000000000 --- a/target/linux/ipq807x/base-files/etc/init.d/bootcount +++ /dev/null @@ -1,34 +0,0 @@ -#!/bin/sh /etc/rc.common - -START=99 - -. /lib/functions/system.sh - -boot() { - case $(board_name) in - redmi,ax6|\ - xiaomi,ax3600) - # OTA handling should not be used. Reset it just in case. - fw_setenv flag_ota_reboot 0 - # Not strictly needed but useful to handle partition crash condition - fw_setenv flag_boot_success 1 - ;; - zte,mf269) - mac_addr=$(mtd_get_mac_binary mac 0x0) - macaddr_add $mac_addr 2 > /sys/devices/platform/soc/c000000.wifi/ieee80211/phy0/macaddress - macaddr_add $mac_addr 3 > /sys/devices/platform/soc/c000000.wifi/ieee80211/phy1/macaddress - wifi - ;; - qnap,301w) - ssdk_sh debug phy set 0 0x4004c441 0x8 1> /dev/kmsg 2>&1 - ssdk_sh debug phy set 0 0x40070000 0x3200 1> /dev/kmsg 2>&1 - ssdk_sh debug phy set 8 0x4004c441 0x8 1> /dev/kmsg 2>&1 - ssdk_sh debug phy set 8 0x40070000 0x3200 1> /dev/kmsg 2>&1 - ;; - esac - - for q in $(ls /sys/class/net/eth*/queues/rx-*/rps_cpus); do echo f > $q; done - for q in $(ls /sys/class/net/eth*/queues/rx-*/rps_flow_cnt); do echo 4096 > $q; done - for q in $(ls /sys/class/net/eth*/queues/tx-*/xps_cpus); do echo f > $q; done - echo 32768 > /proc/sys/net/core/rps_sock_flow_entries -} diff --git a/target/linux/ipq807x/base-files/etc/sysctl.d/99-bridge-nf-call.conf b/target/linux/ipq807x/base-files/etc/sysctl.d/99-bridge-nf-call.conf deleted file mode 100644 index af92caa64..000000000 --- a/target/linux/ipq807x/base-files/etc/sysctl.d/99-bridge-nf-call.conf +++ /dev/null @@ -1,6 +0,0 @@ -# disable bridge netfilter module - -net.bridge.bridge-nf-call-arptables=0 -net.bridge.bridge-nf-call-iptables=0 -net.bridge.bridge-nf-call-ip6tables=0 - diff --git a/target/linux/ipq807x/base-files/lib/upgrade/platform.sh b/target/linux/ipq807x/base-files/lib/upgrade/platform.sh deleted file mode 100644 index a1f3cd233..000000000 --- a/target/linux/ipq807x/base-files/lib/upgrade/platform.sh +++ /dev/null @@ -1,58 +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' - -platform_check_image() { - return 0; -} - -platform_do_upgrade() { - case "$(board_name)" in - zyxel,nbg7815|\ - qnap,301w) - kernelname="0:HLOS" - rootfsname="rootfs" - mmc_do_upgrade "$1" - ;; - redmi,ax6|\ - xiaomi,ax3600|\ - xiaomi,ax9000) - part_num="$(fw_printenv -n flag_boot_rootfs)" - if [ "$part_num" -eq "1" ]; then - CI_UBIPART="rootfs_1" - target_num=1 - # Reset fail flag for the current partition - # With both partition set to fail, the partition 2 (bit 1) - # is loaded - fw_setenv flag_try_sys2_failed 0 - else - CI_UBIPART="rootfs" - target_num=0 - # Reset fail flag for the current partition - # or uboot will skip the loading of this partition - fw_setenv flag_try_sys1_failed 0 - fi - - # Tell uboot to switch partition - fw_setenv flag_boot_rootfs $target_num - fw_setenv flag_last_success $target_num - - # Reset success flag - fw_setenv flag_boot_success 0 - - nand_do_upgrade "$1" - ;; - zte,mf269) - nand_do_upgrade "$1" - ;; - tplink,tl-er2260t|\ - tplink,xtr10890) - nand_do_upgrade "$1" - ;; - *) - default_do_upgrade "$1" - ;; - esac -} diff --git a/target/linux/ipq807x/config-5.10 b/target/linux/ipq807x/config-5.10 deleted file mode 100644 index e848b0dcc..000000000 --- a/target/linux/ipq807x/config-5.10 +++ /dev/null @@ -1,518 +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_MMAP_RND_BITS=18 -CONFIG_ARCH_MMAP_RND_BITS_MAX=24 -CONFIG_ARCH_MMAP_RND_BITS_MIN=18 -CONFIG_ARCH_MMAP_RND_COMPAT_BITS=11 -CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=11 -CONFIG_ARCH_PROC_KCORE_TEXT=y -CONFIG_ARCH_QCOM=y -CONFIG_ARCH_RANDOM=y -CONFIG_ARCH_SELECT_MEMORY_MODEL=y -CONFIG_ARCH_SPARSEMEM_DEFAULT=y -CONFIG_ARCH_SPARSEMEM_ENABLE=y -CONFIG_ARCH_STACKWALK=y -CONFIG_ARCH_SUSPEND_POSSIBLE=y -CONFIG_ARCH_USES_HIGH_VMA_FLAGS=y -CONFIG_ARM64=y -CONFIG_ARM64_4K_PAGES=y -CONFIG_ARM64_AMU_EXTN=y -CONFIG_ARM64_BTI=y -CONFIG_ARM64_CNP=y -CONFIG_ARM64_CRYPTO=y -CONFIG_ARM64_E0PD=y -CONFIG_ARM64_ERRATUM_1165522=y -CONFIG_ARM64_ERRATUM_1286807=y -CONFIG_ARM64_ERRATUM_1418040=y -CONFIG_ARM64_HW_AFDBM=y -CONFIG_ARM64_MODULE_PLTS=y -CONFIG_ARM64_MTE=y -CONFIG_ARM64_PAGE_SHIFT=12 -CONFIG_ARM64_PAN=y -CONFIG_ARM64_PA_BITS=48 -CONFIG_ARM64_PA_BITS_48=y -CONFIG_ARM64_PTR_AUTH=y -CONFIG_ARM64_RAS_EXTN=y -CONFIG_ARM64_SVE=y -CONFIG_ARM64_TAGGED_ADDR_ABI=y -CONFIG_ARM64_TLB_RANGE=y -CONFIG_ARM64_VA_BITS=39 -CONFIG_ARM64_VA_BITS_39=y -CONFIG_ARM64_VHE=y -CONFIG_ARM64_WORKAROUND_REPEAT_TLBI=y -CONFIG_ARM64_WORKAROUND_SPECULATIVE_AT=y -# CONFIG_ARMV8_DEPRECATED is not set -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_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_ARM_SCMI_PROTOCOL is not set -CONFIG_ARM_SMCCC_SOC_ID=y -CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y -CONFIG_BLK_DEV_LOOP=y -CONFIG_BLK_MQ_PCI=y -CONFIG_BLK_MQ_VIRTIO=y -CONFIG_BLK_PM=y -CONFIG_BLOCK_COMPAT=y -CONFIG_CAVIUM_TX2_ERRATUM_219=y -CONFIG_CLKDEV_LOOKUP=y -CONFIG_CLONE_BACKWARDS=y -CONFIG_COMMON_CLK=y -CONFIG_COMMON_CLK_QCOM=y -CONFIG_COMPAT=y -# CONFIG_COMPAT_32BIT_TIME is not set -CONFIG_COMPAT_BINFMT_ELF=y -CONFIG_COMPAT_NETLINK_MESSAGES=y -CONFIG_COMPAT_OLD_SIGACTION=y -CONFIG_COREDUMP=y -CONFIG_CPUFREQ_DT=y -CONFIG_CPUFREQ_DT_PLATDEV=y -CONFIG_CPU_FREQ=y -CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y -# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set -CONFIG_CPU_FREQ_GOV_ATTR_SET=y -CONFIG_CPU_FREQ_GOV_COMMON=y -# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set -CONFIG_CPU_FREQ_GOV_ONDEMAND=y -CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set -# 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_LADDER=y -CONFIG_CPU_IDLE_MULTIPLE_DRIVERS=y -CONFIG_CPU_PM=y -CONFIG_CPU_RMAP=y -CONFIG_CPU_THERMAL=y -CONFIG_CRC16=y -CONFIG_CRYPTO_ACOMP2=y -CONFIG_CRYPTO_AEAD=y -CONFIG_CRYPTO_AEAD2=y -CONFIG_CRYPTO_CBC=y -CONFIG_CRYPTO_CTR=y -CONFIG_CRYPTO_DEFLATE=y -CONFIG_CRYPTO_DEV_QCE=y -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=y -CONFIG_CRYPTO_HASH2=y -CONFIG_CRYPTO_HASH_INFO=y -CONFIG_CRYPTO_HW=y -CONFIG_CRYPTO_LIB_DES=y -CONFIG_CRYPTO_LIB_SHA256=y -CONFIG_CRYPTO_LZO=y -CONFIG_CRYPTO_MANAGER=y -CONFIG_CRYPTO_MANAGER2=y -CONFIG_CRYPTO_NULL2=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_ETHTOOL_NETLINK=y -CONFIG_FIXED_PHY=y -CONFIG_FIX_EARLYCON_MEM=y -CONFIG_FRAME_POINTER=y -CONFIG_FUJITSU_ERRATUM_010001=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_GETTIMEOFDAY=y -CONFIG_GENERIC_IDLE_POLL_SETUP=y -CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y -CONFIG_GENERIC_IRQ_MULTI_HANDLER=y -CONFIG_GENERIC_IRQ_SHOW=y -CONFIG_GENERIC_IRQ_SHOW_LEVEL=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=y -CONFIG_GPIOLIB_IRQCHIP=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_HOLES_IN_ZONE=y -CONFIG_HWSPINLOCK=y -CONFIG_HWSPINLOCK_QCOM=y -CONFIG_HZ=250 -# CONFIG_HZ_100 is not set -CONFIG_HZ_250=y -CONFIG_HZ_PERIODIC=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_ILLEGAL_POINTER_VALUE=0xdead000000000000 -CONFIG_INITRAMFS_SOURCE="" -# CONFIG_IPQ_APSS_6018 is not set -CONFIG_IPQ_APSS_8074=y -# CONFIG_IPQ_APSS_PLL is not set -# CONFIG_IPQ_GCC_4019 is not set -# CONFIG_IPQ_GCC_6018 is not set -# CONFIG_IPQ_GCC_806X is not set -CONFIG_IPQ_GCC_8074=y -# 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_LEDS_TLC591XX=y -CONFIG_LIBFDT=y -CONFIG_LLD_VERSION=0 -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_MHI_BUS=y -CONFIG_MHI_BUS_DEBUG=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_SWITCHDEV=y -CONFIG_NLS=y -CONFIG_NR_CPUS=256 -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_OF_NET=y -CONFIG_OLD_SIGSUSPEND3=y -CONFIG_PADATA=y -CONFIG_PARTITION_PERCPU=y -CONFIG_PCI=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 is not set -# CONFIG_PINCTRL_IPQ8064 is not set -CONFIG_PINCTRL_IPQ8074=y -# 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 is not set -# 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=y -# CONFIG_POWER_RESET_QCOM_PON is not set -CONFIG_POWER_SUPPLY=y -CONFIG_PRINTK_TIME=y -# CONFIG_QCOM_A53PLL is not set -# CONFIG_QCOM_AOSS_QMP is not set -CONFIG_QCOM_APCS_IPC=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_COINCELL is not set -# CONFIG_QCOM_COMMAND_DB is not set -# CONFIG_QCOM_CPR is not set -CONFIG_QCOM_EBI2=y -# 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_QMI_HELPERS=y -# CONFIG_QCOM_RMTFS_MEM is not set -# CONFIG_QCOM_RPMH is not set -CONFIG_QCOM_RPROC_COMMON=y -CONFIG_QCOM_SCM=y -# CONFIG_QCOM_SCM_DOWNLOAD_MODE_DEFAULT is not set -# CONFIG_QCOM_SMD_RPM is not set -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_SYSMON is not set -CONFIG_QCOM_TSENS=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_QRTR=y -CONFIG_QRTR_MHI=y -CONFIG_QRTR_SMD=y -CONFIG_QRTR_TUN=y -CONFIG_QUEUED_RWLOCKS=y -CONFIG_QUEUED_SPINLOCKS=y -CONFIG_RANDOMIZE_BASE=y -CONFIG_RANDOMIZE_MODULE_REGION_FULL=y -CONFIG_RATIONAL=y -CONFIG_RCU_NEED_SEGCBLIST=y -CONFIG_RCU_STALL_COMMON=y -CONFIG_REGMAP=y -CONFIG_REGMAP_I2C=y -CONFIG_REGMAP_MMIO=y -CONFIG_REGMAP_SPMI=y -CONFIG_REGULATOR=y -CONFIG_REGULATOR_FIXED_VOLTAGE=y -# CONFIG_REGULATOR_QCOM_LABIBB is not set -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_QCOM_GLINK=y -CONFIG_RPMSG_QCOM_GLINK_RPM=y -CONFIG_RPMSG_QCOM_GLINK_SMEM=y -CONFIG_RPMSG_QCOM_SMD=y -CONFIG_RPS=y -CONFIG_RWSEM_SPIN_ON_OWNER=y -CONFIG_SCHED_MC=y -CONFIG_SCHED_THERMAL_PRESSURE=y -# 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_SENSORS_EMC2305 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_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_SOC_BUS=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_SYSVIPC_COMPAT=y -CONFIG_SYS_SUPPORTS_HUGETLBFS=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_NETLINK=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_UACCE is not set -CONFIG_UBIFS_FS=y -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_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/ipq807x/files-5.10/arch/arm64/boot/dts/qcom/ipq8070-tl-er2260t.dts b/target/linux/ipq807x/files-5.10/arch/arm64/boot/dts/qcom/ipq8070-tl-er2260t.dts deleted file mode 100644 index 89b36ac01..000000000 --- a/target/linux/ipq807x/files-5.10/arch/arm64/boot/dts/qcom/ipq8070-tl-er2260t.dts +++ /dev/null @@ -1,665 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* Copyright (c) 2020 The Linux Foundation. All rights reserved. - */ - -/dts-v1/; - -#include "ipq8074.dtsi" -#include "ipq8074-hk-cpu.dtsi" -#include -#include -#include -/ { - #address-cells = <0x2>; - #size-cells = <0x2>; - model = "TP-Link TL-ER2260T"; - compatible = "tplink,tl-er2260t", "qcom,ipq8074"; - qcom,msm-id = <0x143 0x0>; - interrupt-parent = <&intc>; - - aliases { - led-boot = &led_sys; - led-failsafe = &led_sys; - led-running = &led_sys; - led-upgrade = &led_sys; - serial0 = &blsp1_uart5; - - ethernet0 = "/soc/dp1"; - ethernet1 = "/soc/dp2"; - ethernet2 = "/soc/dp3"; - ethernet3 = "/soc/dp4"; - ethernet4 = "/soc/dp5"; - ethernet5 = "/soc/dp6"; - }; - - chosen { - stdout-path = "serial0"; - bootargs-append = " root=/dev/ubiblock0_1"; - }; - - gpio_keys { - compatible = "gpio-keys"; - pinctrl-0 = <&button_pins>; - pinctrl-names = "default"; - - reset { - label = "reset"; - linux,code = ; - gpios = <&tlmm 50 GPIO_ACTIVE_LOW>; - linux,input-type = <1>; - debounce-interval = <60>; - }; - }; - - leds { - compatible = "gpio-leds"; - pinctrl-0 = <&leds_pins>; - pinctrl-names = "default"; - - led_sys: sys { - label = "green:sys"; - gpios = <&tlmm 21 GPIO_ACTIVE_HIGH>; - }; - - usb { - label = "green:usb"; - gpios = <&tlmm 22 GPIO_ACTIVE_HIGH>; - linux,default-trigger = "usbport"; - }; - - sfp1-green { - label = "green:sfp1"; - gpios = <&tlmm 51 GPIO_ACTIVE_HIGH>; - }; - - sfp2-green { - label = "green:sfp2"; - gpios = <&tlmm 55 GPIO_ACTIVE_HIGH>; - }; - }; - - spi@78b5000 { - status = "ok"; - pinctrl-0 = <&spi_0_pins>; - pinctrl-names = "default"; - cs-select = <0>; - - m25p80@0 { - compatible = "n25q128a11"; - #address-cells = <1>; - #size-cells = <1>; - reg = <0>; - spi-max-frequency = <50000000>; - }; - }; -}; - -&tlmm { - mdio_pins: mdio_pinmux { - mux_0 { - pins = "gpio68"; - function = "mdc"; - drive-strength = <8>; - bias-pull-up; - }; - mux_1 { - pins = "gpio69"; - function = "mdio"; - drive-strength = <8>; - bias-pull-up; - }; - mux_2 { - pins = "gpio44"; - function = "gpio"; - bias-pull-up; - }; - }; - - i2c_1_pins: i2c_1_pins { - pins = "gpio46", "gpio47"; - function = "blsp2_i2c"; - drive-strength = <8>; - bias-disable; - }; - - button_pins: button_pins { - reset { - pins = "gpio50"; - function = "gpio"; - drive-strength = <8>; - bias-pull-up; - }; - }; - - uniphy_pins: uniphy_pinmux { - mux { - pins = "gpio60"; - function = "rx2"; - bias-disable; - }; - sfp_tx { - pins = "gpio59"; - function = "gpio"; - drive-strength = <8>; - bias-pull-down; - output-high; - }; - }; - - leds_pins: leds_pinmux { - mux { - pins = "gpio21", "gpio22", "gpio65"; - function = "gpio"; - drive-strength = <8>; - bias-pull-down; - }; - led_sfp1_active { - pins = "gpio51"; - function = "gpio"; - drive-strength = <8>; - bias-pull-down; - }; - led_sfp2_active { - pins = "gpio55"; - function = "gpio"; - drive-strength = <8>; - bias-pull-down; - }; - }; -}; - -&mdio { - status = "okay"; - pinctrl-0 = <&mdio_pins>; - pinctrl-names = "default"; - reset-gpios = <&tlmm 37 GPIO_ACTIVE_LOW>; - - phy0:ethernet-phy@0 { - compatible = "ethernet-phy-ieee802.3-c22"; - reg = <0>; - }; - phy1:ethernet-phy@1 { - compatible = "ethernet-phy-ieee802.3-c22"; - reg = <1>; - }; - phy2:ethernet-phy@2 { - compatible = "ethernet-phy-ieee802.3-c22"; - reg = <2>; - }; - phy3:ethernet-phy@3 { - compatible = "ethernet-phy-ieee802.3-c22"; - reg = <3>; - }; - phy4: ethernet-phy@29 { - reg = <29>; - }; - phy5: ethernet-phy@30 { - reg = <30>; - }; -}; - -&ess_switch { - status = "okay"; - switch_cpu_bmp = <0x1>; /* cpu port bitmap */ - switch_lan_bmp = <0x3e>; /* lan port bitmap */ - switch_wan_bmp = <0x40>; /* wan port bitmap */ - switch_mac_mode = <0xb>; /* mac mode for uniphy instance0*/ - switch_mac_mode1 = <0xe>; /* mac mode for uniphy instance1*/ //use 10g_baser mode for default - switch_mac_mode2 = <0xe>; /* mac mode for uniphy instance2*/ //use 10g_baser mode for default - bm_tick_mode = <0>; /* bm tick mode */ - tm_tick_mode = <0>; /* tm tick mode */ - cmnblk_clk = "external_50MHz"; - - 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 = <29>;//29 - phy_i2c_address = <29>;//29 - phy-i2c-mode; /*i2c access phy */ - media-type = "sfp"; /* fiber mode */ - }; - port@5 { - port_id = <6>; - phy_address = <30>;//30 - phy_i2c_address = <30>;//30 - phy-i2c-mode; /*i2c access phy */ - media-type = "sfp"; /* fiber mode */ - }; - }; - 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>; - }; - }; - }; - }; -}; - -&soc { - dp1: dp1 { - device_type = "network"; - compatible = "qcom,nss-dp"; - qcom,id = <1>; - reg = <0x3a001000 0x200>; - qcom,mactype = <0>; - local-mac-address = [000000000000]; - qcom,link-poll = <1>; - qcom,phy-mdio-addr = <0>; - phy-mode = "sgmii"; - mdio-bus = <&mdio>; - }; - dp2: dp2 { - device_type = "network"; - compatible = "qcom,nss-dp"; - qcom,id = <2>; - reg = <0x3a001200 0x200>; - qcom,mactype = <0>; - local-mac-address = [000000000000]; - qcom,link-poll = <1>; - qcom,phy-mdio-addr = <1>; - phy-mode = "sgmii"; - mdio-bus = <&mdio>; - }; - dp3: dp3 { - device_type = "network"; - compatible = "qcom,nss-dp"; - qcom,id = <3>; - reg = <0x3a001400 0x200>; - qcom,mactype = <0>; - local-mac-address = [000000000000]; - qcom,link-poll = <1>; - qcom,phy-mdio-addr = <2>; - phy-mode = "sgmii"; - mdio-bus = <&mdio>; - }; - dp4: dp4 { - device_type = "network"; - compatible = "qcom,nss-dp"; - qcom,id = <4>; - reg = <0x3a001600 0x200>; - qcom,mactype = <0>; - local-mac-address = [000000000000]; - qcom,link-poll = <1>; - qcom,phy-mdio-addr = <3>; - phy-mode = "sgmii"; - mdio-bus = <&mdio>; - }; - dp5: dp5 { - device_type = "network"; - compatible = "qcom,nss-dp"; - qcom,id = <5>; - reg = <0x3a001800 0x200>; - qcom,mactype = <1>; - local-mac-address = [000000000000]; - qcom,link-poll = <1>; - qcom,phy-mdio-addr = <29>; - phy-mode = "sgmii"; - mdio-bus = <&mdio>; - }; - dp6: dp6 { - device_type = "network"; - compatible = "qcom,nss-dp"; - qcom,id = <6>; - reg = <0x3a007000 0x3fff>; - qcom,mactype = <1>; - local-mac-address = [000000000000]; - qcom,link-poll = <1>; - qcom,phy-mdio-addr = <30>; - phy-mode = "sgmii"; - mdio-bus = <&mdio>; - }; - - nss-macsec1 { - compatible = "qcom,nss-macsec"; - phy_addr = <0x1c>; - phy_access_mode = <0x00>; - mdiobus = <&mdio>; - }; - - watchdog@b017000 { - compatible = "qcom,kpss-wdt-ipq807x"; - reg = <0xb017000 0x1000>; - reg-names = "kpss_wdt"; - interrupt-names = "bark_irq"; - interrupts = <0x00 0x03 0x00>; - clocks = <&sleep_clk>; - timeout-sec = <0x0a>; - wdt-max-timeout = <0x20>; - }; -}; - -&blsp1_i2c2 { - status = "okay"; -}; - -&blsp1_i2c3 { - pinctrl-0 = <&i2c_1_pins>; - pinctrl-names = "default"; - status = "okay"; -}; - -&blsp1_uart5 { - status = "okay"; -}; - -&cryptobam { - status = "okay"; -}; - -&crypto { - status = "okay"; -}; - -&qpic_bam { - status = "okay"; -}; - -&qpic_nand { - status = "okay"; - - nand@0 { - reg = <0>; - #address-cells = <1>; - #size-cells = <1>; - 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"; -}; - -&usb_0 { - status = "okay"; -}; diff --git a/target/linux/ipq807x/files-5.10/arch/arm64/boot/dts/qcom/ipq8071-ax3600.dtsi b/target/linux/ipq807x/files-5.10/arch/arm64/boot/dts/qcom/ipq8071-ax3600.dtsi deleted file mode 100644 index 4d93bda5c..000000000 --- a/target/linux/ipq807x/files-5.10/arch/arm64/boot/dts/qcom/ipq8071-ax3600.dtsi +++ /dev/null @@ -1,498 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later OR MIT -/* Copyright (c) 2021, Robert Marko */ - -#include "ipq8074.dtsi" -#include "ipq8074-ac-cpu.dtsi" -#include "ipq8074-ac-nss.dtsi" -#include "ipq8074-memory-512m.dtsi" -#include -#include - -/ { - #address-cells = <2>; - #size-cells = <2>; - - interrupt-parent = <&intc>; - - aliases { - serial0 = &blsp1_uart5; - led-boot = &led_system_yellow; - led-failsafe = &led_system_yellow; - led-running = &led_system_blue; - led-upgrade = &led_system_yellow; - /* Aliases as required by u-boot to patch MAC addresses */ - ethernet1 = &dp2; - ethernet2 = &dp3; - ethernet3 = &dp4; - ethernet4 = &dp5; - label-mac-device = &dp2; - }; - - chosen { - stdout-path = "serial0:115200n8"; - bootargs-append = " root=/dev/ubiblock0_1"; - }; - - keys { - compatible = "gpio-keys"; - - reset { - label = "reset"; - gpios = <&tlmm 34 GPIO_ACTIVE_LOW>; - linux,code = ; - }; - }; - - reserved-memory { - /delete-node/ tzapp@4a400000; - /delete-node/ q6_etr_dump@50f00000; - /delete-node/ m3_dump@51000000; - }; -}; - -&tlmm { - mdio_pins: mdio-pins { - mdc { - pins = "gpio68"; - function = "mdc"; - drive-strength = <8>; - bias-pull-up; - }; - - mdio { - pins = "gpio69"; - function = "mdio"; - drive-strength = <8>; - bias-pull-up; - }; - }; -}; - -&blsp1_uart5 { - status = "okay"; -}; - -&prng { - status = "okay"; -}; - -&cryptobam { - status = "okay"; -}; - -&crypto { - 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"; - /* - * Disable the reset GPIO temporarely as it - * resets the 100Mbit LED configuration which - * the bootloader writes. - */ - //reset-gpios = <&tlmm 37 GPIO_ACTIVE_LOW>; - - ethernet-phy@1 { - reg = <1>; - }; - - ethernet-phy@2 { - reg = <2>; - }; - - ethernet-phy@3 { - reg = <3>; - }; - - ethernet-phy@4 { - reg = <4>; - }; -}; - -&ess_switch { - switch_cpu_bmp = <0x1>; /* cpu port bitmap */ - switch_lan_bmp = <0x1e>; /* lan port bitmap */ - switch_wan_bmp = <0x20>; /* wan port bitmap */ - 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*/ - bm_tick_mode = <0>; /* bm tick mode */ - tm_tick_mode = <0>; /* tm tick mode */ - 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>; - }; - }; - 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>; - }; - }; - }; - }; -}; - -&soc { - dp2: dp2 { - device_type = "network"; - compatible = "qcom,nss-dp"; - qcom,id = <2>; - reg = <0x3a001200 0x200>; - qcom,mactype = <0>; - local-mac-address = [000000000000]; - qcom,link-poll = <1>; - qcom,phy-mdio-addr = <1>; - phy-mode = "sgmii"; - mdio-bus = <&mdio>; - }; - - dp3: dp3 { - device_type = "network"; - compatible = "qcom,nss-dp"; - qcom,id = <3>; - reg = <0x3a001400 0x200>; - qcom,mactype = <0>; - local-mac-address = [000000000000]; - qcom,link-poll = <1>; - qcom,phy-mdio-addr = <2>; - phy-mode = "sgmii"; - mdio-bus = <&mdio>; - }; - - dp4: dp4 { - device_type = "network"; - compatible = "qcom,nss-dp"; - qcom,id = <4>; - reg = <0x3a001600 0x200>; - qcom,mactype = <0>; - local-mac-address = [000000000000]; - qcom,link-poll = <1>; - qcom,phy-mdio-addr = <3>; - phy-mode = "sgmii"; - mdio-bus = <&mdio>; - }; - - dp5: dp5 { - device_type = "network"; - compatible = "qcom,nss-dp"; - qcom,id = <5>; - reg = <0x3a001800 0x200>; - qcom,mactype = <0>; - local-mac-address = [000000000000]; - qcom,link-poll = <1>; - qcom,phy-mdio-addr = <4>; - phy-mode = "sgmii"; - mdio-bus = <&mdio>; - }; -}; - -&wifi { - status = "okay"; - - qcom,board_id = <658>; -}; diff --git a/target/linux/ipq807x/files-5.10/arch/arm64/boot/dts/qcom/ipq8071-mf269.dts b/target/linux/ipq807x/files-5.10/arch/arm64/boot/dts/qcom/ipq8071-mf269.dts deleted file mode 100644 index 62a57cfe5..000000000 --- a/target/linux/ipq807x/files-5.10/arch/arm64/boot/dts/qcom/ipq8071-mf269.dts +++ /dev/null @@ -1,539 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later OR MIT -/* Copyright (c) 2021, ZhiPing */ - -/dts-v1/; - -#include "ipq8074.dtsi" -#include "ipq8074-ac-cpu.dtsi" -#include "ipq8074-ac-nss.dtsi" -#include "ipq8074-memory-512m.dtsi" -#include -#include - -/ { - #address-cells = <2>; - #size-cells = <2>; - - model = "ZTE MF269"; - compatible = "zte,mf269", "qcom,ipq8074"; - interrupt-parent = <&intc>; - - aliases { - led-boot = &led_power; - led-failsafe = &led_power; - led-running = &led_power; - led-upgrade = &led_power; - serial0 = &blsp1_uart5; - }; - - chosen { - stdout-path = "serial0:115200n8"; - bootargs-append = " root=/dev/ubiblock0_1"; - }; - - reserved-memory { - /delete-node/ tzapp@4a400000; - /delete-node/ q6_etr_dump@50f00000; - /delete-node/ m3_dump@51000000; - }; - - keys { - compatible = "gpio-keys"; - - reset { - label = "reset"; - linux,code = ; - gpios = <&tlmm 46 GPIO_ACTIVE_LOW>; - }; - - wps { - label = "wps"; - linux,code = ; - gpios = <&tlmm 37 GPIO_ACTIVE_LOW>; - }; - }; - - leds { - compatible = "gpio-leds"; - - led_power: power { - label = "white:power"; - gpio = <&tlmm 56 GPIO_ACTIVE_HIGH>; - }; - }; - - soc { - dp5: dp5 { - device_type = "network"; - compatible = "qcom,nss-dp"; - qcom,id = <5>; - reg = <0x3a003000 0x3fff>; - qcom,mactype = <1>; - local-mac-address = [000000000000]; - qcom,link-poll = <1>; - qcom,phy-mdio-addr = <24>; - phy-mode = "sgmii"; - mdio-bus = <&mdio>; - }; - - dp6: dp6 { - device_type = "network"; - compatible = "qcom,nss-dp"; - qcom,id = <6>; - reg = <0x3a007000 0x3fff>; - qcom,mactype = <1>; - local-mac-address = [000000000000]; - qcom,link-poll = <1>; - qcom,phy-mdio-addr = <28>; - phy-mode = "sgmii"; - mdio-bus = <&mdio>; - }; - }; -}; - -&blsp1_spi1 { - status = "okay"; - pinctrl-0 = <&spi_0_pins>; - pinctrl-names = "default"; - cs-select = <0>; - - flash@0 { - compatible = "jedec,spi-nor", "n25q128a11"; - #address-cells = <1>; - #size-cells = <1>; - reg = <0>; - spi-max-frequency = <50000000>; - }; -}; - -&blsp1_uart5 { - status = "okay"; -}; - -&cryptobam { - status = "okay"; -}; - -&crypto { - status = "okay"; -}; - -&ess_switch { - switch_cpu_bmp = <0x1>; /* cpu port bitmap */ - switch_lan_bmp = <0x3e>; /* lan port bitmap */ - switch_wan_bmp = <0x40>; /* wan port bitmap */ - switch_mac_mode = <0x0>; /* mac mode for uniphy instance0*/ - switch_mac_mode1 = <0xf>; /* mac mode for uniphy instance1*/ - switch_mac_mode2 = <0xf>; /* mac mode for uniphy instance2*/ - bm_tick_mode = <0>; /* bm tick mode */ - tm_tick_mode = <0>; /* tm tick mode */ - - qcom,port_phyinfo { - port@4 { - port_id = <5>; - phy_address = <24>; - port_mac_sel = "QGMAC_PORT"; - }; - port@5 { - port_id = <6>; - phy_address = <28>; - port_mac_sel = "QGMAC_PORT"; - }; - }; - 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>; - }; - }; - }; - }; -}; - -&mdio { - status = "okay"; - - pinctrl-0 = <&mdio_pins>; - pinctrl-names = "default"; - //reset-gpios = <&tlmm 37 GPIO_ACTIVE_LOW>; - - ethernet-phy@4 { - reg = <24>; - //reset-gpios = <&tlmm 44 GPIO_ACTIVE_LOW>; - }; - - ethernet-phy@5 { - reg = <28>; - //reset-gpios = <&tlmm 25 GPIO_ACTIVE_LOW>; - }; -}; - -&prng { - 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"; - }; - }; -}; - -&qusb_phy_0 { - status = "okay"; -}; - -&ssphy_0 { - status = "okay"; -}; - -&tlmm { - i2c_4_pins: i2c-4-pinmux { - pins = "gpio21", "gpio22"; - function = "blsp4_i2c1"; - drive-strength = <8>; - bias-disable; - }; - - slic_ctl_pins: slic_ctl_pins { - mux { - pins = "gpio59"; - function = "gpio"; - bias-pull-up; - }; - }; - - spi_5_pins: spi-5-pins { - pins = "gpio0", "gpio2", "gpio9", "gpio16"; - function = "blsp5_spi"; - drive-strength = <8>; - bias-disable; - }; - - mdio_pins: mdio_pinmux { - mux_0 { - pins = "gpio68"; - function = "mdc"; - drive-strength = <8>; - bias-pull-up; - }; - - mux_1 { - pins = "gpio69"; - function = "mdio"; - drive-strength = <8>; - bias-pull-up; - }; - - mux_2 { - pins = "gpio25"; - function = "gpio"; - bias-pull-up; - }; - - mux_3 { - pins = "gpio44"; - function = "gpio"; - bias-pull-up; - }; - }; - - usb_vbus_pins: usb_vbus_pins { - mux { - pins = "gpio29"; - function = "gpio"; - drive-strength = <8>; - bias-disable; - output-high; - }; - }; -}; - -&usb_0 { - pinctrl-0 = <&usb_vbus_pins>; - pinctrl-names = "default"; - status = "okay"; -}; - -&wifi { - status = "okay"; - - qcom,board_id = <658>; - qcom,ath11k-calibration-variant = "ZTE-MF269"; -}; diff --git a/target/linux/ipq807x/files-5.10/arch/arm64/boot/dts/qcom/ipq8072-301w.dts b/target/linux/ipq807x/files-5.10/arch/arm64/boot/dts/qcom/ipq8072-301w.dts deleted file mode 100644 index a8a9161bd..000000000 --- a/target/linux/ipq807x/files-5.10/arch/arm64/boot/dts/qcom/ipq8072-301w.dts +++ /dev/null @@ -1,819 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later OR MIT -/* Copyright (c) 2021, Dirk Buchwalder */ - -/dts-v1/; - -#include "ipq8074.dtsi" -#include "ipq8074-hk-cpu.dtsi" -#include "ipq8074-ac-nss.dtsi" -#include -#include -#include - -/ { - #address-cells = <2>; - #size-cells = <2>; - - model = "QNAP 301w"; - compatible = "qnap,301w", "qcom,ipq8074"; - interrupt-parent = <&intc>; - - aliases { - serial0 = &blsp1_uart5; - /* - * Aliases as required by u-boot - * to patch MAC addresses - */ - led-boot = &led_system_red; - led-failsafe = &led_system_red; - led-running = &led_pwr_green; - led-upgrade = &led_system_red; - ethernet0 = &dp1; - ethernet1 = &dp2; - ethernet2 = &dp3; - ethernet3 = &dp4; - ethernet4 = &dp5; - ethernet5 = &dp6; - label-mac-device = &dp1; - }; - - chosen { - stdout-path = "serial0:115200n8"; - }; - - keys { - compatible = "gpio-keys"; - - wps { - label = "wps"; - gpios = <&tlmm 57 GPIO_ACTIVE_LOW>; - linux,code = ; - }; - - reset { - label = "reset"; - gpios = <&tlmm 67 GPIO_ACTIVE_LOW>; - linux,code = ; - }; - }; - - leds { - compatible = "gpio-leds"; - - led_system_green: system-green { - label = "green:system"; - gpios = <&tlmm 1 GPIO_ACTIVE_HIGH>; - color = ; - }; - - led_system_red: system-red { - label = "red:system"; - gpios = <&tlmm 3 GPIO_ACTIVE_HIGH>; - color = ; - }; - - led_pwr_green: pwr-green { - label = "green:pwr"; - gpios = <&tlmm 4 GPIO_ACTIVE_HIGH>; - color = ; - }; - - led_wifi_green: wifi-green { - label = "green:wifi"; - gpios = <&tlmm 42 GPIO_ACTIVE_HIGH>; - color = ; - }; - - led_lan1_green: lan1-green { - label = "green:lan1"; - gpios = <&tlmm 6 GPIO_ACTIVE_HIGH>; - color = ; - }; - - led_lan1_amber: lan1-amber { - label = "amber:lan1"; - gpios = <&tlmm 7 GPIO_ACTIVE_HIGH>; - color = ; - }; - - led_lan2_green: lan2-green { - label = "green:lan2"; - gpios = <&tlmm 8 GPIO_ACTIVE_HIGH>; - color = ; - }; - - led_lan2_amber: lan2-amber { - label = "amber:lan2"; - gpios = <&tlmm 11 GPIO_ACTIVE_HIGH>; - color = ; - }; - - led_lan3_green: lan3-green { - label = "green:lan3"; - gpios = <&tlmm 12 GPIO_ACTIVE_HIGH>; - color = ; - }; - - led_lan3_amber: lan3-amber { - label = "amber:lan3"; - gpios = <&tlmm 13 GPIO_ACTIVE_HIGH>; - color = ; - }; - - led_lan4_green: lan4-green { - label = "green:lan4"; - gpios = <&tlmm 14 GPIO_ACTIVE_HIGH>; - color = ; - }; - - led_lan4_amber: lan4-amber { - label = "amber:lan4"; - gpios = <&tlmm 15 GPIO_ACTIVE_HIGH>; - color = ; - }; - - led_10g_1_green: 10g_1-green { - label = "green:10g_1"; - gpios = <&tlmm 54 GPIO_ACTIVE_HIGH>; - color = ; - }; - - led_10g_1_amber: 10g_1-amber { - label = "amber:10g_1"; - gpios = <&tlmm 56 GPIO_ACTIVE_HIGH>; - color = ; - }; - - led_10g_2_green: 10g_2-green { - label = "green:10g_2"; - gpios = <&tlmm 51 GPIO_ACTIVE_HIGH>; - color = ; - }; - - led_10g_2_amber: 10g_2-amber { - label = "amber:10g_2"; - gpios = <&tlmm 52 GPIO_ACTIVE_HIGH>; - color = ; - }; - }; -}; - -&tlmm { - - mdio_pins: mdio-pins { - mdc { - pins = "gpio68"; - function = "mdc"; - drive-strength = <8>; - bias-pull-up; - }; - - mdio { - pins = "gpio69"; - function = "mdio"; - drive-strength = <8>; - bias-pull-up; - }; - }; - - button_pins: button_pins { - wps_button { - pins = "gpio57"; - function = "gpio"; - drive-strength = <8>; - bias-pull-up; - }; - - rst_button { - pins = "gpio67"; - function = "gpio"; - drive-strength = <8>; - bias-pull-up; - }; - }; - - qpic_pins: qpic-pins { - status = "disabled"; - /*disabling qpic-pins due to the leds are using all of the gpios*/ - }; - - leds_pins: leds_pinmux { - led_pwr_green { - pins = "gpio4"; - function = "gpio"; - drive-strength = <8>; - bias-pull-down; - }; - led_system_green { - pins = "gpio1"; - function = "gpio"; - drive-strength = <8>; - bias-pull-down; - }; - led_system_red { - pins = "gpio3"; - function = "gpio"; - drive-strength = <8>; - bias-pull-down; - }; - led_lan1_green { - pins = "gpio6"; - function = "gpio"; - drive-strength = <8>; - bias-pull-down; - }; - led_lan1_amber { - pins = "gpio7"; - function = "gpio"; - drive-strength = <8>; - bias-pull-down; - }; - led_lan2_green { - pins = "gpio8"; - function = "gpio"; - drive-strength = <8>; - bias-pull-down; - }; - led_lan2_amber { - pins = "gpio11"; - function = "gpio"; - drive-strength = <8>; - bias-pull-down; - }; - led_lan3_green { - pins = "gpio12"; - function = "gpio"; - drive-strength = <8>; - bias-pull-down; - }; - led_lan3_amber { - pins = "gpio13"; - function = "gpio"; - drive-strength = <8>; - bias-pull-down; - }; - led_lan4_green { - pins = "gpio14"; - function = "gpio"; - drive-strength = <8>; - bias-pull-down; - }; - led_lan4_amber { - pins = "gpio15"; - function = "gpio"; - drive-strength = <8>; - bias-pull-down; - }; - led_10g_1_green { - pins = "gpio54"; - function = "gpio"; - drive-strength = <8>; - bias-pull-down; - }; - led_10g_1_amber { - pins = "gpio56"; - function = "gpio"; - drive-strength = <8>; - bias-pull-down; - }; - led_10g_2_green { - pins = "gpio51"; - function = "gpio"; - drive-strength = <8>; - bias-pull-down; - }; - led_10g_2_amber { - pins = "gpio52"; - function = "gpio"; - drive-strength = <8>; - bias-pull-down; - }; - led_wifi_green { - pins = "gpio42"; - function = "gpio"; - drive-strength = <8>; - bias-pull-down; - }; - }; -}; - -&blsp1_uart5 { - status = "okay"; -}; - -&prng { - status = "okay"; -}; - -&ssphy_0 { - status = "okay"; -}; - -&qusb_phy_0 { - status = "okay"; -}; - -&ssphy_1 { - status = "okay"; -}; - -&qusb_phy_1 { - status = "okay"; -}; - -&usb_0 { - status = "okay"; -}; - -&usb_1 { - status = "okay"; -}; - -&cryptobam { - status = "okay"; -}; - -&crypto { - status = "okay"; -}; - -&qpic_bam { - status = "okay"; -}; - -&blsp1_spi1 { /* BLSP1 QUP1 */ - pinctrl-0 = <&spi_0_pins>; - pinctrl-names = "default"; - cs-gpios = <0>; - status = "okay"; - - flash@0 { - #address-cells = <1>; - #size-cells = <1>; - reg = <0>; - compatible = "jedec,spi-nor"; - spi-max-frequency = <50000000>; - - partitions { - compatible = "qcom,smem-part"; - }; - }; -}; - -&mdio { - status = "okay"; - - pinctrl-0 = <&mdio_pins>; - pinctrl-names = "default"; - reset-gpios = <&tlmm 37 GPIO_ACTIVE_LOW>; - - ethernet-phy@0 { - compatible ="ethernet-phy-ieee802.3-c45"; - reg = <0>; - reset-gpios = <&tlmm 59 GPIO_ACTIVE_LOW>; - }; - - ethernet-phy@8 { - compatible ="ethernet-phy-ieee802.3-c45"; - reg = <8>; - reset-gpios = <&tlmm 44 GPIO_ACTIVE_LOW>; - }; - - ethernet-phy@16 { - reg = <16>; - }; - - ethernet-phy@17 { - reg = <17>; - }; - - ethernet-phy@18 { - reg = <18>; - }; - - ethernet-phy@19 { - reg = <19>; - }; - -}; - -&sdhc_1 { - /* According to the stock dts from the QNAP gpl drop - * the emmc has a problem with the hs400 > hs200 speed switch. - * But at the momment it doesn't seems possible to run that card in hs200 mode, - * it doesn't get recognized without the hs400 mode. - * Unfortunately it's not stable in hs400 mode so reduce the speed to mmc highspeed. - */ - no-1-8-v; - cap-sd-highspeed; - cap-mmc-highspeed; - max-frequency = <5000000>; - vqmmc-supply = <&ldo11>; - status = "okay"; -}; - -&ess_switch { - status = "okay"; - - switch_cpu_bmp = <0x1>; /* cpu port bitmap */ - switch_lan_bmp = <0x3e>; /* lan port bitmap */ - switch_wan_bmp = <0xc0>; /* wan port bitmap */ - switch_mac_mode = <0x0>; /* mac mode for uniphy instance0*/ - switch_mac_mode1 = <0xd>; /* mac mode for uniphy instance1*/ - switch_mac_mode2 = <0xd>; /* mac mode for uniphy instance2*/ - bm_tick_mode = <0>; /* bm tick mode */ - tm_tick_mode = <0>; /* tm tick mode */ - - qcom,port_phyinfo { - port@0 { - port_id = <1>; - phy_address = <16>; - }; - port@1 { - port_id = <2>; - phy_address = <17>; - }; - port@2 { - port_id = <3>; - phy_address = <18>; - }; - port@3 { - port_id = <4>; - phy_address = <19>; - }; - port@4 { - port_id = <5>; - phy_address = <8>; - compatible = "ethernet-phy-ieee802.3-c45"; - ethernet-phy-ieee802.3-c45; - }; - port@5 { - port_id = <6>; - phy_address = <0>; - compatible = "ethernet-phy-ieee802.3-c45"; - ethernet-phy-ieee802.3-c45; - }; - }; - - 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>; - }; - }; - }; - }; -}; - -&soc { - dp1: dp1 { - device_type = "network"; - compatible = "qcom,nss-dp"; - qcom,id = <1>; - reg = <0x3a001000 0x200>; - qcom,mactype = <0>; - local-mac-address = [000000000000]; - qcom,link-poll = <1>; - qcom,phy-mdio-addr = <16>; - phy-mode = "sgmii"; - mdio-bus = <&mdio>; - }; - - dp2: dp2 { - device_type = "network"; - compatible = "qcom,nss-dp"; - qcom,id = <2>; - reg = <0x3a001200 0x200>; - qcom,mactype = <0>; - local-mac-address = [000000000000]; - qcom,link-poll = <1>; - qcom,phy-mdio-addr = <17>; - phy-mode = "sgmii"; - mdio-bus = <&mdio>; - }; - - dp3: dp3 { - device_type = "network"; - compatible = "qcom,nss-dp"; - qcom,id = <3>; - reg = <0x3a001400 0x200>; - qcom,mactype = <0>; - local-mac-address = [000000000000]; - qcom,link-poll = <1>; - qcom,phy-mdio-addr = <18>; - phy-mode = "sgmii"; - mdio-bus = <&mdio>; - }; - - dp4: dp4 { - device_type = "network"; - compatible = "qcom,nss-dp"; - qcom,id = <4>; - reg = <0x3a001600 0x200>; - qcom,mactype = <0>; - local-mac-address = [000000000000]; - qcom,link-poll = <1>; - qcom,phy-mdio-addr = <19>; - phy-mode = "sgmii"; - mdio-bus = <&mdio>; - }; - - dp5: dp5 { - device_type = "network"; - compatible = "qcom,nss-dp"; - qcom,id = <5>; - reg = <0x3a001800 0x200>; - qcom,mactype = <1>; - local-mac-address = [000000000000]; - qcom,link-poll = <1>; - qcom,phy-mdio-addr = <8>; - phy-mode = "sgmii"; - mdio-bus = <&mdio>; - }; - - dp6: dp6 { - device_type = "network"; - compatible = "qcom,nss-dp"; - qcom,id = <6>; - reg = <0x3a007000 0x3fff>; - qcom,mactype = <1>; - local-mac-address = [000000000000]; - qcom,link-poll = <1>; - qcom,phy-mdio-addr = <0>; - phy-mode = "sgmii"; - mdio-bus = <&mdio>; - }; -}; - -&wifi { - status = "okay"; - /* using board_id 0xff is intentionally - * as the stock firmware is also using this default board_id - */ - qcom,board_id = <0xff>; - qcom,ath11k-calibration-variant = "QNAP-301w"; -}; diff --git a/target/linux/ipq807x/files-5.10/arch/arm64/boot/dts/qcom/ipq8074-ac-cpu.dtsi b/target/linux/ipq807x/files-5.10/arch/arm64/boot/dts/qcom/ipq8074-ac-cpu.dtsi deleted file mode 100644 index 4b2c3c484..000000000 --- a/target/linux/ipq807x/files-5.10/arch/arm64/boot/dts/qcom/ipq8074-ac-cpu.dtsi +++ /dev/null @@ -1,173 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only - -&CPU0 { - operating-points-v2 = <&cpu_opp_table>; - voltage-tolerance = <1>; - cpu0-supply = <&s3>; -}; - -&CPU1 { - operating-points-v2 = <&cpu_opp_table>; - voltage-tolerance = <1>; - cpu-supply = <&s3>; -}; - -&CPU2 { - operating-points-v2 = <&cpu_opp_table>; - voltage-tolerance = <1>; - cpu-supply = <&s3>; -}; - -&CPU3 { - operating-points-v2 = <&cpu_opp_table>; - voltage-tolerance = <1>; - cpu-supply = <&s3>; -}; - -&cpus { - cpu_opp_table: cpu_opp_table { - compatible = "operating-points-v2"; - opp-shared; - - opp-1017600000 { - opp-hz = /bits/ 64 <1017600000>; - opp-microvolt = <704000>; - clock-latency-ns = <200000>; - }; - opp-1382400000 { - opp-hz = /bits/ 64 <1382400000>; - opp-microvolt = <824000>; - clock-latency-ns = <200000>; - }; - }; -}; - -&cpu0_thermal { - trips { - cpu0_passive: cpu-passive { - temperature = <95000>; - hysteresis = <2000>; - type = "passive"; - }; - - cpu0_crit: cpu_crit { - temperature = <110000>; - hysteresis = <1000>; - type = "critical"; - }; - }; - - cooling-maps { - map0 { - trip = <&cpu0_passive>; - cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, - <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, - <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, - <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; - }; - }; -}; - -&cpu1_thermal { - trips { - cpu1_passive: cpu-passive { - temperature = <95000>; - hysteresis = <2000>; - type = "passive"; - }; - - cpu1_crit: cpu_crit { - temperature = <110000>; - hysteresis = <1000>; - type = "critical"; - }; - }; - - cooling-maps { - map0 { - trip = <&cpu1_passive>; - cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, - <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, - <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, - <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; - }; - }; -}; - -&cpu2_thermal { - trips { - cpu2_passive: cpu-passive { - temperature = <95000>; - hysteresis = <2000>; - type = "passive"; - }; - - cpu2_crit: cpu_crit { - temperature = <110000>; - hysteresis = <1000>; - type = "critical"; - }; - }; - - cooling-maps { - map0 { - trip = <&cpu2_passive>; - cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, - <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, - <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, - <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; - }; - }; -}; - -&cpu3_thermal { - trips { - cpu3_passive: cpu-passive { - temperature = <95000>; - hysteresis = <2000>; - type = "passive"; - }; - - cpu3_crit: cpu_crit { - temperature = <110000>; - hysteresis = <1000>; - type = "critical"; - }; - }; - - cooling-maps { - map0 { - trip = <&cpu3_passive>; - cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, - <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, - <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, - <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; - }; - }; -}; - -&cluster_thermal { - trips { - cluster_passive: cluster-passive { - temperature = <95000>; - hysteresis = <2000>; - type = "passive"; - }; - - cluster_crit: cluster_crit { - temperature = <110000>; - hysteresis = <1000>; - type = "critical"; - }; - }; - - cooling-maps { - map0 { - trip = <&cluster_passive>; - cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, - <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, - <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, - <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; - }; - }; -}; diff --git a/target/linux/ipq807x/files-5.10/arch/arm64/boot/dts/qcom/ipq8074-ac-nss.dtsi b/target/linux/ipq807x/files-5.10/arch/arm64/boot/dts/qcom/ipq8074-ac-nss.dtsi deleted file mode 100644 index 3b10e151b..000000000 --- a/target/linux/ipq807x/files-5.10/arch/arm64/boot/dts/qcom/ipq8074-ac-nss.dtsi +++ /dev/null @@ -1,256 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only - -&soc { - dummy_reg: dummy-regulator@0 { - compatible = "regulator-fixed"; - regulator-name = "dummy-reg"; - regulator-min-microvolt = <848000>; - regulator-max-microvolt = <848000>; - regulator-always-on; - regulator-boot-on; - }; - - nss-common { - compatible = "qcom,nss-common"; - reg = <0x01868010 0x1000>; - reg-names = "nss-misc-reset"; - }; - - nss0: nss@40000000 { - compatible = "qcom,nss"; - interrupts = , - , - , - , - , - , - , - , - , - ; - reg = <0x39000000 0x1000>, - <0x38000000 0x30000>, - <0x0b111000 0x1000>; - reg-names = "nphys", "vphys", "qgic-phys"; - clocks = <&gcc GCC_NSS_NOC_CLK>, - <&gcc GCC_NSS_PTP_REF_CLK>, - <&gcc GCC_NSS_CSR_CLK>, <&gcc GCC_NSS_CFG_CLK>, - <&gcc GCC_NSS_IMEM_CLK>, - <&gcc GCC_NSSNOC_QOSGEN_REF_CLK>, - <&gcc GCC_MEM_NOC_NSS_AXI_CLK>, - <&gcc GCC_NSSNOC_SNOC_CLK>, - <&gcc GCC_NSSNOC_TIMEOUT_REF_CLK>, - <&gcc GCC_NSS_CE_AXI_CLK>, - <&gcc GCC_NSS_CE_APB_CLK>, - <&gcc GCC_NSSNOC_CE_AXI_CLK>, - <&gcc GCC_NSSNOC_CE_APB_CLK>, - <&gcc GCC_NSSNOC_UBI0_AHB_CLK>, - <&gcc GCC_UBI0_CORE_CLK>, - <&gcc GCC_UBI0_AHB_CLK>, - <&gcc GCC_UBI0_AXI_CLK>, - <&gcc GCC_UBI0_MPT_CLK>, - <&gcc GCC_UBI0_NC_AXI_CLK>; - clock-names = "nss-noc-clk", "nss-ptp-ref-clk", - "nss-csr-clk", "nss-cfg-clk", - "nss-imem-clk", - "nss-nssnoc-qosgen-ref-clk", - "nss-mem-noc-nss-axi-clk", - "nss-nssnoc-snoc-clk", - "nss-nssnoc-timeout-ref-clk", - "nss-ce-axi-clk", "nss-ce-apb-clk", - "nss-nssnoc-ce-axi-clk", - "nss-nssnoc-ce-apb-clk", - "nss-nssnoc-ahb-clk", - "nss-core-clk", "nss-ahb-clk", - "nss-axi-clk", "nss-mpt-clk", - "nss-nc-axi-clk"; - qcom,id = <0>; - qcom,num-queue = <4>; - qcom,num-irq = <10>; - qcom,num-pri = <4>; - qcom,load-addr = <0x40000000>; - qcom,low-frequency = <187200000>; - qcom,mid-frequency = <748800000>; - qcom,max-frequency = <1689600000>; - npu-supply = <&dummy_reg>; - mx-supply = <&dummy_reg>; - qcom,bridge-enabled; - qcom,ipv4-enabled; - qcom,ipv4-reasm-enabled; - qcom,ipv6-enabled; - qcom,ipv6-reasm-enabled; - qcom,wlanredirect-enabled; - qcom,tun6rd-enabled; - qcom,l2tpv2-enabled; - qcom,gre-enabled; - qcom,gre-redir-enabled; - qcom,gre-redir-mark-enabled; - qcom,map-t-enabled; - qcom,portid-enabled; - qcom,ppe-enabled; - qcom,pppoe-enabled; - qcom,pptp-enabled; - qcom,tunipip6-enabled; - qcom,shaping-enabled; - qcom,wlan-dataplane-offload-enabled; - qcom,vlan-enabled; - qcom,igs-enabled; - qcom,vxlan-enabled; - qcom,match-enabled; - qcom,mirror-enabled; - qcom,udp-st-enabled; - }; - - nss1: nss@40800000 { - compatible = "qcom,nss"; - interrupts = , - , - , - , - , - , - , - , - ; - reg = <0x39400000 0x1000>, - <0x38030000 0x30000>, - <0x0b111000 0x1000>; - reg-names = "nphys", "vphys", "qgic-phys"; - clocks = <&gcc GCC_NSS_NOC_CLK>, - <&gcc GCC_NSS_PTP_REF_CLK>, - <&gcc GCC_NSS_CSR_CLK>, <&gcc GCC_NSS_CFG_CLK>, - <&gcc GCC_NSS_IMEM_CLK>, - <&gcc GCC_NSSNOC_QOSGEN_REF_CLK>, - <&gcc GCC_MEM_NOC_NSS_AXI_CLK>, - <&gcc GCC_NSSNOC_SNOC_CLK>, - <&gcc GCC_NSSNOC_TIMEOUT_REF_CLK>, - <&gcc GCC_NSS_CE_AXI_CLK>, - <&gcc GCC_NSS_CE_APB_CLK>, - <&gcc GCC_NSSNOC_CE_AXI_CLK>, - <&gcc GCC_NSSNOC_CE_APB_CLK>, - <&gcc GCC_NSSNOC_UBI1_AHB_CLK>, - <&gcc GCC_UBI1_CORE_CLK>, - <&gcc GCC_UBI1_AHB_CLK>, - <&gcc GCC_UBI1_AXI_CLK>, - <&gcc GCC_UBI1_MPT_CLK>, - <&gcc GCC_UBI1_NC_AXI_CLK>; - clock-names = "nss-noc-clk", "nss-ptp-ref-clk", - "nss-csr-clk", "nss-cfg-clk", - "nss-imem-clk", - "nss-nssnoc-qosgen-ref-clk", - "nss-mem-noc-nss-axi-clk", - "nss-nssnoc-snoc-clk", - "nss-nssnoc-timeout-ref-clk", - "nss-ce-axi-clk", "nss-ce-apb-clk", - "nss-nssnoc-ce-axi-clk", - "nss-nssnoc-ce-apb-clk", - "nss-nssnoc-ahb-clk", - "nss-core-clk", "nss-ahb-clk", - "nss-axi-clk", "nss-mpt-clk", - "nss-nc-axi-clk"; - qcom,id = <1>; - qcom,num-queue = <4>; - qcom,num-irq = <9>; - qcom,num-pri = <4>; - qcom,load-addr = <0x40800000>; - qcom,capwap-enabled; - qcom,dtls-enabled; - qcom,tls-enabled; - qcom,crypto-enabled; - qcom,ipsec-enabled; - qcom,qvpn-enabled; - qcom,pvxlan-enabled; - qcom,clmap-enabled; - qcom,rmnet_rx-enabled; - }; - - nss_crypto: qcom,nss_crypto { - compatible = "qcom,nss-crypto"; - #address-cells = <1>; - #size-cells = <1>; - qcom,max-contexts = <64>; - qcom,max-context-size = <32>; - ranges; - - eip197_node { - compatible = "qcom,eip197"; - reg-names = "crypto_pbase"; - reg = <0x39800000 0x7ffff>; - clocks = <&gcc GCC_NSS_CRYPTO_CLK>, - <&gcc GCC_NSSNOC_CRYPTO_CLK>, - <&gcc GCC_CRYPTO_PPE_CLK>; - clock-names = "crypto_clk", - "crypto_nocclk", - "crypto_ppeclk"; - clock-frequency = /bits/ 64 <600000000 600000000 300000000>; - qcom,dma-mask = <0xff>; - qcom,transform-enabled; - qcom,aes128-cbc; - qcom,aes192-cbc; - qcom,aes256-cbc; - qcom,aes128-ctr; - qcom,aes192-ctr; - qcom,aes256-ctr; - qcom,aes128-ecb; - qcom,aes192-ecb; - qcom,aes256-ecb; - qcom,3des-cbc; - qcom,md5-hash; - qcom,sha160-hash; - qcom,sha224-hash; - qcom,sha384-hash; - qcom,sha512-hash; - qcom,sha256-hash; - qcom,md5-hmac; - qcom,sha160-hmac; - qcom,sha224-hmac; - qcom,sha256-hmac; - qcom,sha384-hmac; - qcom,sha512-hmac; - qcom,aes128-gcm-gmac; - qcom,aes192-gcm-gmac; - qcom,aes256-gcm-gmac; - qcom,aes128-cbc-md5-hmac; - qcom,aes128-cbc-sha160-hmac; - qcom,aes192-cbc-md5-hmac; - qcom,aes192-cbc-sha160-hmac; - qcom,aes256-cbc-md5-hmac; - qcom,aes256-cbc-sha160-hmac; - qcom,aes128-ctr-sha160-hmac; - qcom,aes192-ctr-sha160-hmac; - qcom,aes256-ctr-sha160-hmac; - qcom,aes128-ctr-md5-hmac; - qcom,aes192-ctr-md5-hmac; - qcom,aes256-ctr-md5-hmac; - qcom,3des-cbc-md5-hmac; - qcom,3des-cbc-sha160-hmac; - qcom,aes128-cbc-sha256-hmac; - qcom,aes192-cbc-sha256-hmac; - qcom,aes256-cbc-sha256-hmac; - qcom,aes128-ctr-sha256-hmac; - qcom,aes192-ctr-sha256-hmac; - qcom,aes256-ctr-sha256-hmac; - qcom,3des-cbc-sha256-hmac; - qcom,aes128-cbc-sha384-hmac; - qcom,aes192-cbc-sha384-hmac; - qcom,aes256-cbc-sha384-hmac; - qcom,aes128-ctr-sha384-hmac; - qcom,aes192-ctr-sha384-hmac; - qcom,aes256-ctr-sha384-hmac; - qcom,aes128-cbc-sha512-hmac; - qcom,aes192-cbc-sha512-hmac; - qcom,aes256-cbc-sha512-hmac; - qcom,aes128-ctr-sha512-hmac; - qcom,aes192-ctr-sha512-hmac; - qcom,aes256-ctr-sha512-hmac; - - engine0 { - reg_offset = <0x80000>; - qcom,ifpp-enabled; - qcom,ipue-enabled; - qcom,ofpp-enabled; - qcom,opue-enabled; - }; - }; - }; -}; diff --git a/target/linux/ipq807x/files-5.10/arch/arm64/boot/dts/qcom/ipq8074-hk-cpu.dtsi b/target/linux/ipq807x/files-5.10/arch/arm64/boot/dts/qcom/ipq8074-hk-cpu.dtsi deleted file mode 100644 index be7b4a972..000000000 --- a/target/linux/ipq807x/files-5.10/arch/arm64/boot/dts/qcom/ipq8074-hk-cpu.dtsi +++ /dev/null @@ -1,258 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only - -&CPU0 { - operating-points-v2 = <&cpu_opp_table>; - voltage-tolerance = <1>; - cpu0-supply = <&s3>; -}; - -&CPU1 { - operating-points-v2 = <&cpu_opp_table>; - voltage-tolerance = <1>; - cpu-supply = <&s3>; -}; - -&CPU2 { - operating-points-v2 = <&cpu_opp_table>; - voltage-tolerance = <1>; - cpu-supply = <&s3>; -}; - -&CPU3 { - operating-points-v2 = <&cpu_opp_table>; - voltage-tolerance = <1>; - cpu-supply = <&s3>; -}; - -&cpus { - cpu_opp_table: cpu_opp_table { - compatible = "operating-points-v2"; - opp-shared; - - opp-1017600000 { - opp-hz = /bits/ 64 <1017600000>; - opp-microvolt = <704000>; - clock-latency-ns = <200000>; - }; - opp-1382400000 { - opp-hz = /bits/ 64 <1382400000>; - opp-microvolt = <784000>; - clock-latency-ns = <200000>; - }; - opp-1651200000 { - opp-hz = /bits/ 64 <1651200000>; - opp-microvolt = <832000>; - clock-latency-ns = <200000>; - }; - opp-1843200000 { - opp-hz = /bits/ 64 <1843200000>; - opp-microvolt = <880000>; - clock-latency-ns = <200000>; - }; - opp-1920000000 { - opp-hz = /bits/ 64 <1920000000>; - opp-microvolt = <904000>; - clock-latency-ns = <200000>; - }; - opp-2208000000 { - opp-hz = /bits/ 64 <2208000000>; - opp-microvolt = <984000>; - clock-latency-ns = <200000>; - }; - }; -}; - -&cpu0_thermal { - trips { - cpu0_passive_low: cpu-passive-low { - temperature = <95000>; - hysteresis = <2000>; - type = "passive"; - }; - - cpu0_passive_high: cpu-passive-high { - temperature = <100000>; - hysteresis = <2000>; - type = "passive"; - }; - - cpu0_crit: cpu_crit { - temperature = <110000>; - hysteresis = <1000>; - type = "critical"; - }; - }; - - cooling-maps { - map0 { - trip = <&cpu0_passive_low>; - cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, - <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, - <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, - <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; - }; - map1 { - trip = <&cpu0_passive_high>; - cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, - <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, - <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, - <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; - }; - }; -}; - -&cpu1_thermal { - trips { - cpu1_passive_low: cpu-passive-low { - temperature = <95000>; - hysteresis = <2000>; - type = "passive"; - }; - - cpu1_passive_high: cpu-passive-high { - temperature = <100000>; - hysteresis = <2000>; - type = "passive"; - }; - - cpu1_crit: cpu_crit { - temperature = <110000>; - hysteresis = <1000>; - type = "critical"; - }; - }; - - cooling-maps { - map0 { - trip = <&cpu1_passive_low>; - cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, - <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, - <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, - <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; - }; - map1 { - trip = <&cpu1_passive_high>; - cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, - <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, - <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, - <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; - }; - }; -}; - -&cpu2_thermal { - trips { - cpu2_passive_low: cpu-passive-low { - temperature = <95000>; - hysteresis = <2000>; - type = "passive"; - }; - - cpu2_passive_high: cpu-passive-high { - temperature = <100000>; - hysteresis = <2000>; - type = "passive"; - }; - - cpu2_crit: cpu_crit { - temperature = <110000>; - hysteresis = <1000>; - type = "critical"; - }; - }; - - cooling-maps { - map0 { - trip = <&cpu2_passive_low>; - cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, - <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, - <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, - <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; - }; - map1 { - trip = <&cpu2_passive_high>; - cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, - <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, - <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, - <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; - }; - }; -}; - -&cpu3_thermal { - trips { - cpu3_passive_low: cpu-passive-low { - temperature = <95000>; - hysteresis = <2000>; - type = "passive"; - }; - - cpu3_passive_high: cpu-passive-high { - temperature = <100000>; - hysteresis = <2000>; - type = "passive"; - }; - - cpu3_crit: cpu_crit { - temperature = <110000>; - hysteresis = <1000>; - type = "critical"; - }; - }; - - cooling-maps { - map0 { - trip = <&cpu3_passive_low>; - cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, - <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, - <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, - <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; - }; - map1 { - trip = <&cpu3_passive_high>; - cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, - <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, - <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, - <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; - }; - }; -}; - -&cluster_thermal { - trips { - cluster_passive_low: cluster-passive { - temperature = <95000>; - hysteresis = <2000>; - type = "passive"; - }; - - cluster_passive_high: cluster-passive-high { - temperature = <100000>; - hysteresis = <2000>; - type = "passive"; - }; - - cluster_crit: cluster_crit { - temperature = <110000>; - hysteresis = <1000>; - type = "critical"; - }; - }; - - cooling-maps { - map0 { - trip = <&cluster_passive_low>; - cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, - <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, - <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, - <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; - }; - map1 { - trip = <&cluster_passive_high>; - cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, - <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, - <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, - <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; - }; - }; -}; diff --git a/target/linux/ipq807x/files-5.10/arch/arm64/boot/dts/qcom/ipq8074-memory-512m.dtsi b/target/linux/ipq807x/files-5.10/arch/arm64/boot/dts/qcom/ipq8074-memory-512m.dtsi deleted file mode 100644 index fca32acb1..000000000 --- a/target/linux/ipq807x/files-5.10/arch/arm64/boot/dts/qcom/ipq8074-memory-512m.dtsi +++ /dev/null @@ -1,51 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* Copyright (C) 2020 The Linux Foundation. All rights reserved. - */ - -/ { - reserved-memory { - #address-cells = <2>; - #size-cells = <2>; - ranges; - - nss@40000000 { - no-map; - reg = <0x0 0x40000000 0x0 0x01000000>; - }; - - uboot@4a600000 { - no-map; - reg = <0x0 0x4a600000 0x0 0x00400000>; - }; - - sbl@4aa00000 { - no-map; - reg = <0x0 0x4aa00000 0x0 0x00100000>; - }; - - smem_region: smem@4ab00000 { - no-map; - reg = <0x0 0x4ab00000 0x0 0x00100000>; - }; - - tz@4ac00000 { - no-map; - reg = <0x0 0x4ac00000 0x0 0x00400000>; - }; - - q6_region: wcnss@4b000000 { - no-map; - reg = <0x0 0x4b000000 0x0 0x03700000>; - }; - - q6_etr_region: q6_etr_dump@4e700000 { - no-map; - reg = <0x0 0x4e700000 0x0 0x100000>; - }; - - wifi_dump@50500000 { - no-map; - reg = <0x0 0x50500000 0x0 0x200000>; - }; - }; -}; diff --git a/target/linux/ipq807x/files-5.10/arch/arm64/boot/dts/qcom/ipq8074-nbg7815.dts b/target/linux/ipq807x/files-5.10/arch/arm64/boot/dts/qcom/ipq8074-nbg7815.dts deleted file mode 100644 index 9a7f38445..000000000 --- a/target/linux/ipq807x/files-5.10/arch/arm64/boot/dts/qcom/ipq8074-nbg7815.dts +++ /dev/null @@ -1,741 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later OR MIT -/* - * Copyright (c) 2022, Karol Przybylski - * Copyright (c) 2023, Andre Valentin - */ - -/dts-v1/; - -#include "ipq8074.dtsi" -#include "ipq8074-hk-cpu.dtsi" -#include "ipq8074-ac-nss.dtsi" -#include -#include -#include - -/ { - #address-cells = <2>; - #size-cells = <2>; - model = "Zyxel NBG7815"; - compatible = "zyxel,nbg7815", "qcom,ipq8074"; - - aliases { - sdhc1 = &sdhc_1; /* SDC1 eMMC slot */ - serial0 = &blsp1_uart5; - serial1 = &blsp1_uart3; - /* Alias as required by u-boot to patch MAC addresses */ - ethernet0 = &dp1; - ethernet1 = &dp2; - ethernet2 = &dp3; - ethernet3 = &dp4; - ethernet4 = &dp5; - ethernet5 = &dp6; - label-mac-device = &dp1; - }; - - chosen { - stdout-path = "serial0:115200n8"; - }; - - keys { - compatible = "gpio-keys"; - - reset { - label = "reset"; - linux,code = ; - gpios = <&tlmm 54 GPIO_ACTIVE_LOW>; - }; - }; -}; - -&tlmm { - mdio_pins: mdio-pins { - mdc { - pins = "gpio68"; - function = "mdc"; - drive-strength = <8>; - bias-pull-up; - }; - - mdio { - pins = "gpio69"; - function = "mdio"; - drive-strength = <8>; - bias-pull-up; - }; - }; -}; - - -&blsp1_uart3 { - status = "okay"; -}; - -&blsp1_uart5 { - status = "okay"; -}; - -&prng { - status = "okay"; -}; - -&cryptobam { - status = "okay"; -}; - -&crypto { - status = "okay"; -}; - -&qpic_bam { - status = "okay"; -}; - - -&blsp1_spi1 { - pinctrl-0 = <&spi_0_pins>; - pinctrl-names = "default"; - cs-gpios = <0>; - status = "okay"; - - /* - * Bootloader will find the NAND DT node by the compatible and - * then "fixup" it by adding the partitions from the SMEM table - * using the legacy bindings thus making it impossible for us - * to change the partition table or utilize NVMEM for calibration. - * So add a dummy partitions node that bootloader will populate - * and set it as disabled so the kernel ignores it instead of - * printing warnings due to the broken way bootloader adds the - * partitions. - */ - partitions { - status = "disabled"; - }; - - - flash@0 { - #address-cells = <1>; - #size-cells = <1>; - reg = <0>; - compatible = "jedec,spi-nor"; - spi-max-frequency = <50000000>; - - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - partition@0 { - label = "0:sbl1"; - reg = <0x0 0x50000>; - read-only; - }; - - partition@50000 { - label = "0:mibib"; - reg = <0x50000 0x10000>; - read-only; - }; - - partition@60000 { - label = "0:bootconfig"; - reg = <0x60000 0x20000>; - read-only; - }; - - partition@80000 { - label = "0:bootconfig1"; - reg = <0x80000 0x20000>; - read-only; - }; - - partition@a0000 { - label = "0:qsee"; - reg = <0xa0000 0x180000>; - read-only; - }; - - partition@220000 { - label = "0:qsee_1"; - reg = <0x220000 0x180000>; - read-only; - }; - - partition@3a0000 { - label = "0:devcfg"; - reg = <0x3a0000 0x10000>; - read-only; - }; - - partition@3b0000 { - label = "0:devcfg_1"; - reg = <0x3b0000 0x10000>; - read-only; - }; - - partition@3c0000 { - label = "0:apdp"; - reg = <0x3c0000 0x10000>; - read-only; - }; - - partition@3d0000 { - label = "0:apdp_1"; - reg = <0x3d0000 0x10000>; - read-only; - }; - - partition@3e0000 { - label = "0:rpm"; - reg = <0x3e0000 0x40000>; - read-only; - }; - - partition@420000 { - label = "0:rpm_1"; - reg = <0x420000 0x40000>; - read-only; - }; - - partition@460000 { - label = "0:cdt"; - reg = <0x460000 0x10000>; - read-only; - }; - - partition@470000 { - label = "0:cdt_1"; - reg = <0x470000 0x10000>; - read-only; - }; - - partition@480000 { - label = "0:appsbl"; - reg = <0x480000 0xc0000>; - read-only; - }; - - partition@540000 { - label = "0:appsbl_1"; - reg = <0x540000 0xc0000>; - read-only; - }; - - partition@600000 { - compatible = "u-boot,env"; - label = "0:appsblenv"; - reg = <0x600000 0x10000>; - - macaddr_lan: ethaddr { - }; - }; - - partition@610000 { - label = "0:art"; - reg = <0x610000 0x40000>; - read-only; - }; - - partition@650000 { - label = "0:ethphyfw"; - reg = <0x650000 0x80000>; - read-only; - }; - - partition@6d0000 { - label = "0:crt"; - reg = <0x6d0000 0x10000>; - read-only; - }; - - partition@6e0000 { - label = "dual_flag"; - reg = <0x6e0000 0x10000>; - }; - - partition@6f0000 { - label = "reserved"; - reg = <0x6f0000 0x110000>; - read-only; - }; - }; - }; -}; - -&mdio { - status = "okay"; - - pinctrl-0 = <&mdio_pins>; - pinctrl-names = "default"; - reset-gpios = <&tlmm 37 GPIO_ACTIVE_LOW>; - - ethernet-phy@0 { - reg = <0>; - }; - - ethernet-phy@1 { - reg = <1>; - }; - - ethernet-phy@2 { - reg = <2>; - }; - - ethernet-phy@3 { - reg = <3>; - }; - - ethernet-phy@28 { - reg = <28>; - }; - - ethernet-phy@8 { - compatible ="ethernet-phy-ieee802.3-c45"; - reg = <8>; - }; - -}; - -&ess_switch { - status = "okay"; - - switch_cpu_bmp = <0x1>; /* cpu port bitmap */ - switch_lan_bmp = <0x3e>; /* lan port bitmap */ - switch_wan_bmp = <0x40>; /* wan port bitmap */ - switch_mac_mode = <0x0>; /* mac mode for uniphy instance0*/ - switch_mac_mode1 = <0xf>; /* mac mode for uniphy instance1*/ - switch_mac_mode2 = <0xd>; /* mac mode for uniphy instance2*/ - bm_tick_mode = <0>; /* bm tick mode */ - tm_tick_mode = <0>; /* tm tick mode */ - - 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 = <28>; - port_mac_sel = "QGMAC_PORT"; - }; - port@5 { - port_id = <6>; - ethernet-phy-ieee802.3-c45; - phy_address = <8>; - }; - }; - - 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>; - }; - }; - }; - }; -}; - -&soc { - dp1: dp1 { - device_type = "network"; - compatible = "qcom,nss-dp"; - qcom,id = <1>; - reg = <0x3a001000 0x200>; - qcom,mactype = <0>; - local-mac-address = [000000000000]; - qcom,link-poll = <1>; - qcom,phy-mdio-addr = <0>; - phy-mode = "sgmii"; - mdio-bus = <&mdio>; - }; - - dp2: dp2 { - device_type = "network"; - compatible = "qcom,nss-dp"; - qcom,id = <2>; - reg = <0x3a001200 0x200>; - qcom,mactype = <0>; - local-mac-address = [000000000000]; - qcom,link-poll = <1>; - qcom,phy-mdio-addr = <1>; - phy-mode = "sgmii"; - mdio-bus = <&mdio>; - }; - - dp3: dp3 { - device_type = "network"; - compatible = "qcom,nss-dp"; - qcom,id = <3>; - reg = <0x3a001400 0x200>; - qcom,mactype = <0>; - local-mac-address = [000000000000]; - qcom,link-poll = <1>; - qcom,phy-mdio-addr = <2>; - phy-mode = "sgmii"; - mdio-bus = <&mdio>; - }; - - dp4: dp4 { - device_type = "network"; - compatible = "qcom,nss-dp"; - qcom,id = <4>; - reg = <0x3a001600 0x200>; - qcom,mactype = <0>; - local-mac-address = [000000000000]; - qcom,link-poll = <1>; - qcom,phy-mdio-addr = <3>; - phy-mode = "sgmii"; - mdio-bus = <&mdio>; - }; - - dp5: dp5 { - device_type = "network"; - compatible = "qcom,nss-dp"; - qcom,id = <5>; - reg = <0x3a001800 0x200>; - qcom,mactype = <1>; - local-mac-address = [000000000000]; - qcom,link-poll = <1>; - qcom,phy-mdio-addr = <28>; - phy-mode = "sgmii"; - mdio-bus = <&mdio>; - }; - - dp6: dp6 { - device_type = "network"; - compatible = "qcom,nss-dp"; - qcom,id = <6>; - reg = <0x3a007000 0x3fff>; - qcom,mactype = <1>; - local-mac-address = [000000000000]; - qcom,link-poll = <1>; - qcom,phy-mdio-addr = <8>; - phy-mode = "sgmii"; - mdio-bus = <&mdio>; - }; -}; - -&blsp1_i2c2 { - pinctrl-0 = <&i2c_0_pins>; - pinctrl-names = "default"; - status = "okay"; - - tmp103@70 { - compatible = "ti,tmp103"; - reg = <0x70>; - }; -}; - -&sdhc_1 { - qcom,clk-rates = <400000 25000000 50000000 100000000 \ - 192000000 384000000>; - qcom,bus-speed-mode = "HS200_1p8v", "DDR_1p8v"; - qcom,nonremovable; - status = "ok"; -}; - -&ssphy_0 { - status = "okay"; -}; - -&qusb_phy_0 { - status = "okay"; -}; - -&ssphy_1 { - status = "okay"; -}; - -&qusb_phy_1 { - status = "okay"; -}; - -&usb_0 { - status = "okay"; -}; - -&usb_1 { - status = "okay"; -}; - -&wifi { - status = "okay"; - - qcom,ath11k-calibration-variant = "Zyxel-NBG7815"; -}; diff --git a/target/linux/ipq807x/files-5.10/arch/arm64/boot/dts/qcom/ipq8078-xtr10890.dts b/target/linux/ipq807x/files-5.10/arch/arm64/boot/dts/qcom/ipq8078-xtr10890.dts deleted file mode 100644 index bdf01d050..000000000 --- a/target/linux/ipq807x/files-5.10/arch/arm64/boot/dts/qcom/ipq8078-xtr10890.dts +++ /dev/null @@ -1,969 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/dts-v1/; -/* Copyright (c) 2017, 2020-2021, The Linux Foundation. All rights reserved. - */ -#include "ipq8074.dtsi" -#include "ipq8074-hk-cpu.dtsi" -#include "ipq8074-ac-nss.dtsi" -#include -#include -#include - -/ { - #address-cells = <0x2>; - #size-cells = <0x2>; - model = "TP-LINK XTR10890"; - compatible = "tplink,xtr10890", "qcom,ipq8074"; - interrupt-parent = <&intc>; - //qcom,msm-id = <0x143 0x0>, <0x186 0x0>, <0x158 0x0>, <0x188 0x0>; - - aliases { - serial0 = &blsp1_uart5; - serial1 = &blsp1_uart3; - /* - * Aliases as required by u-boot - * to patch MAC addresses - */ - led-boot = &led_system_red; - led-failsafe = &led_system_green; - led-running = &led_system_red; - led-upgrade = &led_system_green; - ethernet0 = &dp1; - ethernet1 = &dp2; - ethernet2 = &dp3; - ethernet3 = &dp4; - ethernet4 = &dp5; - ethernet5 = &dp6; - }; - - chosen { - stdout-path = "serial0"; - bootargs-append = " root=/dev/ubiblock0_1 rootfstype=squashfs"; - }; - - reserved-memory { - - /delete-node/ wifi_dump@51100000; - /delete-node/ wigig_dump@51300000; - qcn9000_pcie0: qcn9000_pcie0@51100000 { - no-map; - reg = <0x0 0x51100000 0x0 0x03500000>; - }; - - mhi_region0: dma_pool0@54600000 { - compatible = "shared-dma-pool"; - no-map; - reg = <0x0 0x54600000 0x0 0x00900000>; - }; - - }; - - - keys { - compatible = "gpio-keys"; - pinctrl-0 = <&button_pins>; - pinctrl-names = "default"; - status = "okay"; - button@1 { - label = "wps"; - linux,code = ; - gpios = <&tlmm 50 GPIO_ACTIVE_LOW>; - linux,input-type = <1>; - debounce-interval = <60>; - }; - }; - - leds { - compatible = "gpio-leds"; - led_system_green: system-green { - label = "green:system"; - gpios = <&tlmm 31 GPIO_ACTIVE_LOW>; - }; - led_system_red: system-red { - label = "red:system"; - gpios = <&tlmm 29 GPIO_ACTIVE_HIGH>; - }; - - 10g-green { - label = "green:10g"; - gpios = <&tlmm 32 GPIO_ACTIVE_HIGH>; - }; - - sfp_green { - label = "green:sfp"; - gpios = <&tlmm 30 GPIO_ACTIVE_HIGH>; - }; - }; - -}; - -&sdhc_1 { - status = "okay"; -}; - - -&qpic_nand { - pinctrl-0 = <&qpic_pins>; - pinctrl-names = "default"; - status = "okay"; - nand@0 { - reg = <0>; - #address-cells = <1>; - #size-cells = <1>; - nand-ecc-strength = <4>; - nand-ecc-step-size = <512>; - nand-bus-width = <8>; - - partition0@0 { - label = "0:SBL1"; - reg = <0x0 0x80000>; - read-only; - }; - partition1@80000 { - label = "0:MIBIB"; - reg = <0x80000 0x40000>; - }; - - partition2@c0000 { - label = "0:BOOTCONFIG"; - reg = <0xc0000 0x20000>; - read-only; - }; - partition3@e0000 { - label = "0:BOOTCONFIG1"; - reg = <0xe0000 0x20000>; - read-only; - }; - - partition4@100000 { - label = "0:QSEE"; - reg = <0x100000 0x280000>; - read-only; - }; - - partition4@380000 { - label = "0:DEVCFG"; - reg = <0x380000 0x20000>; - read-only; - }; - - partition4@3a0000 { - label = "0:RPM"; - reg = <0x3a0000 0x40000>; - read-only; - }; - - partition5@3e0000 { - label = "0:CDT"; - reg = <0x3e0000 0x20000>; - read-only; - }; - - partition6@400000 { - label = "0:APPSBLENV"; - reg = <0x400000 0x40000>; - }; - - partition7@440000 { - label = "0:APPSBL"; - reg = <0x440000 0x100000>; - }; - - partition8@540000 { - label = "0:ART"; - reg = <0x540000 0x80000>; - }; - - partition12@5c0000 { - label = "rootfs"; - reg = <0x5c0000 0x7000000>; - }; - - partition13@75c0000 { - label = "0:WIFIFW"; - reg = <0x75c0000 0x900000>; - }; - - partition15@7ec0000 { - label = "0:ETHPHYFW"; - reg = <0x7ec0000 0x80000>; - }; - }; -}; - - -&mdio{ - status = "okay"; - - pinctrl-0 = <&mdio_pins>; - pinctrl-names = "default"; - phy-reset-gpio = <&tlmm 37 0>; - phy0: ethernet-phy@0 { - reg = <16>; - }; - phy1: ethernet-phy@1 { - reg = <17>; - }; - phy2: ethernet-phy@2 { - reg = <18>; - }; - phy3: ethernet-phy@3 { - reg = <19>; - }; - phy4: ethernet-phy@4 { - reg = <30>; - }; - phy5: ethernet-phy@5 { - compatible ="ethernet-phy-ieee802.3-c45"; - reg = <0>; - }; -}; - -&tlmm { - sd_pins: sd-pinmux { - pins = "gpio63"; - function = "sd_card"; - drive-strength = <8>; - bias-pull-up; - }; - - button_pins: button_pins { - wps_button { - pins = "gpio50"; - function = "gpio"; - drive-strength = <8>; - bias-pull-up; - }; - }; - - leds_pins: leds_pinmux { - led_pwr_green { - pins = "gpio31"; - function = "gpio"; - drive-strength = <8>; - bias-pull-down; - }; - - led_pwr_red { - pins = "gpio29"; - function = "gpio"; - drive-strength = <8>; - bias-pull-down; - }; - - led_sfp_green { - pins = "gpio30"; - function = "gpio"; - drive-strength = <8>; - bias-pull-down; - }; - - led_10g_green { - pins = "gpio32"; - function = "gpio"; - drive-strength = <8>; - bias-pull-down; - }; - }; - - mdio_pins: mdio_pinmux { - mux_0 { - pins = "gpio68"; - function = "mdc"; - drive-strength = <8>; - bias-pull-up; - }; - mux_1 { - pins = "gpio69"; - function = "mdio"; - drive-strength = <8>; - bias-pull-up; - }; - }; - - qpic_pins: qpic-pins { - pins = "gpio1", "gpio3", "gpio4", - "gpio5", "gpio6", "gpio7", - "gpio8", "gpio10", "gpio11", - "gpio12", "gpio13", "gpio14", - "gpio15", "gpio17"; - function = "qpic"; - drive-strength = <8>; - bias-disable; - }; - - uniphy_pins: uniphy_pinmux { - mux { - pins = "gpio60"; - function = "rx2"; - bias-disable; - }; - - sfp_tx { - pins = "gpio52"; - function = "gpio"; - drive-strength = <8>; - bias-pull-down; - output-low; - }; - }; - - i2c_0_pins: i2c-0-pinmux { - pins = "gpio46", "gpio47"; - function = "blsp1_i2c"; - drive-strength = <8>; - bias-disable; - }; - - pwm_pins: pwm_pinmux { - mux_1 { - pins = "gpio25"; - function = "pwm02"; - drive-strength = <8>; - }; - }; - - pcie0_pins: pcie_pins { - pcie0_rst { - pins = "gpio58"; - function = "pcie0_rst"; - drive-strength = <8>; - bias-pull-down; - }; - pcie0_wake { - pins = "gpio59"; - function = "pcie0_wake"; - drive-strength = <8>; - bias-pull-down; - }; - }; -}; - -&blsp1_uart5 { - status = "okay"; -}; - -&blsp1_spi1 { - status = "okay"; - pinctrl-0 = <&spi_0_pins>; - pinctrl-names = "default"; - cs-select = <0>; - - m25p80@0 { - compatible = "n25q128a11"; - #address-cells = <1>; - #size-cells = <1>; - reg = <0>; - spi-max-frequency = <50000000>; - }; -}; - -&blsp1_i2c2 { - pinctrl-0 = <&i2c_0_pins>; - pinctrl-names = "default"; - status = "okay"; -}; - -&ssphy_0 { - status = "okay"; -}; - -&qusb_phy_0 { - status = "okay"; -}; - -&ssphy_1 { - status = "okay"; -}; - -&qusb_phy_1 { - status = "okay"; -}; - -&usb_0 { - status = "okay"; -}; - -&usb_1 { - status = "okay"; -}; - -&prng { - status = "okay"; -}; - -&cryptobam { - status = "okay"; -}; - -&crypto { - status = "okay"; -}; - -&qpic_bam { - status = "okay"; -}; - -&pcie_qmp0 { - status = "okay"; -}; - -&pcie0 { - perst-gpio = <&tlmm 58 1>; - status = "okay"; - - pcie0_rp { - status = "ok"; - - mhi_0: qcom,mhi@0 { - reg = <0 0 0 0 0 >; - qrtr_instance_id = <0x20>; - #address-cells = <0x2>; - #size-cells = <0x2>; - memory-region = <&mhi_region0>; - // base-addr = <0x51100000>; - // m3-dump-addr = <0x53400000>; - // etr-addr = <0x53500000>; - // qcom,caldb-addr = <0x53600000>; - // mhi,max-channels = <30>; - // mhi,timeout = <10000>; - // qcom,board_id= <0xa4>; - - // pcie0_mhi: pcie0_mhi { - // status = "ok"; - // }; - }; - }; - -}; - -&pcie_qmp1 { - //status = "okay"; - status = "disabled"; -}; - -&pcie1 { - perst-gpio = <&tlmm 61 0x1>; - status = "disabled"; -}; - -&ess_switch { - status = "okay"; - pinctrl-0 = <&uniphy_pins>; - pinctrl-names = "default"; - switch_cpu_bmp = <0x1>; /* cpu port bitmap */ - switch_lan_bmp = <0x3e>; /* lan port bitmap */ - switch_wan_bmp = <0x40>; /* wan port bitmap */ - switch_mac_mode = <0x0b>; /* mac mode for uniphy instance0*/ - switch_mac_mode1 = <0x0e>; /* mac mode for uniphy instance1*/ - switch_mac_mode2 = <0x0d>; /* mac mode for uniphy instance2*/ - bm_tick_mode = <0>; /* bm tick mode */ - tm_tick_mode = <0>; /* tm tick mode */ - qcom,port_phyinfo { - port@0 { - port_id = <1>; - phy_address = <16>; - }; - port@1 { - port_id = <2>; - phy_address = <17>; - }; - port@2 { - port_id = <3>; - phy_address = <18>; - }; - port@3 { - port_id = <4>; - phy_address = <19>; - }; - port@4 { - port_id = <5>; - phy_address = <30>; - phy_i2c_address = <30>; - phy-i2c-mode; /*i2c access phy */ - media-type = "sfp"; /* fiber mode */ - }; - port@5 { - port_id = <6>; - phy_address = <0>; - ethernet-phy-ieee802.3-c45; - }; - }; - port_scheduler_resource { - - port@0 { - port_id = < 0x00 >; - ucast_queue = < 0x00 0x8f >; - mcast_queue = < 0x100 0x10f >; - l0sp = < 0x00 0x23 >; - l0cdrr = < 0x00 0x2f >; - l0edrr = < 0x00 0x2f >; - l1cdrr = < 0x00 0x07 >; - l1edrr = < 0x00 0x07 >; - }; - - port@1 { - port_id = < 0x01 >; - ucast_queue = < 0x90 0x9f >; - mcast_queue = < 0x110 0x113 >; - l0sp = < 0x24 0x27 >; - l0cdrr = < 0x30 0x3f >; - l0edrr = < 0x30 0x3f >; - l1cdrr = < 0x08 0x0b >; - l1edrr = < 0x08 0x0b >; - }; - - port@2 { - port_id = < 0x02 >; - ucast_queue = < 0xa0 0xaf >; - mcast_queue = < 0x114 0x117 >; - l0sp = < 0x28 0x2b >; - l0cdrr = < 0x40 0x4f >; - l0edrr = < 0x40 0x4f >; - l1cdrr = < 0x0c 0x0f >; - l1edrr = < 0x0c 0x0f >; - }; - - port@3 { - port_id = < 0x03 >; - ucast_queue = < 0xb0 0xbf >; - mcast_queue = < 0x118 0x11b >; - l0sp = < 0x2c 0x2f >; - l0cdrr = < 0x50 0x5f >; - l0edrr = < 0x50 0x5f >; - l1cdrr = < 0x10 0x13 >; - l1edrr = < 0x10 0x13 >; - }; - - port@4 { - port_id = < 0x04 >; - ucast_queue = < 0xc0 0xcf >; - mcast_queue = < 0x11c 0x11f >; - l0sp = < 0x30 0x33 >; - l0cdrr = < 0x60 0x6f >; - l0edrr = < 0x60 0x6f >; - l1cdrr = < 0x14 0x17 >; - l1edrr = < 0x14 0x17 >; - }; - - port@5 { - port_id = < 0x05 >; - ucast_queue = < 0xd0 0xdf >; - mcast_queue = < 0x120 0x123 >; - l0sp = < 0x34 0x37 >; - l0cdrr = < 0x70 0x7f >; - l0edrr = < 0x70 0x7f >; - l1cdrr = < 0x18 0x1b >; - l1edrr = < 0x18 0x1b >; - }; - - port@6 { - port_id = < 0x06 >; - ucast_queue = < 0xe0 0xef >; - mcast_queue = < 0x124 0x127 >; - l0sp = < 0x38 0x3b >; - l0cdrr = < 0x80 0x8f >; - l0edrr = < 0x80 0x8f >; - l1cdrr = < 0x1c 0x1f >; - l1edrr = < 0x1c 0x1f >; - }; - - port@7 { - port_id = < 0x07 >; - ucast_queue = < 0xf0 0xff >; - mcast_queue = < 0x128 0x12b >; - l0sp = < 0x3c 0x3f >; - l0cdrr = < 0x90 0x9f >; - l0edrr = < 0x90 0x9f >; - l1cdrr = < 0x20 0x23 >; - l1edrr = < 0x20 0x23 >; - }; - }; - - port_scheduler_config { - - port@0 { - port_id = < 0x00 >; - - l1scheduler { - - group@0 { - sp = < 0x00 0x01 >; - cfg = < 0x00 0x00 0x00 0x00 >; - }; - }; - - l0scheduler { - - group@0 { - ucast_queue = < 0x00 0x04 0x08 >; - mcast_queue = < 0x100 0x104 >; - cfg = < 0x00 0x00 0x00 0x00 0x00 >; - }; - - group@1 { - ucast_queue = < 0x01 0x05 0x09 >; - mcast_queue = < 0x101 0x105 >; - cfg = < 0x00 0x01 0x01 0x01 0x01 >; - }; - - group@2 { - ucast_queue = < 0x02 0x06 0x0a >; - mcast_queue = < 0x102 0x106 >; - cfg = < 0x00 0x02 0x02 0x02 0x02 >; - }; - - group@3 { - ucast_queue = < 0x03 0x07 0x0b >; - mcast_queue = < 0x103 0x107 >; - cfg = < 0x00 0x03 0x03 0x03 0x03 >; - }; - }; - }; - - port@1 { - port_id = < 0x01 >; - - l1scheduler { - - group@0 { - sp = < 0x24 >; - cfg = < 0x00 0x08 0x00 0x08 >; - }; - - group@1 { - sp = < 0x25 >; - cfg = < 0x01 0x09 0x01 0x09 >; - }; - }; - - l0scheduler { - - group@0 { - ucast_queue = < 0x90 >; - ucast_loop_pri = < 0x10 >; - mcast_queue = < 0x110 >; - mcast_loop_pri = < 0x04 >; - cfg = < 0x24 0x00 0x30 0x00 0x30 >; - }; - }; - }; - - port@2 { - port_id = < 0x02 >; - - l1scheduler { - - group@0 { - sp = < 0x28 >; - cfg = < 0x00 0x0c 0x00 0x0c >; - }; - - group@1 { - sp = < 0x29 >; - cfg = < 0x01 0x0d 0x01 0x0d >; - }; - }; - - l0scheduler { - - group@0 { - ucast_queue = < 0xa0 >; - ucast_loop_pri = < 0x10 >; - mcast_queue = < 0x114 >; - mcast_loop_pri = < 0x04 >; - cfg = < 0x28 0x00 0x40 0x00 0x40 >; - }; - }; - }; - - port@3 { - port_id = < 0x03 >; - - l1scheduler { - - group@0 { - sp = < 0x2c >; - cfg = < 0x00 0x10 0x00 0x10 >; - }; - - group@1 { - sp = < 0x2d >; - cfg = < 0x01 0x11 0x01 0x11 >; - }; - }; - - l0scheduler { - - group@0 { - ucast_queue = < 0xb0 >; - ucast_loop_pri = < 0x10 >; - mcast_queue = < 0x118 >; - mcast_loop_pri = < 0x04 >; - cfg = < 0x2c 0x00 0x50 0x00 0x50 >; - }; - }; - }; - - port@4 { - port_id = < 0x04 >; - - l1scheduler { - - group@0 { - sp = < 0x30 >; - cfg = < 0x00 0x14 0x00 0x14 >; - }; - - group@1 { - sp = < 0x31 >; - cfg = < 0x01 0x15 0x01 0x15 >; - }; - }; - - l0scheduler { - - group@0 { - ucast_queue = < 0xc0 >; - ucast_loop_pri = < 0x10 >; - mcast_queue = < 0x11c >; - mcast_loop_pri = < 0x04 >; - cfg = < 0x30 0x00 0x60 0x00 0x60 >; - }; - }; - }; - - port@5 { - port_id = < 0x05 >; - - l1scheduler { - - group@0 { - sp = < 0x34 >; - cfg = < 0x00 0x18 0x00 0x18 >; - }; - - group@1 { - sp = < 0x35 >; - cfg = < 0x01 0x19 0x01 0x19 >; - }; - }; - - l0scheduler { - - group@0 { - ucast_queue = < 0xd0 >; - ucast_loop_pri = < 0x10 >; - mcast_queue = < 0x120 >; - mcast_loop_pri = < 0x04 >; - cfg = < 0x34 0x00 0x70 0x00 0x70 >; - }; - }; - }; - - port@6 { - port_id = < 0x06 >; - - l1scheduler { - - group@0 { - sp = < 0x38 >; - cfg = < 0x00 0x1c 0x00 0x1c >; - }; - - group@1 { - sp = < 0x39 >; - cfg = < 0x01 0x1d 0x01 0x1d >; - }; - }; - - l0scheduler { - - group@0 { - ucast_queue = < 0xe0 >; - ucast_loop_pri = < 0x10 >; - mcast_queue = < 0x124 >; - mcast_loop_pri = < 0x04 >; - cfg = < 0x38 0x00 0x80 0x00 0x80 >; - }; - }; - }; - - port@7 { - port_id = < 0x07 >; - - l1scheduler { - - group@0 { - sp = < 0x3c >; - cfg = < 0x00 0x20 0x00 0x20 >; - }; - - group@1 { - sp = < 0x3d >; - cfg = < 0x01 0x21 0x01 0x21 >; - }; - }; - - l0scheduler { - - group@0 { - ucast_queue = < 0xf0 >; - ucast_loop_pri = < 0x10 >; - mcast_queue = < 0x128 >; - cfg = < 0x3c 0x00 0x90 0x00 0x90 >; - }; - }; - }; - }; -}; - - -&soc { - - phy@86000 { - status = "okay"; - }; - - sd-pwrseq { - status = "okay"; - }; - - sdhci@7864900 { - pinctrl-0 = <&sd_pins>; - pinctrl-names = "default"; - cd-gpios = <&tlmm 63 GPIO_ACTIVE_LOW>; - status = "okay"; - }; - - pwm { - pinctrl-0 = <&pwm_pins>; - pinctrl-names = "default"; - used-pwm-indices = <1>, <0>, <0>, <0>; - status = "disabled"; - }; - - // qcom,test@0 { - // status = "okay"; - // }; - - - dp1: dp1 { - device_type = "network"; - compatible = "qcom,nss-dp"; - qcom,id = <1>; - reg = <0x3a001000 0x200>; - qcom,mactype = <0>; - local-mac-address = [000000000000]; - qcom,link-poll = <1>; - qcom,phy-mdio-addr = <16>; - phy-mode = "sgmii"; - mdio-bus = <&mdio>; - }; - - dp2: dp2 { - device_type = "network"; - compatible = "qcom,nss-dp"; - qcom,id = <2>; - reg = <0x3a001200 0x200>; - qcom,mactype = <0>; - local-mac-address = [000000000000]; - qcom,link-poll = <1>; - qcom,phy-mdio-addr = <17>; - phy-mode = "sgmii"; - mdio-bus = <&mdio>; - }; - - dp3: dp3 { - device_type = "network"; - compatible = "qcom,nss-dp"; - qcom,id = <3>; - reg = <0x3a001400 0x200>; - qcom,mactype = <0>; - local-mac-address = [000000000000]; - qcom,link-poll = <1>; - qcom,phy-mdio-addr = <18>; - phy-mode = "sgmii"; - mdio-bus = <&mdio>; - }; - - dp4: dp4 { - device_type = "network"; - compatible = "qcom,nss-dp"; - qcom,id = <4>; - reg = <0x3a001600 0x200>; - qcom,mactype = <0>; - local-mac-address = [000000000000]; - qcom,link-poll = <1>; - qcom,phy-mdio-addr = <19>; - phy-mode = "sgmii"; - mdio-bus = <&mdio>; - }; - - dp5: dp5 { - device_type = "network"; - compatible = "qcom,nss-dp"; - qcom,id = <5>; - reg = <0x3a003000 0x3fff>; - qcom,mactype = <1>; - local-mac-address = [000000000000]; - qcom,link-poll = <1>; - qcom,phy-mdio-addr = <30>; - phy-mode = "sgmii"; - mdio-bus = <&mdio>; - }; - - dp6: dp6 { - device_type = "network"; - compatible = "qcom,nss-dp"; - qcom,id = <6>; - reg = <0x3a007000 0x3fff>; - qcom,mactype = <1>; - local-mac-address = [000000000000]; - qcom,link-poll = <1>; - qcom,phy-mdio-addr = <0>; - phy-mode = "sgmii"; - mdio-bus = <&mdio>; - }; - - // qcn9000_pcie0: qcn9000_pcie0@51100000 { - // no-map; - // reg = <0x0 0x51100000 0x0 0x02D00000>; - // }; - - wifi1: wifi1@f00000 { - - compatible = "qcom,cnss-qcn9000"; - qcom,wlan-ramdump-dynamic = <0x400000>; - mhi,max-channels = <30>; - mhi,timeout = <10000>; - qrtr_node_id = <0x20>; - qca,auto-restart; - - pcie0_mhi: pcie0_mhi { - status = "ok"; - }; - - }; -}; - -&wifi { - status = "okay"; - qcom,board_id = <528>; - qcom,ath11k-calibration-variant = "TL-XTR10890"; -}; - -&wifi1 { - base-addr = <0x51100000>; - m3-dump-addr = <0x53400000>; - etr-addr = <0x53500000>; - caldb-addr = <0x53600000>; - hremote-size = <0x2300000>; - tgt-mem-mode = <0x0>; - caldb-size = <0x800000>; - hremote_node = <&qcn9000_pcie0>; - pageable-size = <0x800000>; - board_id = <171>; - qcom,ath11k-calibration-variant = "TL-XTR10890"; - status = "ok"; -}; diff --git a/target/linux/ipq807x/files-5.10/drivers/hwmon/emc2305.c b/target/linux/ipq807x/files-5.10/drivers/hwmon/emc2305.c deleted file mode 100644 index 147900154..000000000 --- a/target/linux/ipq807x/files-5.10/drivers/hwmon/emc2305.c +++ /dev/null @@ -1,376 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Copyright (c) 2021 Sartura Ltd. - * - * Driver for the SMSC/Microchip EMC2301/2/3/5 fan controller. - * - * Author: Robert Marko - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define MANUFACTURER_ID_REG 0xfe -#define SMSC_MANUFACTURER_ID 0x5d - -#define PRODUCT_ID_REG 0xfd -#define EMC2305_PRODUCT_ID 0x34 -#define EMC2303_PRODUCT_ID 0x35 -#define EMC2302_PRODUCT_ID 0x36 -#define EMC2301_PRODUCT_ID 0x37 - -#define TACH1_HIGH_BYTE 0x3e -#define TACH1_LOW_BYTE 0x3f - -#define FAN1_CONFIG 0x32 -#define FAN_TACH_RANGE_MASK GENMASK(6, 5) -#define FAN_TACH_MULTIPLIER_8 3 -#define FAN_TACH_MULTIPLIER_4 2 -#define FAN_TACH_MULTIPLIER_2 1 -#define FAN_TACH_MULTIPLIER_1 0 -#define FAN_TACH_CONSTANT 3932160 -#define FAN_TACH_READING_MASK GENMASK(15,3) - -#define TACH1_TARGET_LOW_BYTE 0x3c -#define TACH1_TARGET_HIGH_BYTE 0x3d -#define TACH_HIGH_MASK GENMASK(12,5) -#define TACH_LOW_MASK GENMASK(4,0) - -#define FANX_OFFSET 0x10 -#define FAN_NUM_MAX 5 - -struct emc2305_fan_data { - u32 min_rpm; - u32 max_rpm; - u32 target_rpm; -}; - -struct emc2305_data { - struct regmap *regmap; - struct i2c_client *client; - struct emc2305_fan_data fan_data[FAN_NUM_MAX]; -}; - -static struct regmap_config emc2305_regmap_config = { - .reg_bits = 8, - .val_bits = 8, - .max_register = 0xff, -}; - -static int emc2305_read_fan(struct emc2305_data *data, int channel, - long *val) -{ - unsigned int regval, high_byte, low_byte; - u8 range, multiplier; - int ret; - - ret = regmap_read(data->regmap, - FAN1_CONFIG + channel * FANX_OFFSET, - ®val); - if (ret < 0) - return ret; - - range = FIELD_GET(FAN_TACH_RANGE_MASK, regval); - - switch (range) { - case FAN_TACH_MULTIPLIER_8: - multiplier = 8; - break; - case FAN_TACH_MULTIPLIER_4: - multiplier = 4; - break; - case FAN_TACH_MULTIPLIER_2: - multiplier = 2; - break; - case FAN_TACH_MULTIPLIER_1: - multiplier = 1; - break; - default: - return -EINVAL; - } - - ret = regmap_read(data->regmap, - TACH1_HIGH_BYTE + channel * FANX_OFFSET, - &high_byte); - if (ret < 0) - return ret; - - ret = regmap_read(data->regmap, - TACH1_LOW_BYTE + channel * FANX_OFFSET, - &low_byte); - if (ret < 0) - return ret; - - regval = (u8) high_byte << 8 | (u8) low_byte; - - *val = (FAN_TACH_CONSTANT * multiplier) / FIELD_GET(FAN_TACH_READING_MASK, regval); - - return 0; -} - -static int emc2305_read_fan_target(struct emc2305_data *data, int channel, - long *val) -{ - unsigned int regval; - int ret; - - ret = regmap_bulk_read(data->regmap, - TACH1_TARGET_LOW_BYTE + channel * FANX_OFFSET, - ®val, - 2); - if (ret < 0) - return ret; - - *val = regval; - - return 0; -} - -static int emc2305_set_fan_target(struct emc2305_data *data, int channel, - long val) -{ - int ret; - - ret = regmap_write(data->regmap, - TACH1_TARGET_LOW_BYTE + channel * FANX_OFFSET, - val & TACH_LOW_MASK); - if (ret < 0) - return ret; - - ret = regmap_write(data->regmap, - TACH1_TARGET_HIGH_BYTE + channel * FANX_OFFSET, - (val & TACH_HIGH_MASK) >> 5); - if (ret < 0) - return ret; - - return 0; -} - -static int emc2305_write(struct device *dev, enum hwmon_sensor_types type, - u32 attr, int channel, long val) -{ - struct emc2305_data *data = dev_get_drvdata(dev); - int err; - - switch (type) { - case hwmon_fan: - switch (attr) { - case hwmon_fan_target: - err = emc2305_set_fan_target(data, channel, val); - break; - default: - return -EOPNOTSUPP; - } - break; - default: - return -EOPNOTSUPP; - } - - return err; -} - -static int emc2305_read(struct device *dev, enum hwmon_sensor_types type, - u32 attr, int channel, long *val) -{ - struct emc2305_data *data = dev_get_drvdata(dev); - int err; - - switch (type) { - case hwmon_fan: - switch (attr) { - case hwmon_fan_input: - err = emc2305_read_fan(data, channel, val); - break; - case hwmon_fan_target: - err = emc2305_read_fan_target(data, channel, val); - break; - default: - return -EOPNOTSUPP; - } - break; - default: - return -EOPNOTSUPP; - } - - return err; -} - -static const char * const emc2305_fan_label[] = { - "Fan1", - "Fan2", - "Fan3", - "Fan4", - "Fan5", -}; - -static int emc2305_read_string(struct device *dev, - enum hwmon_sensor_types type, - u32 attr, int channel, const char **str) -{ - switch (type) { - case hwmon_fan: - *str = emc2305_fan_label[channel]; - break; - default: - return -EOPNOTSUPP; - } - - return 0; -} - -static umode_t emc2305_is_visible(const void *data, enum hwmon_sensor_types type, - u32 attr, int channel) -{ - switch (type) { - case hwmon_fan: - switch (attr) { - case hwmon_fan_input: - case hwmon_fan_label: - return 0444; - case hwmon_fan_target: - return 0644; - default: - return 0; - } - default: - return 0; - } -} - -static const struct hwmon_channel_info *emc2301_info[] = { - HWMON_CHANNEL_INFO(fan, - HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_LABEL), - NULL -}; - -static const struct hwmon_channel_info *emc2302_info[] = { - HWMON_CHANNEL_INFO(fan, - HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_LABEL, - HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_LABEL), - NULL -}; - -static const struct hwmon_channel_info *emc2303_info[] = { - HWMON_CHANNEL_INFO(fan, - HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_LABEL, - HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_LABEL, - HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_LABEL), - NULL -}; - -static const struct hwmon_channel_info *emc2305_info[] = { - HWMON_CHANNEL_INFO(fan, - HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_LABEL, - HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_LABEL, - HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_LABEL, - HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_LABEL, - HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_LABEL), - NULL -}; - -static const struct hwmon_ops emc2305_hwmon_ops = { - .is_visible = emc2305_is_visible, - .write = emc2305_write, - .read = emc2305_read, - .read_string = emc2305_read_string, -}; - -static struct hwmon_chip_info emc2305_chip_info = { - .ops = &emc2305_hwmon_ops, -}; - -static int emc2305_probe(struct i2c_client *client) -{ - struct device *dev = &client->dev; - struct emc2305_data *data; - struct device *hwmon_dev; - const char *model_name; - unsigned int regval; - int ret; - - data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); - if (!data) - return -ENOMEM; - - data->client = client; - i2c_set_clientdata(client, data); - - data->regmap = devm_regmap_init_i2c(client, &emc2305_regmap_config); - if (IS_ERR(data->regmap)) { - dev_err(dev, "failed to allocate register map\n"); - return PTR_ERR(data->regmap); - } - - ret = regmap_read(data->regmap, MANUFACTURER_ID_REG, ®val); - if (ret < 0) - return ret; - - if (regval != SMSC_MANUFACTURER_ID) { - dev_err(dev, "Invalid manufacturer id: 0x%x\n", regval); - return -ENODEV; - } - - ret = regmap_read(data->regmap, PRODUCT_ID_REG, ®val); - if (ret < 0) - return ret; - - switch (regval) { - case EMC2305_PRODUCT_ID: - model_name = "emc2305"; - emc2305_chip_info.info = emc2305_info; - break; - case EMC2303_PRODUCT_ID: - model_name = "emc2303"; - emc2305_chip_info.info = emc2303_info; - break; - case EMC2302_PRODUCT_ID: - model_name = "emc2302"; - emc2305_chip_info.info = emc2302_info; - break; - case EMC2301_PRODUCT_ID: - model_name = "emc2301"; - emc2305_chip_info.info = emc2301_info; - break; - default: - dev_err(dev, "Unknown ID detected: 0x%x\n", regval); - return -ENODEV; - } - - dev_info(dev, "%s detected\n", model_name); - - hwmon_dev = devm_hwmon_device_register_with_info(dev, model_name, - data, &emc2305_chip_info, - NULL); - if (IS_ERR(hwmon_dev)) - return PTR_ERR(hwmon_dev); - - return 0; -} - -static const struct of_device_id emc2305_of_match[] = { - { .compatible = "smsc,emc2301", }, - { .compatible = "smsc,emc2302", }, - { .compatible = "smsc,emc2303", }, - { .compatible = "smsc,emc2305", }, - { }, -}; -MODULE_DEVICE_TABLE(of, emc2305_of_match); - -static struct i2c_driver emc2305_driver = { - .probe_new = emc2305_probe, - .driver = { - .name = "emc2305", - .of_match_table = of_match_ptr(emc2305_of_match), - }, -}; -module_i2c_driver(emc2305_driver); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Robert Marko "); -MODULE_DESCRIPTION("SMSC EMC2301/2/3/5 fan controller"); diff --git a/target/linux/ipq807x/files-5.15/arch/arm64/boot/dts/qcom/ipq8070-tl-er2260t.dts b/target/linux/ipq807x/files-5.15/arch/arm64/boot/dts/qcom/ipq8070-tl-er2260t.dts deleted file mode 100644 index fb6d4b831..000000000 --- a/target/linux/ipq807x/files-5.15/arch/arm64/boot/dts/qcom/ipq8070-tl-er2260t.dts +++ /dev/null @@ -1,666 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* Copyright (c) 2020 The Linux Foundation. All rights reserved. - */ - -/dts-v1/; - -#include "ipq8074.dtsi" -#include "ipq8074-ess.dtsi" -#include "ipq8074-hk-cpu.dtsi" -#include -#include -#include -/ { - #address-cells = <0x2>; - #size-cells = <0x2>; - model = "TP-Link TL-ER2260T"; - compatible = "tplink,tl-er2260t", "qcom,ipq8074"; - qcom,msm-id = <0x143 0x0>; - interrupt-parent = <&intc>; - - aliases { - led-boot = &led_sys; - led-failsafe = &led_sys; - led-running = &led_sys; - led-upgrade = &led_sys; - serial0 = &blsp1_uart5; - - ethernet0 = "/soc/dp1"; - ethernet1 = "/soc/dp2"; - ethernet2 = "/soc/dp3"; - ethernet3 = "/soc/dp4"; - ethernet4 = "/soc/dp5"; - ethernet5 = "/soc/dp6"; - }; - - chosen { - stdout-path = "serial0"; - bootargs-append = " root=/dev/ubiblock0_1"; - }; - - gpio_keys { - compatible = "gpio-keys"; - pinctrl-0 = <&button_pins>; - pinctrl-names = "default"; - - reset { - label = "reset"; - linux,code = ; - gpios = <&tlmm 50 GPIO_ACTIVE_LOW>; - linux,input-type = <1>; - debounce-interval = <60>; - }; - }; - - leds { - compatible = "gpio-leds"; - pinctrl-0 = <&leds_pins>; - pinctrl-names = "default"; - - led_sys: sys { - label = "green:sys"; - gpios = <&tlmm 21 GPIO_ACTIVE_HIGH>; - }; - - usb { - label = "green:usb"; - gpios = <&tlmm 22 GPIO_ACTIVE_HIGH>; - linux,default-trigger = "usbport"; - }; - - sfp1-green { - label = "green:sfp1"; - gpios = <&tlmm 51 GPIO_ACTIVE_HIGH>; - }; - - sfp2-green { - label = "green:sfp2"; - gpios = <&tlmm 55 GPIO_ACTIVE_HIGH>; - }; - }; - - spi@78b5000 { - status = "ok"; - pinctrl-0 = <&spi_0_pins>; - pinctrl-names = "default"; - cs-select = <0>; - - m25p80@0 { - compatible = "n25q128a11"; - #address-cells = <1>; - #size-cells = <1>; - reg = <0>; - spi-max-frequency = <50000000>; - }; - }; -}; - -&tlmm { - mdio_pins: mdio_pinmux { - mux_0 { - pins = "gpio68"; - function = "mdc"; - drive-strength = <8>; - bias-pull-up; - }; - mux_1 { - pins = "gpio69"; - function = "mdio"; - drive-strength = <8>; - bias-pull-up; - }; - mux_2 { - pins = "gpio44"; - function = "gpio"; - bias-pull-up; - }; - }; - - i2c_1_pins: i2c_1_pins { - pins = "gpio46", "gpio47"; - function = "blsp2_i2c"; - drive-strength = <8>; - bias-disable; - }; - - button_pins: button_pins { - reset { - pins = "gpio50"; - function = "gpio"; - drive-strength = <8>; - bias-pull-up; - }; - }; - - uniphy_pins: uniphy_pinmux { - mux { - pins = "gpio60"; - function = "rx2"; - bias-disable; - }; - sfp_tx { - pins = "gpio59"; - function = "gpio"; - drive-strength = <8>; - bias-pull-down; - output-high; - }; - }; - - leds_pins: leds_pinmux { - mux { - pins = "gpio21", "gpio22", "gpio65"; - function = "gpio"; - drive-strength = <8>; - bias-pull-down; - }; - led_sfp1_active { - pins = "gpio51"; - function = "gpio"; - drive-strength = <8>; - bias-pull-down; - }; - led_sfp2_active { - pins = "gpio55"; - function = "gpio"; - drive-strength = <8>; - bias-pull-down; - }; - }; -}; - -&mdio { - status = "okay"; - pinctrl-0 = <&mdio_pins>; - pinctrl-names = "default"; - reset-gpios = <&tlmm 37 GPIO_ACTIVE_LOW>; - - phy0:ethernet-phy@0 { - compatible = "ethernet-phy-ieee802.3-c22"; - reg = <0>; - }; - phy1:ethernet-phy@1 { - compatible = "ethernet-phy-ieee802.3-c22"; - reg = <1>; - }; - phy2:ethernet-phy@2 { - compatible = "ethernet-phy-ieee802.3-c22"; - reg = <2>; - }; - phy3:ethernet-phy@3 { - compatible = "ethernet-phy-ieee802.3-c22"; - reg = <3>; - }; - phy4: ethernet-phy@29 { - reg = <29>; - }; - phy5: ethernet-phy@30 { - reg = <30>; - }; -}; - -&switch { - status = "okay"; - switch_cpu_bmp = <0x1>; /* cpu port bitmap */ - switch_lan_bmp = <0x3e>; /* lan port bitmap */ - switch_wan_bmp = <0x40>; /* wan port bitmap */ - switch_mac_mode = <0xb>; /* mac mode for uniphy instance0*/ - switch_mac_mode1 = <0xe>; /* mac mode for uniphy instance1*/ //use 10g_baser mode for default - switch_mac_mode2 = <0xe>; /* mac mode for uniphy instance2*/ //use 10g_baser mode for default - bm_tick_mode = <0>; /* bm tick mode */ - tm_tick_mode = <0>; /* tm tick mode */ - cmnblk_clk = "external_50MHz"; - - 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 = <29>;//29 - phy_i2c_address = <29>;//29 - phy-i2c-mode; /*i2c access phy */ - media-type = "sfp"; /* fiber mode */ - }; - port@5 { - port_id = <6>; - phy_address = <30>;//30 - phy_i2c_address = <30>;//30 - phy-i2c-mode; /*i2c access phy */ - media-type = "sfp"; /* fiber mode */ - }; - }; - 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>; - }; - }; - }; - }; -}; - -&soc { - dp1: dp1 { - device_type = "network"; - compatible = "qcom,nss-dp"; - qcom,id = <1>; - reg = <0x3a001000 0x200>; - qcom,mactype = <0>; - local-mac-address = [000000000000]; - qcom,link-poll = <1>; - qcom,phy-mdio-addr = <0>; - phy-mode = "sgmii"; - mdio-bus = <&mdio>; - }; - dp2: dp2 { - device_type = "network"; - compatible = "qcom,nss-dp"; - qcom,id = <2>; - reg = <0x3a001200 0x200>; - qcom,mactype = <0>; - local-mac-address = [000000000000]; - qcom,link-poll = <1>; - qcom,phy-mdio-addr = <1>; - phy-mode = "sgmii"; - mdio-bus = <&mdio>; - }; - dp3: dp3 { - device_type = "network"; - compatible = "qcom,nss-dp"; - qcom,id = <3>; - reg = <0x3a001400 0x200>; - qcom,mactype = <0>; - local-mac-address = [000000000000]; - qcom,link-poll = <1>; - qcom,phy-mdio-addr = <2>; - phy-mode = "sgmii"; - mdio-bus = <&mdio>; - }; - dp4: dp4 { - device_type = "network"; - compatible = "qcom,nss-dp"; - qcom,id = <4>; - reg = <0x3a001600 0x200>; - qcom,mactype = <0>; - local-mac-address = [000000000000]; - qcom,link-poll = <1>; - qcom,phy-mdio-addr = <3>; - phy-mode = "sgmii"; - mdio-bus = <&mdio>; - }; - dp5: dp5 { - device_type = "network"; - compatible = "qcom,nss-dp"; - qcom,id = <5>; - reg = <0x3a001800 0x200>; - qcom,mactype = <1>; - local-mac-address = [000000000000]; - qcom,link-poll = <1>; - qcom,phy-mdio-addr = <29>; - phy-mode = "sgmii"; - mdio-bus = <&mdio>; - }; - dp6: dp6 { - device_type = "network"; - compatible = "qcom,nss-dp"; - qcom,id = <6>; - reg = <0x3a007000 0x3fff>; - qcom,mactype = <1>; - local-mac-address = [000000000000]; - qcom,link-poll = <1>; - qcom,phy-mdio-addr = <30>; - phy-mode = "sgmii"; - mdio-bus = <&mdio>; - }; - - nss-macsec1 { - compatible = "qcom,nss-macsec"; - phy_addr = <0x1c>; - phy_access_mode = <0x00>; - mdiobus = <&mdio>; - }; - - watchdog@b017000 { - compatible = "qcom,kpss-wdt-ipq807x"; - reg = <0xb017000 0x1000>; - reg-names = "kpss_wdt"; - interrupt-names = "bark_irq"; - interrupts = <0x00 0x03 0x00>; - clocks = <&sleep_clk>; - timeout-sec = <0x0a>; - wdt-max-timeout = <0x20>; - }; -}; - -&blsp1_i2c2 { - status = "okay"; -}; - -&blsp1_i2c3 { - pinctrl-0 = <&i2c_1_pins>; - pinctrl-names = "default"; - status = "okay"; -}; - -&blsp1_uart5 { - status = "okay"; -}; - -&cryptobam { - status = "okay"; -}; - -&crypto { - status = "okay"; -}; - -&qpic_bam { - status = "okay"; -}; - -&qpic_nand { - status = "okay"; - - nand@0 { - reg = <0>; - #address-cells = <1>; - #size-cells = <1>; - 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"; -}; - -&usb_0 { - status = "okay"; -}; diff --git a/target/linux/ipq807x/files-5.15/arch/arm64/boot/dts/qcom/ipq8071-ax3600.dts b/target/linux/ipq807x/files-5.15/arch/arm64/boot/dts/qcom/ipq8071-ax3600.dts deleted file mode 100644 index 3af5a3471..000000000 --- a/target/linux/ipq807x/files-5.15/arch/arm64/boot/dts/qcom/ipq8071-ax3600.dts +++ /dev/null @@ -1,71 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later OR MIT -/* Copyright (c) 2021, Robert Marko */ - -/dts-v1/; - -#include "ipq8071-ax3600.dtsi" - -/ { - model = "Xiaomi AX3600"; - compatible = "xiaomi,ax3600", "qcom,ipq8074"; - - leds { - compatible = "gpio-leds"; - - led_system_blue: system-blue { - label = "blue:system"; - gpios = <&tlmm 42 GPIO_ACTIVE_HIGH>; - }; - - led_system_yellow: system-yellow { - label = "yellow:system"; - gpios = <&tlmm 43 GPIO_ACTIVE_HIGH>; - }; - - network-yellow { - label = "yellow:network"; - gpios = <&tlmm 22 GPIO_ACTIVE_HIGH>; - }; - - network-blue { - label = "blue:network"; - gpios = <&tlmm 21 GPIO_ACTIVE_HIGH>; - }; - - aiot { - label = "blue:aiot"; - gpios = <&tlmm 51 GPIO_ACTIVE_HIGH>; - linux,default-trigger = "phy0tpt"; - }; - }; -}; - -&pcie_qmp0 { - status = "okay"; -}; - -&pcie0 { - status = "okay"; - - perst-gpio = <&tlmm 52 GPIO_ACTIVE_HIGH>; - - bridge@0,0 { - reg = <0x00000000 0 0 0 0>; - #address-cells = <3>; - #size-cells = <2>; - ranges; - - wifi0: wifi@1,0 { - status = "okay"; - - compatible = "qcom,ath10k"; - reg = <0x00010000 0 0 0 0>; - - qcom,ath10k-calibration-variant = "Xiaomi-AX3600"; - }; - }; -}; - -&wifi { - qcom,ath11k-calibration-variant = "Xiaomi-AX3600"; -}; diff --git a/target/linux/ipq807x/files-5.15/arch/arm64/boot/dts/qcom/ipq8071-ax3600.dtsi b/target/linux/ipq807x/files-5.15/arch/arm64/boot/dts/qcom/ipq8071-ax3600.dtsi deleted file mode 100644 index 2c29da383..000000000 --- a/target/linux/ipq807x/files-5.15/arch/arm64/boot/dts/qcom/ipq8071-ax3600.dtsi +++ /dev/null @@ -1,494 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later OR MIT -/* Copyright (c) 2021, Robert Marko */ - -#include "ipq8074-512m.dtsi" -#include "ipq8074-ac-cpu.dtsi" -#include "ipq8074-ess.dtsi" -#include -#include - -/ { - #address-cells = <2>; - #size-cells = <2>; - - interrupt-parent = <&intc>; - - aliases { - serial0 = &blsp1_uart5; - led-boot = &led_system_yellow; - led-failsafe = &led_system_yellow; - led-running = &led_system_blue; - led-upgrade = &led_system_yellow; - /* Aliases as required by u-boot to patch MAC addresses */ - ethernet1 = &dp2; - ethernet2 = &dp3; - ethernet3 = &dp4; - ethernet4 = &dp5; - label-mac-device = &dp2; - }; - - chosen { - stdout-path = "serial0:115200n8"; - bootargs-append = " root=/dev/ubiblock0_1"; - }; - - keys { - compatible = "gpio-keys"; - - reset { - label = "reset"; - gpios = <&tlmm 34 GPIO_ACTIVE_LOW>; - linux,code = ; - }; - }; -}; - -&tlmm { - mdio_pins: mdio-pins { - mdc { - pins = "gpio68"; - function = "mdc"; - drive-strength = <8>; - bias-pull-up; - }; - - mdio { - pins = "gpio69"; - function = "mdio"; - drive-strength = <8>; - bias-pull-up; - }; - }; -}; - -&blsp1_uart5 { - status = "okay"; -}; - -&prng { - status = "okay"; -}; - -&cryptobam { - status = "okay"; -}; - -&crypto { - 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 37 GPIO_ACTIVE_LOW>; - - ethernet-phy@1 { - reg = <1>; - }; - - ethernet-phy@2 { - reg = <2>; - }; - - ethernet-phy@3 { - reg = <3>; - }; - - ethernet-phy@4 { - 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_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*/ - bm_tick_mode = <0>; /* bm tick mode */ - tm_tick_mode = <0>; /* tm tick mode */ - - 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>; - }; - }; - - 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>; - }; - }; - }; - }; -}; - -&edma { - status = "okay"; -}; - -&soc { - dp2: dp2 { - device_type = "network"; - compatible = "qcom,nss-dp"; - qcom,id = <2>; - reg = <0x3a001200 0x200>; - qcom,mactype = <0>; - local-mac-address = [000000000000]; - qcom,link-poll = <1>; - qcom,phy-mdio-addr = <1>; - phy-mode = "sgmii"; - mdio-bus = <&mdio>; - }; - - dp3: dp3 { - device_type = "network"; - compatible = "qcom,nss-dp"; - qcom,id = <3>; - reg = <0x3a001400 0x200>; - qcom,mactype = <0>; - local-mac-address = [000000000000]; - qcom,link-poll = <1>; - qcom,phy-mdio-addr = <2>; - phy-mode = "sgmii"; - mdio-bus = <&mdio>; - }; - - dp4: dp4 { - device_type = "network"; - compatible = "qcom,nss-dp"; - qcom,id = <4>; - reg = <0x3a001600 0x200>; - qcom,mactype = <0>; - local-mac-address = [000000000000]; - qcom,link-poll = <1>; - qcom,phy-mdio-addr = <3>; - phy-mode = "sgmii"; - mdio-bus = <&mdio>; - }; - - dp5: dp5 { - device_type = "network"; - compatible = "qcom,nss-dp"; - qcom,id = <5>; - reg = <0x3a001800 0x200>; - qcom,mactype = <0>; - local-mac-address = [000000000000]; - qcom,link-poll = <1>; - qcom,phy-mdio-addr = <4>; - phy-mode = "sgmii"; - mdio-bus = <&mdio>; - }; -}; - -&wifi { - status = "okay"; - - qcom,board_id = <658>; -}; diff --git a/target/linux/ipq807x/files-5.15/arch/arm64/boot/dts/qcom/ipq8071-ax6.dts b/target/linux/ipq807x/files-5.15/arch/arm64/boot/dts/qcom/ipq8071-ax6.dts deleted file mode 100644 index c66fb95bc..000000000 --- a/target/linux/ipq807x/files-5.15/arch/arm64/boot/dts/qcom/ipq8071-ax6.dts +++ /dev/null @@ -1,39 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later OR MIT -/* Copyright (c) 2021, Zhijun You */ - -/dts-v1/; - -#include "ipq8071-ax3600.dtsi" - -/ { - model = "Redmi AX6"; - compatible = "redmi,ax6", "qcom,ipq8074"; - - leds { - compatible = "gpio-leds"; - - led_system_blue: system-blue { - label = "blue:system"; - gpios = <&tlmm 21 GPIO_ACTIVE_HIGH>; - }; - - led_system_yellow: system-yellow { - label = "yellow:system"; - gpios = <&tlmm 22 GPIO_ACTIVE_HIGH>; - }; - - network-blue { - label = "blue:network"; - gpios = <&tlmm 42 GPIO_ACTIVE_HIGH>; - }; - - network-yellow { - label = "yellow:network"; - gpios = <&tlmm 43 GPIO_ACTIVE_HIGH>; - }; - }; -}; - -&wifi { - qcom,ath11k-calibration-variant = "Redmi-AX6"; -}; diff --git a/target/linux/ipq807x/files-5.15/arch/arm64/boot/dts/qcom/ipq8071-mf269.dts b/target/linux/ipq807x/files-5.15/arch/arm64/boot/dts/qcom/ipq8071-mf269.dts deleted file mode 100644 index a6f7f1741..000000000 --- a/target/linux/ipq807x/files-5.15/arch/arm64/boot/dts/qcom/ipq8071-mf269.dts +++ /dev/null @@ -1,587 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later OR MIT -/* Copyright (c) 2021, ZhiPing */ - -/dts-v1/; - -#include "ipq8074-512m.dtsi" -#include "ipq8074-ac-cpu.dtsi" -#include "ipq8074-ess.dtsi" -#include "ipq8074-ac-nss.dtsi" - -#include -#include - -/ { - #address-cells = <2>; - #size-cells = <2>; - - model = "ZTE MF269"; - compatible = "zte,mf269", "qcom,ipq8074"; - interrupt-parent = <&intc>; - - aliases { - led-boot = &led_power; - led-failsafe = &led_power; - led-running = &led_power; - led-upgrade = &led_power; - serial0 = &blsp1_uart5; - }; - - chosen { - stdout-path = "serial0:115200n8"; - bootargs-append = " root=/dev/ubiblock0_1"; - }; - - keys { - compatible = "gpio-keys"; - - reset { - label = "reset"; - linux,code = ; - gpios = <&tlmm 46 GPIO_ACTIVE_LOW>; - }; - - wps { - label = "wps"; - linux,code = ; - gpios = <&tlmm 37 GPIO_ACTIVE_LOW>; - }; - }; - - leds { - compatible = "gpio-leds"; - - led_power: power { - label = "white:power"; - gpio = <&tlmm 56 GPIO_ACTIVE_HIGH>; - }; - }; - - soc { - dp5: dp5 { - device_type = "network"; - compatible = "qcom,nss-dp"; - qcom,id = <5>; - reg = <0x3a003000 0x3fff>; - qcom,mactype = <1>; - local-mac-address = [000000000000]; - qcom,link-poll = <1>; - qcom,phy-mdio-addr = <24>; - phy-mode = "sgmii"; - mdio-bus = <&mdio>; - }; - - dp6: dp6 { - device_type = "network"; - compatible = "qcom,nss-dp"; - qcom,id = <6>; - reg = <0x3a007000 0x3fff>; - qcom,mactype = <1>; - local-mac-address = [000000000000]; - qcom,link-poll = <1>; - qcom,phy-mdio-addr = <28>; - phy-mode = "sgmii"; - mdio-bus = <&mdio>; - }; - }; -}; - -&blsp1_spi1 { - status = "okay"; - pinctrl-0 = <&spi_0_pins>; - pinctrl-names = "default"; - cs-select = <0>; - - flash@0 { - compatible = "jedec,spi-nor", "n25q128a11"; - #address-cells = <1>; - #size-cells = <1>; - reg = <0>; - spi-max-frequency = <50000000>; - }; -}; - -/* -&blsp1_spi6 { - status = "okay"; - pinctrl-0 = <&spi_5_pins>; - pinctrl-names = "default"; - cs-select = <0>; - - si3217x@0 { - compatible = "si3217x"; - num_slic = <1>; - reg = <0>; - spi-cpha; - spi-cpol; - spi-max-frequency = <960000>; - pinctrl-0 = <&slic_ctl_pins>; - pinctrl-names = "default"; - ctl-gpio = <&tlmm 57 0>; - rst-gpio = <&tlmm 58 0>; - irq-gpio = <&tlmm 59 0>; - }; -}; - -&blsp1_i2c5 { - status = "okay"; - - pinctrl-0 = <&i2c_4_pins>; - pinctrl-names = "default"; - - aw9106b@5b { - compatible = "aw9106b"; - reg = <0x5b>; - reset-gpio = <&tlmm 54 0>; - }; -}; -*/ - -&blsp1_uart5 { - status = "okay"; -}; - -&cryptobam { - status = "okay"; -}; - -&crypto { - status = "okay"; -}; - -&edma { - status = "okay"; -}; - -&switch { - status = "okay"; - - switch_cpu_bmp = <0x1>; /* cpu port bitmap */ - switch_lan_bmp = <0x3e>; /* lan port bitmap */ - switch_wan_bmp = <0x40>; /* wan port bitmap */ - switch_mac_mode = <0x0>; /* mac mode for uniphy instance0*/ - switch_mac_mode1 = <0xf>; /* mac mode for uniphy instance1*/ - switch_mac_mode2 = <0xf>; /* mac mode for uniphy instance2*/ - bm_tick_mode = <0>; /* bm tick mode */ - tm_tick_mode = <0>; /* tm tick mode */ - - qcom,port_phyinfo { - port@4 { - port_id = <5>; - phy_address = <24>; - port_mac_sel = "QGMAC_PORT"; - }; - port@5 { - port_id = <6>; - phy_address = <28>; - port_mac_sel = "QGMAC_PORT"; - }; - }; - - 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>; - }; - }; - }; - }; -}; - -&mdio { - status = "okay"; - - pinctrl-0 = <&mdio_pins>; - pinctrl-names = "default"; - //reset-gpios = <&tlmm 37 GPIO_ACTIVE_LOW>; - - ethernet-phy@4 { - reg = <24>; - //reset-gpios = <&tlmm 44 GPIO_ACTIVE_LOW>; - }; - - ethernet-phy@5 { - reg = <28>; - //reset-gpios = <&tlmm 25 GPIO_ACTIVE_LOW>; - }; -}; - -&prng { - 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"; - }; - }; -}; - -&qusb_phy_0 { - status = "okay"; -}; - -&ssphy_0 { - status = "okay"; -}; - -&tlmm { - i2c_4_pins: i2c-4-pinmux { - pins = "gpio21", "gpio22"; - function = "blsp4_i2c1"; - drive-strength = <8>; - bias-disable; - }; - - slic_ctl_pins: slic_ctl_pins { - mux { - pins = "gpio59"; - function = "gpio"; - bias-pull-up; - }; - }; - - spi_5_pins: spi-5-pins { - pins = "gpio0", "gpio2", "gpio9", "gpio16"; - function = "blsp5_spi"; - drive-strength = <8>; - bias-disable; - }; - - mdio_pins: mdio_pinmux { - mux_0 { - pins = "gpio68"; - function = "mdc"; - drive-strength = <8>; - bias-pull-up; - }; - - mux_1 { - pins = "gpio69"; - function = "mdio"; - drive-strength = <8>; - bias-pull-up; - }; - - mux_2 { - pins = "gpio25"; - function = "gpio"; - bias-pull-up; - }; - - mux_3 { - pins = "gpio44"; - function = "gpio"; - bias-pull-up; - }; - }; - - usb_vbus_pins: usb_vbus_pins { - mux { - pins = "gpio29"; - function = "gpio"; - drive-strength = <8>; - bias-disable; - output-high; - }; - }; - - usb_cc_pins: usb_cc_pins { - mux { - pins = "gpio47", "gpio48"; - function = "gpio"; - drive-strength = <8>; - bias-disable; - output-high; - }; - }; -}; - -&usb_0 { - pinctrl-0 = <&usb_vbus_pins &usb_cc_pins>; - pinctrl-names = "default"; - status = "okay"; -}; - -&wifi { - status = "okay"; - - qcom,board_id = <658>; - qcom,ath11k-calibration-variant = "ZTE-MF269"; -}; diff --git a/target/linux/ipq807x/files-5.15/arch/arm64/boot/dts/qcom/ipq8072-301w.dts b/target/linux/ipq807x/files-5.15/arch/arm64/boot/dts/qcom/ipq8072-301w.dts deleted file mode 100644 index d00951824..000000000 --- a/target/linux/ipq807x/files-5.15/arch/arm64/boot/dts/qcom/ipq8072-301w.dts +++ /dev/null @@ -1,820 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later OR MIT -/* Copyright (c) 2021, Dirk Buchwalder */ - -/dts-v1/; - -#include "ipq8074.dtsi" -#include "ipq8074-hk-cpu.dtsi" -#include "ipq8074-ess.dtsi" -#include -#include -#include - -/ { - #address-cells = <2>; - #size-cells = <2>; - - model = "QNAP 301w"; - compatible = "qnap,301w", "qcom,ipq8074"; - interrupt-parent = <&intc>; - - aliases { - serial0 = &blsp1_uart5; - /* - * Aliases as required by u-boot - * to patch MAC addresses - */ - led-boot = &led_system_red; - led-failsafe = &led_system_red; - led-running = &led_pwr_green; - led-upgrade = &led_system_red; - ethernet0 = &dp1; - ethernet1 = &dp2; - ethernet2 = &dp3; - ethernet3 = &dp4; - ethernet4 = &dp5; - ethernet5 = &dp6; - label-mac-device = &dp1; - }; - - chosen { - stdout-path = "serial0:115200n8"; - }; - - keys { - compatible = "gpio-keys"; - - wps { - label = "wps"; - gpios = <&tlmm 57 GPIO_ACTIVE_LOW>; - linux,code = ; - }; - - reset { - label = "reset"; - gpios = <&tlmm 67 GPIO_ACTIVE_LOW>; - linux,code = ; - }; - }; - - leds { - compatible = "gpio-leds"; - - led_system_green: system-green { - label = "green:system"; - gpios = <&tlmm 1 GPIO_ACTIVE_HIGH>; - color = ; - }; - - led_system_red: system-red { - label = "red:system"; - gpios = <&tlmm 3 GPIO_ACTIVE_HIGH>; - color = ; - }; - - led_pwr_green: pwr-green { - label = "green:pwr"; - gpios = <&tlmm 4 GPIO_ACTIVE_HIGH>; - color = ; - }; - - led_wifi_green: wifi-green { - label = "green:wifi"; - gpios = <&tlmm 42 GPIO_ACTIVE_HIGH>; - color = ; - }; - - led_lan1_green: lan1-green { - label = "green:lan1"; - gpios = <&tlmm 6 GPIO_ACTIVE_HIGH>; - color = ; - }; - - led_lan1_amber: lan1-amber { - label = "amber:lan1"; - gpios = <&tlmm 7 GPIO_ACTIVE_HIGH>; - color = ; - }; - - led_lan2_green: lan2-green { - label = "green:lan2"; - gpios = <&tlmm 8 GPIO_ACTIVE_HIGH>; - color = ; - }; - - led_lan2_amber: lan2-amber { - label = "amber:lan2"; - gpios = <&tlmm 11 GPIO_ACTIVE_HIGH>; - color = ; - }; - - led_lan3_green: lan3-green { - label = "green:lan3"; - gpios = <&tlmm 12 GPIO_ACTIVE_HIGH>; - color = ; - }; - - led_lan3_amber: lan3-amber { - label = "amber:lan3"; - gpios = <&tlmm 13 GPIO_ACTIVE_HIGH>; - color = ; - }; - - led_lan4_green: lan4-green { - label = "green:lan4"; - gpios = <&tlmm 14 GPIO_ACTIVE_HIGH>; - color = ; - }; - - led_lan4_amber: lan4-amber { - label = "amber:lan4"; - gpios = <&tlmm 15 GPIO_ACTIVE_HIGH>; - color = ; - }; - - led_10g_1_green: 10g_1-green { - label = "green:10g_1"; - gpios = <&tlmm 54 GPIO_ACTIVE_HIGH>; - color = ; - }; - - led_10g_1_amber: 10g_1-amber { - label = "amber:10g_1"; - gpios = <&tlmm 56 GPIO_ACTIVE_HIGH>; - color = ; - }; - - led_10g_2_green: 10g_2-green { - label = "green:10g_2"; - gpios = <&tlmm 51 GPIO_ACTIVE_HIGH>; - color = ; - }; - - led_10g_2_amber: 10g_2-amber { - label = "amber:10g_2"; - gpios = <&tlmm 52 GPIO_ACTIVE_HIGH>; - color = ; - }; - }; -}; - -&tlmm { - - mdio_pins: mdio-pins { - mdc { - pins = "gpio68"; - function = "mdc"; - drive-strength = <8>; - bias-pull-up; - }; - - mdio { - pins = "gpio69"; - function = "mdio"; - drive-strength = <8>; - bias-pull-up; - }; - }; - - button_pins: button_pins { - wps_button { - pins = "gpio57"; - function = "gpio"; - drive-strength = <8>; - bias-pull-up; - }; - - rst_button { - pins = "gpio67"; - function = "gpio"; - drive-strength = <8>; - bias-pull-up; - }; - }; - - qpic_pins: qpic-pins { - status = "disabled"; - /*disabling qpic-pins due to the leds are using all of the gpios*/ - }; - - leds_pins: leds_pinmux { - led_pwr_green { - pins = "gpio4"; - function = "gpio"; - drive-strength = <8>; - bias-pull-down; - }; - led_system_green { - pins = "gpio1"; - function = "gpio"; - drive-strength = <8>; - bias-pull-down; - }; - led_system_red { - pins = "gpio3"; - function = "gpio"; - drive-strength = <8>; - bias-pull-down; - }; - led_lan1_green { - pins = "gpio6"; - function = "gpio"; - drive-strength = <8>; - bias-pull-down; - }; - led_lan1_amber { - pins = "gpio7"; - function = "gpio"; - drive-strength = <8>; - bias-pull-down; - }; - led_lan2_green { - pins = "gpio8"; - function = "gpio"; - drive-strength = <8>; - bias-pull-down; - }; - led_lan2_amber { - pins = "gpio11"; - function = "gpio"; - drive-strength = <8>; - bias-pull-down; - }; - led_lan3_green { - pins = "gpio12"; - function = "gpio"; - drive-strength = <8>; - bias-pull-down; - }; - led_lan3_amber { - pins = "gpio13"; - function = "gpio"; - drive-strength = <8>; - bias-pull-down; - }; - led_lan4_green { - pins = "gpio14"; - function = "gpio"; - drive-strength = <8>; - bias-pull-down; - }; - led_lan4_amber { - pins = "gpio15"; - function = "gpio"; - drive-strength = <8>; - bias-pull-down; - }; - led_10g_1_green { - pins = "gpio54"; - function = "gpio"; - drive-strength = <8>; - bias-pull-down; - }; - led_10g_1_amber { - pins = "gpio56"; - function = "gpio"; - drive-strength = <8>; - bias-pull-down; - }; - led_10g_2_green { - pins = "gpio51"; - function = "gpio"; - drive-strength = <8>; - bias-pull-down; - }; - led_10g_2_amber { - pins = "gpio52"; - function = "gpio"; - drive-strength = <8>; - bias-pull-down; - }; - led_wifi_green { - pins = "gpio42"; - function = "gpio"; - drive-strength = <8>; - bias-pull-down; - }; - }; -}; - -&blsp1_uart5 { - status = "okay"; -}; - -&prng { - status = "okay"; -}; - -&ssphy_0 { - status = "okay"; -}; - -&qusb_phy_0 { - status = "okay"; -}; - -&ssphy_1 { - status = "okay"; -}; - -&qusb_phy_1 { - status = "okay"; -}; - -&usb_0 { - status = "okay"; -}; - -&usb_1 { - status = "okay"; -}; - -&cryptobam { - status = "okay"; -}; - -&crypto { - status = "okay"; -}; - -&qpic_bam { - status = "okay"; -}; - -&blsp1_spi1 { /* BLSP1 QUP1 */ - pinctrl-0 = <&spi_0_pins>; - pinctrl-names = "default"; - cs-gpios = <0>; - status = "okay"; - - flash@0 { - #address-cells = <1>; - #size-cells = <1>; - reg = <0>; - compatible = "jedec,spi-nor"; - spi-max-frequency = <50000000>; - - partitions { - compatible = "qcom,smem-part"; - }; - }; -}; - -&mdio { - status = "okay"; - - pinctrl-0 = <&mdio_pins>; - pinctrl-names = "default"; - reset-gpios = <&tlmm 37 GPIO_ACTIVE_LOW>; - - ethernet-phy@0 { - compatible ="ethernet-phy-ieee802.3-c45"; - reg = <0>; - reset-gpios = <&tlmm 59 GPIO_ACTIVE_LOW>; - }; - - ethernet-phy@8 { - compatible ="ethernet-phy-ieee802.3-c45"; - reg = <8>; - reset-gpios = <&tlmm 44 GPIO_ACTIVE_LOW>; - }; - - ethernet-phy@16 { - reg = <16>; - }; - - ethernet-phy@17 { - reg = <17>; - }; - - ethernet-phy@18 { - reg = <18>; - }; - - ethernet-phy@19 { - reg = <19>; - }; - -}; - -&sdhc_1 { - /* According to the stock dts from the QNAP gpl drop - * the emmc has a problem with the hs400 > hs200 speed switch. - * Therefore remove the mmc-hs400-1_8v property - */ - /delete-property/ mmc-hs400-1_8v; - mmc-hs200-1_8v; - mmc-ddr-1_8v; - vqmmc-supply = <&ldo11>; - status = "okay"; -}; - -&switch { - status = "okay"; - - switch_cpu_bmp = <0x1>; /* cpu port bitmap */ - switch_lan_bmp = <0x3e>; /* lan port bitmap */ - switch_wan_bmp = <0xc0>; /* wan port bitmap */ - switch_mac_mode = <0xb>; /* mac mode for uniphy instance0*/ - switch_mac_mode1 = <0xd>; /* mac mode for uniphy instance1*/ - switch_mac_mode2 = <0xd>; /* mac mode for uniphy instance2*/ - bm_tick_mode = <0>; /* bm tick mode */ - tm_tick_mode = <0>; /* tm tick mode */ - - qcom,port_phyinfo { - port@0 { - port_id = <1>; - phy_address = <16>; - }; - port@1 { - port_id = <2>; - phy_address = <17>; - }; - port@2 { - port_id = <3>; - phy_address = <18>; - }; - port@3 { - port_id = <4>; - phy_address = <19>; - }; - port@4 { - port_id = <5>; - phy_address = <8>; - compatible = "ethernet-phy-ieee802.3-c45"; - ethernet-phy-ieee802.3-c45; - }; - port@5 { - port_id = <6>; - phy_address = <0>; - compatible = "ethernet-phy-ieee802.3-c45"; - ethernet-phy-ieee802.3-c45; - }; - }; - - 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>; - }; - }; - }; - }; -}; - -&edma { - status = "okay"; -}; - -&soc { - dp1: dp1 { - device_type = "network"; - compatible = "qcom,nss-dp"; - qcom,id = <1>; - reg = <0x3a001000 0x200>; - qcom,mactype = <0>; - local-mac-address = [000000000000]; - qcom,link-poll = <1>; - qcom,phy-mdio-addr = <16>; - phy-mode = "sgmii"; - mdio-bus = <&mdio>; - }; - - dp2: dp2 { - device_type = "network"; - compatible = "qcom,nss-dp"; - qcom,id = <2>; - reg = <0x3a001200 0x200>; - qcom,mactype = <0>; - local-mac-address = [000000000000]; - qcom,link-poll = <1>; - qcom,phy-mdio-addr = <17>; - phy-mode = "sgmii"; - mdio-bus = <&mdio>; - }; - - dp3: dp3 { - device_type = "network"; - compatible = "qcom,nss-dp"; - qcom,id = <3>; - reg = <0x3a001400 0x200>; - qcom,mactype = <0>; - local-mac-address = [000000000000]; - qcom,link-poll = <1>; - qcom,phy-mdio-addr = <18>; - phy-mode = "sgmii"; - mdio-bus = <&mdio>; - }; - - dp4: dp4 { - device_type = "network"; - compatible = "qcom,nss-dp"; - qcom,id = <4>; - reg = <0x3a001600 0x200>; - qcom,mactype = <0>; - local-mac-address = [000000000000]; - qcom,link-poll = <1>; - qcom,phy-mdio-addr = <19>; - phy-mode = "sgmii"; - mdio-bus = <&mdio>; - }; - - dp5: dp5 { - device_type = "network"; - compatible = "qcom,nss-dp"; - qcom,id = <5>; - reg = <0x3a001800 0x200>; - qcom,mactype = <1>; - local-mac-address = [000000000000]; - qcom,link-poll = <1>; - qcom,phy-mdio-addr = <8>; - phy-mode = "sgmii"; - mdio-bus = <&mdio>; - }; - - dp6: dp6 { - device_type = "network"; - compatible = "qcom,nss-dp"; - qcom,id = <6>; - reg = <0x3a007000 0x3fff>; - qcom,mactype = <1>; - local-mac-address = [000000000000]; - qcom,link-poll = <1>; - qcom,phy-mdio-addr = <0>; - phy-mode = "sgmii"; - mdio-bus = <&mdio>; - }; -}; - -&wifi { - status = "okay"; - /* using board_id 0xff is intentionally - * as the stock firmware is also using this default board_id - */ - qcom,board_id = <0xff>; - qcom,ath11k-calibration-variant = "QNAP-301w"; -}; diff --git a/target/linux/ipq807x/files-5.15/arch/arm64/boot/dts/qcom/ipq8074-ac-nss.dtsi b/target/linux/ipq807x/files-5.15/arch/arm64/boot/dts/qcom/ipq8074-ac-nss.dtsi deleted file mode 100644 index 3b10e151b..000000000 --- a/target/linux/ipq807x/files-5.15/arch/arm64/boot/dts/qcom/ipq8074-ac-nss.dtsi +++ /dev/null @@ -1,256 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only - -&soc { - dummy_reg: dummy-regulator@0 { - compatible = "regulator-fixed"; - regulator-name = "dummy-reg"; - regulator-min-microvolt = <848000>; - regulator-max-microvolt = <848000>; - regulator-always-on; - regulator-boot-on; - }; - - nss-common { - compatible = "qcom,nss-common"; - reg = <0x01868010 0x1000>; - reg-names = "nss-misc-reset"; - }; - - nss0: nss@40000000 { - compatible = "qcom,nss"; - interrupts = , - , - , - , - , - , - , - , - , - ; - reg = <0x39000000 0x1000>, - <0x38000000 0x30000>, - <0x0b111000 0x1000>; - reg-names = "nphys", "vphys", "qgic-phys"; - clocks = <&gcc GCC_NSS_NOC_CLK>, - <&gcc GCC_NSS_PTP_REF_CLK>, - <&gcc GCC_NSS_CSR_CLK>, <&gcc GCC_NSS_CFG_CLK>, - <&gcc GCC_NSS_IMEM_CLK>, - <&gcc GCC_NSSNOC_QOSGEN_REF_CLK>, - <&gcc GCC_MEM_NOC_NSS_AXI_CLK>, - <&gcc GCC_NSSNOC_SNOC_CLK>, - <&gcc GCC_NSSNOC_TIMEOUT_REF_CLK>, - <&gcc GCC_NSS_CE_AXI_CLK>, - <&gcc GCC_NSS_CE_APB_CLK>, - <&gcc GCC_NSSNOC_CE_AXI_CLK>, - <&gcc GCC_NSSNOC_CE_APB_CLK>, - <&gcc GCC_NSSNOC_UBI0_AHB_CLK>, - <&gcc GCC_UBI0_CORE_CLK>, - <&gcc GCC_UBI0_AHB_CLK>, - <&gcc GCC_UBI0_AXI_CLK>, - <&gcc GCC_UBI0_MPT_CLK>, - <&gcc GCC_UBI0_NC_AXI_CLK>; - clock-names = "nss-noc-clk", "nss-ptp-ref-clk", - "nss-csr-clk", "nss-cfg-clk", - "nss-imem-clk", - "nss-nssnoc-qosgen-ref-clk", - "nss-mem-noc-nss-axi-clk", - "nss-nssnoc-snoc-clk", - "nss-nssnoc-timeout-ref-clk", - "nss-ce-axi-clk", "nss-ce-apb-clk", - "nss-nssnoc-ce-axi-clk", - "nss-nssnoc-ce-apb-clk", - "nss-nssnoc-ahb-clk", - "nss-core-clk", "nss-ahb-clk", - "nss-axi-clk", "nss-mpt-clk", - "nss-nc-axi-clk"; - qcom,id = <0>; - qcom,num-queue = <4>; - qcom,num-irq = <10>; - qcom,num-pri = <4>; - qcom,load-addr = <0x40000000>; - qcom,low-frequency = <187200000>; - qcom,mid-frequency = <748800000>; - qcom,max-frequency = <1689600000>; - npu-supply = <&dummy_reg>; - mx-supply = <&dummy_reg>; - qcom,bridge-enabled; - qcom,ipv4-enabled; - qcom,ipv4-reasm-enabled; - qcom,ipv6-enabled; - qcom,ipv6-reasm-enabled; - qcom,wlanredirect-enabled; - qcom,tun6rd-enabled; - qcom,l2tpv2-enabled; - qcom,gre-enabled; - qcom,gre-redir-enabled; - qcom,gre-redir-mark-enabled; - qcom,map-t-enabled; - qcom,portid-enabled; - qcom,ppe-enabled; - qcom,pppoe-enabled; - qcom,pptp-enabled; - qcom,tunipip6-enabled; - qcom,shaping-enabled; - qcom,wlan-dataplane-offload-enabled; - qcom,vlan-enabled; - qcom,igs-enabled; - qcom,vxlan-enabled; - qcom,match-enabled; - qcom,mirror-enabled; - qcom,udp-st-enabled; - }; - - nss1: nss@40800000 { - compatible = "qcom,nss"; - interrupts = , - , - , - , - , - , - , - , - ; - reg = <0x39400000 0x1000>, - <0x38030000 0x30000>, - <0x0b111000 0x1000>; - reg-names = "nphys", "vphys", "qgic-phys"; - clocks = <&gcc GCC_NSS_NOC_CLK>, - <&gcc GCC_NSS_PTP_REF_CLK>, - <&gcc GCC_NSS_CSR_CLK>, <&gcc GCC_NSS_CFG_CLK>, - <&gcc GCC_NSS_IMEM_CLK>, - <&gcc GCC_NSSNOC_QOSGEN_REF_CLK>, - <&gcc GCC_MEM_NOC_NSS_AXI_CLK>, - <&gcc GCC_NSSNOC_SNOC_CLK>, - <&gcc GCC_NSSNOC_TIMEOUT_REF_CLK>, - <&gcc GCC_NSS_CE_AXI_CLK>, - <&gcc GCC_NSS_CE_APB_CLK>, - <&gcc GCC_NSSNOC_CE_AXI_CLK>, - <&gcc GCC_NSSNOC_CE_APB_CLK>, - <&gcc GCC_NSSNOC_UBI1_AHB_CLK>, - <&gcc GCC_UBI1_CORE_CLK>, - <&gcc GCC_UBI1_AHB_CLK>, - <&gcc GCC_UBI1_AXI_CLK>, - <&gcc GCC_UBI1_MPT_CLK>, - <&gcc GCC_UBI1_NC_AXI_CLK>; - clock-names = "nss-noc-clk", "nss-ptp-ref-clk", - "nss-csr-clk", "nss-cfg-clk", - "nss-imem-clk", - "nss-nssnoc-qosgen-ref-clk", - "nss-mem-noc-nss-axi-clk", - "nss-nssnoc-snoc-clk", - "nss-nssnoc-timeout-ref-clk", - "nss-ce-axi-clk", "nss-ce-apb-clk", - "nss-nssnoc-ce-axi-clk", - "nss-nssnoc-ce-apb-clk", - "nss-nssnoc-ahb-clk", - "nss-core-clk", "nss-ahb-clk", - "nss-axi-clk", "nss-mpt-clk", - "nss-nc-axi-clk"; - qcom,id = <1>; - qcom,num-queue = <4>; - qcom,num-irq = <9>; - qcom,num-pri = <4>; - qcom,load-addr = <0x40800000>; - qcom,capwap-enabled; - qcom,dtls-enabled; - qcom,tls-enabled; - qcom,crypto-enabled; - qcom,ipsec-enabled; - qcom,qvpn-enabled; - qcom,pvxlan-enabled; - qcom,clmap-enabled; - qcom,rmnet_rx-enabled; - }; - - nss_crypto: qcom,nss_crypto { - compatible = "qcom,nss-crypto"; - #address-cells = <1>; - #size-cells = <1>; - qcom,max-contexts = <64>; - qcom,max-context-size = <32>; - ranges; - - eip197_node { - compatible = "qcom,eip197"; - reg-names = "crypto_pbase"; - reg = <0x39800000 0x7ffff>; - clocks = <&gcc GCC_NSS_CRYPTO_CLK>, - <&gcc GCC_NSSNOC_CRYPTO_CLK>, - <&gcc GCC_CRYPTO_PPE_CLK>; - clock-names = "crypto_clk", - "crypto_nocclk", - "crypto_ppeclk"; - clock-frequency = /bits/ 64 <600000000 600000000 300000000>; - qcom,dma-mask = <0xff>; - qcom,transform-enabled; - qcom,aes128-cbc; - qcom,aes192-cbc; - qcom,aes256-cbc; - qcom,aes128-ctr; - qcom,aes192-ctr; - qcom,aes256-ctr; - qcom,aes128-ecb; - qcom,aes192-ecb; - qcom,aes256-ecb; - qcom,3des-cbc; - qcom,md5-hash; - qcom,sha160-hash; - qcom,sha224-hash; - qcom,sha384-hash; - qcom,sha512-hash; - qcom,sha256-hash; - qcom,md5-hmac; - qcom,sha160-hmac; - qcom,sha224-hmac; - qcom,sha256-hmac; - qcom,sha384-hmac; - qcom,sha512-hmac; - qcom,aes128-gcm-gmac; - qcom,aes192-gcm-gmac; - qcom,aes256-gcm-gmac; - qcom,aes128-cbc-md5-hmac; - qcom,aes128-cbc-sha160-hmac; - qcom,aes192-cbc-md5-hmac; - qcom,aes192-cbc-sha160-hmac; - qcom,aes256-cbc-md5-hmac; - qcom,aes256-cbc-sha160-hmac; - qcom,aes128-ctr-sha160-hmac; - qcom,aes192-ctr-sha160-hmac; - qcom,aes256-ctr-sha160-hmac; - qcom,aes128-ctr-md5-hmac; - qcom,aes192-ctr-md5-hmac; - qcom,aes256-ctr-md5-hmac; - qcom,3des-cbc-md5-hmac; - qcom,3des-cbc-sha160-hmac; - qcom,aes128-cbc-sha256-hmac; - qcom,aes192-cbc-sha256-hmac; - qcom,aes256-cbc-sha256-hmac; - qcom,aes128-ctr-sha256-hmac; - qcom,aes192-ctr-sha256-hmac; - qcom,aes256-ctr-sha256-hmac; - qcom,3des-cbc-sha256-hmac; - qcom,aes128-cbc-sha384-hmac; - qcom,aes192-cbc-sha384-hmac; - qcom,aes256-cbc-sha384-hmac; - qcom,aes128-ctr-sha384-hmac; - qcom,aes192-ctr-sha384-hmac; - qcom,aes256-ctr-sha384-hmac; - qcom,aes128-cbc-sha512-hmac; - qcom,aes192-cbc-sha512-hmac; - qcom,aes256-cbc-sha512-hmac; - qcom,aes128-ctr-sha512-hmac; - qcom,aes192-ctr-sha512-hmac; - qcom,aes256-ctr-sha512-hmac; - - engine0 { - reg_offset = <0x80000>; - qcom,ifpp-enabled; - qcom,ipue-enabled; - qcom,ofpp-enabled; - qcom,opue-enabled; - }; - }; - }; -}; diff --git a/target/linux/ipq807x/files-5.15/arch/arm64/boot/dts/qcom/ipq8074-ess.dtsi b/target/linux/ipq807x/files-5.15/arch/arm64/boot/dts/qcom/ipq8074-ess.dtsi deleted file mode 100644 index 7fb30dbdd..000000000 --- a/target/linux/ipq807x/files-5.15/arch/arm64/boot/dts/qcom/ipq8074-ess.dtsi +++ /dev/null @@ -1,170 +0,0 @@ -// 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-ipq807x"; - reg = <0x3a000000 0x1000000>; - switch_access_mode = "local bus"; - switch_cpu_bmp = <0x1>; /* cpu port bitmap */ - switch_inner_bmp = <0x80>; /*inner port bitmap*/ - 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_UNIPHY2_AHB_CLK>, - <&gcc GCC_UNIPHY2_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_PORT6_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_NSS_PPE_BTQ_CLK>, - <&gcc GCC_MDIO_AHB_CLK>, - <&gcc GCC_NSS_NOC_CLK>, - <&gcc GCC_NSSNOC_SNOC_CLK>, - <&gcc GCC_MEM_NOC_NSS_AXI_CLK>, - <&gcc GCC_NSS_CRYPTO_CLK>, - <&gcc GCC_NSS_IMEM_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_NSS_PORT6_RX_CLK>, - <&gcc GCC_NSS_PORT6_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 GCC_UNIPHY2_PORT6_RX_CLK>, - <&gcc GCC_UNIPHY2_PORT6_TX_CLK>, - <&gcc NSS_PORT5_RX_CLK_SRC>, - <&gcc NSS_PORT5_TX_CLK_SRC>; - clock-names = "cmn_ahb_clk", "cmn_sys_clk", - "uniphy0_ahb_clk", "uniphy0_sys_clk", - "uniphy1_ahb_clk", "uniphy1_sys_clk", - "uniphy2_ahb_clk", "uniphy2_sys_clk", - "port1_mac_clk", "port2_mac_clk", - "port3_mac_clk", "port4_mac_clk", - "port5_mac_clk", "port6_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", "nss_ppe_btq_clk", - "gcc_mdio_ahb_clk", "gcc_nss_noc_clk", - "gcc_nssnoc_snoc_clk", - "gcc_mem_noc_nss_axi_clk", - "gcc_nss_crypto_clk", - "gcc_nss_imem_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", - "nss_port6_rx_clk", "nss_port6_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", - "uniphy2_port6_rx_clk", - "uniphy2_port6_tx_clk", - "nss_port5_rx_clk_src", - "nss_port5_tx_clk_src"; - 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_UNIPHY2_SOFT_RESET>, - <&gcc GCC_UNIPHY2_XPCS_RESET>, - <&gcc GCC_NSSPORT1_RESET>, - <&gcc GCC_NSSPORT2_RESET>, - <&gcc GCC_NSSPORT3_RESET>, - <&gcc GCC_NSSPORT4_RESET>, - <&gcc GCC_NSSPORT5_RESET>, - <&gcc GCC_NSSPORT6_RESET>; - reset-names = "ppe_rst", "uniphy0_soft_rst", - "uniphy0_xpcs_rst", "uniphy1_soft_rst", - "uniphy1_xpcs_rst", "uniphy2_soft_rst", - "uniphy2_xpcs_rst", "nss_port1_rst", - "nss_port2_rst", "nss_port3_rst", - "nss_port4_rst", "nss_port5_rst", - "nss_port6_rst"; - mdio-bus = <&mdio>; - status = "disabled"; - }; - - ess-uniphy@7a00000 { - compatible = "qcom,ess-uniphy"; - reg = <0x7a00000 0x30000>; - uniphy_access_mode = "local bus"; - }; - - edma: edma@3ab00000 { - compatible = "qcom,edma"; - reg = <0x3ab00000 0x76900>; - reg-names = "edma-reg-base"; - qcom,txdesc-ring-start = <23>; - qcom,txdesc-rings = <1>; - qcom,txcmpl-ring-start = <7>; - 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"; - }; -}; diff --git a/target/linux/ipq807x/files-5.15/arch/arm64/boot/dts/qcom/ipq8078-xtr10890.dts b/target/linux/ipq807x/files-5.15/arch/arm64/boot/dts/qcom/ipq8078-xtr10890.dts deleted file mode 100644 index 5e9816f5d..000000000 --- a/target/linux/ipq807x/files-5.15/arch/arm64/boot/dts/qcom/ipq8078-xtr10890.dts +++ /dev/null @@ -1,543 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later OR MIT -/* Copyright (c) 2022, Robert Marko */ - -/dts-v1/; - -#include "ipq8074.dtsi" -#include "ipq8074-hk-cpu.dtsi" -#include "ipq8074-ess.dtsi" -#include -#include -#include - -/ { - model = "TP-LINK XTR10890"; - compatible = "tplink,xtr10890", "qcom,ipq8074"; - - aliases { - led-boot = &led_system_red; - led-failsafe = &led_system_red; - led-running = &led_system_blue; - led-upgrade = &led_system_red; - serial0 = &blsp1_uart5; - /* Aliases as required by u-boot to patch MAC addresses */ - ethernet0 = &dp1; - ethernet1 = &dp2; - ethernet2 = &dp3; - ethernet3 = &dp4; - ethernet4 = &dp5; - label-mac-device = &dp1; - }; - - chosen { - stdout-path = "serial0:115200n8"; - bootargs-append = " root=/dev/ubiblock0_1"; - }; - - keys { - compatible = "gpio-keys"; - - reset { - label = "reset"; - gpios = <&tlmm 34 GPIO_ACTIVE_LOW>; - linux,code = ; - }; - - wps { - label = "wps"; - gpios = <&tlmm 63 GPIO_ACTIVE_LOW>; - linux,code = ; - }; - }; - - leds { - compatible = "gpio-leds"; - - led_system_blue: system-blue { - label = "blue:system"; - gpios = <&tlmm 26 GPIO_ACTIVE_HIGH>; - color = ; - }; - - led_system_red: system-red { - label = "yellow:system"; - gpios = <&tlmm 25 GPIO_ACTIVE_HIGH>; - color = ; - }; - }; -}; - -&tlmm { - mdio_pins: mdio-pins { - mdc { - pins = "gpio68"; - function = "mdc"; - drive-strength = <8>; - bias-pull-up; - }; - - mdio { - pins = "gpio69"; - function = "mdio"; - drive-strength = <8>; - bias-pull-up; - }; - }; -}; - -&blsp1_uart5 { - status = "okay"; -}; - -&prng { - status = "okay"; -}; - -&cryptobam { - status = "okay"; -}; - -&crypto { - status = "okay"; -}; - -&qpic_bam { - status = "okay"; -}; - -&qpic_nand { - status = "okay"; - - nand@0 { - reg = <0>; - nand-ecc-strength = <8>; - nand-ecc-step-size = <512>; - nand-bus-width = <8>; - - partitions { - compatible = "qcom,smem-part"; - }; - }; -}; - -&qusb_phy_0 { - status = "okay"; -}; - -&ssphy_0 { - status = "okay"; -}; - -&usb_0 { - status = "okay"; -}; - -&mdio { - status = "okay"; - - pinctrl-0 = <&mdio_pins>; - pinctrl-names = "default"; - reset-gpios = <&tlmm 37 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>; - }; - - qca8081: ethernet-phy@28 { - compatible = "ethernet-phy-id004d.d101"; - reg = <28>; - reset-gpios = <&tlmm 44 GPIO_ACTIVE_LOW>; - }; -}; - -&switch { - status = "okay"; - - switch_cpu_bmp = <0x1>; /* cpu port bitmap */ - switch_lan_bmp = <0x3e>; /* lan port bitmap */ - switch_wan_bmp = <0x40>; /* wan port bitmap */ - switch_mac_mode = <0xb>; /* mac mode for uniphy instance0*/ - switch_mac_mode1 = <0xff>; /* mac mode for uniphy instance1*/ - switch_mac_mode2 = <0xc>; /* mac mode for uniphy instance2*/ - bm_tick_mode = <0>; /* bm tick mode */ - tm_tick_mode = <0>; /* tm tick mode */ - - 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@5 { - port_id = <6>; - phy_address = <28>; - port_mac_sel = "QGMAC_PORT"; - }; - }; - - 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>; - }; - }; - }; - }; -}; - -&edma { - status = "okay"; -}; - -&soc { - dp1: dp1 { - device_type = "network"; - compatible = "qcom,nss-dp"; - qcom,id = <6>; - reg = <0x3a007000 0x3fff>; - qcom,mactype = <0>; - local-mac-address = [000000000000]; - phy-handle = <&qca8081>; - phy-mode = "sgmii"; - }; - - dp2: dp2 { - device_type = "network"; - compatible = "qcom,nss-dp"; - qcom,id = <4>; - reg = <0x3a001600 0x200>; - qcom,mactype = <0>; - local-mac-address = [000000000000]; - phy-handle = <&qca8075_3>; - phy-mode = "sgmii"; - }; - - dp3: dp3 { - device_type = "network"; - compatible = "qcom,nss-dp"; - qcom,id = <3>; - reg = <0x3a001400 0x200>; - qcom,mactype = <0>; - local-mac-address = [000000000000]; - phy-handle = <&qca8075_2>; - phy-mode = "sgmii"; - }; - - dp4: dp4 { - device_type = "network"; - compatible = "qcom,nss-dp"; - qcom,id = <2>; - reg = <0x3a001200 0x200>; - qcom,mactype = <0>; - local-mac-address = [000000000000]; - phy-handle = <&qca8075_1>; - phy-mode = "sgmii"; - }; - - dp5: dp5 { - device_type = "network"; - compatible = "qcom,nss-dp"; - qcom,id = <1>; - reg = <0x3a001000 0x200>; - qcom,mactype = <1>; - local-mac-address = [000000000000]; - phy-handle = <&qca8075_0>; - phy-mode = "sgmii"; - }; -}; - -&wifi { - status = "okay"; - qcom,ath11k-calibration-variant = "TP-LINK-XTR10890"; -}; diff --git a/target/linux/ipq807x/files-5.15/drivers/power/qcom/Kconfig b/target/linux/ipq807x/files-5.15/drivers/power/qcom/Kconfig deleted file mode 100644 index 01993a617..000000000 --- a/target/linux/ipq807x/files-5.15/drivers/power/qcom/Kconfig +++ /dev/null @@ -1,7 +0,0 @@ -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. diff --git a/target/linux/ipq807x/files-5.15/drivers/power/qcom/Makefile b/target/linux/ipq807x/files-5.15/drivers/power/qcom/Makefile deleted file mode 100644 index 43a288e62..000000000 --- a/target/linux/ipq807x/files-5.15/drivers/power/qcom/Makefile +++ /dev/null @@ -1 +0,0 @@ -obj-$(CONFIG_QCOM_APM) += apm.o diff --git a/target/linux/ipq807x/files-5.15/drivers/power/qcom/apm.c b/target/linux/ipq807x/files-5.15/drivers/power/qcom/apm.c deleted file mode 100644 index bd93358e3..000000000 --- a/target/linux/ipq807x/files-5.15/drivers/power/qcom/apm.c +++ /dev/null @@ -1,944 +0,0 @@ -/* - * 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"); diff --git a/target/linux/ipq807x/files-5.15/drivers/regulator/cpr3-npu-regulator.c b/target/linux/ipq807x/files-5.15/drivers/regulator/cpr3-npu-regulator.c deleted file mode 100644 index e808073c0..000000000 --- a/target/linux/ipq807x/files-5.15/drivers/regulator/cpr3-npu-regulator.c +++ /dev/null @@ -1,695 +0,0 @@ -/* - * 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"); diff --git a/target/linux/ipq807x/files-5.15/drivers/regulator/cpr3-regulator.c b/target/linux/ipq807x/files-5.15/drivers/regulator/cpr3-regulator.c deleted file mode 100644 index d5d8a1a0b..000000000 --- a/target/linux/ipq807x/files-5.15/drivers/regulator/cpr3-regulator.c +++ /dev/null @@ -1,5112 +0,0 @@ -/* - * 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; -} diff --git a/target/linux/ipq807x/files-5.15/drivers/regulator/cpr3-regulator.h b/target/linux/ipq807x/files-5.15/drivers/regulator/cpr3-regulator.h deleted file mode 100644 index 7c69c4630..000000000 --- a/target/linux/ipq807x/files-5.15/drivers/regulator/cpr3-regulator.h +++ /dev/null @@ -1,1211 +0,0 @@ -/* - * 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__ */ diff --git a/target/linux/ipq807x/files-5.15/drivers/regulator/cpr3-util.c b/target/linux/ipq807x/files-5.15/drivers/regulator/cpr3-util.c deleted file mode 100644 index 45493af71..000000000 --- a/target/linux/ipq807x/files-5.15/drivers/regulator/cpr3-util.c +++ /dev/null @@ -1,2750 +0,0 @@ -/* - * 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; -} diff --git a/target/linux/ipq807x/files-5.15/drivers/regulator/cpr4-apss-regulator.c b/target/linux/ipq807x/files-5.15/drivers/regulator/cpr4-apss-regulator.c deleted file mode 100644 index 114e2acb2..000000000 --- a/target/linux/ipq807x/files-5.15/drivers/regulator/cpr4-apss-regulator.c +++ /dev/null @@ -1,1819 +0,0 @@ -/* - * 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); diff --git a/target/linux/ipq807x/files-5.15/include/linux/power/qcom/apm.h b/target/linux/ipq807x/files-5.15/include/linux/power/qcom/apm.h deleted file mode 100644 index 432683578..000000000 --- a/target/linux/ipq807x/files-5.15/include/linux/power/qcom/apm.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * 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/ipq807x/files-5.15/include/soc/qcom/socinfo.h b/target/linux/ipq807x/files-5.15/include/soc/qcom/socinfo.h deleted file mode 100644 index db4344616..000000000 --- a/target/linux/ipq807x/files-5.15/include/soc/qcom/socinfo.h +++ /dev/null @@ -1,463 +0,0 @@ -/* 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/ipq807x/generic/target.mk b/target/linux/ipq807x/generic/target.mk deleted file mode 100644 index f5cb1fb19..000000000 --- a/target/linux/ipq807x/generic/target.mk +++ /dev/null @@ -1 +0,0 @@ -BOARDNAME:=Generic diff --git a/target/linux/ipq807x/image/generic.mk b/target/linux/ipq807x/image/generic.mk deleted file mode 100644 index f4b3b26f0..000000000 --- a/target/linux/ipq807x/image/generic.mk +++ /dev/null @@ -1,111 +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/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/qnap_301w - $(call Device/FitImage) - DEVICE_VENDOR := QNAP - DEVICE_MODEL := 301w - DEVICE_DTS_CONFIG := config@hk01 - KERNEL_SIZE := 16384k - BLOCKSIZE := 512k - SOC := ipq8072 - IMAGES += factory.bin sysupgrade.bin - IMAGE/factory.bin := append-rootfs | pad-rootfs | pad-to 64k - IMAGE/sysupgrade.bin/squashfs := append-rootfs | pad-to 64k | sysupgrade-tar rootfs=$$$$@ | append-metadata - DEVICE_PACKAGES := ipq-wifi-qnap_301w e2fsprogs kmod-fs-ext4 losetup -endef -TARGET_DEVICES += qnap_301w - -define Device/redmi_ax6 - $(call Device/xiaomi_ax3600) - DEVICE_VENDOR := Redmi - DEVICE_MODEL := AX6 - DEVICE_PACKAGES := ipq-wifi-redmi_ax6 -endef -TARGET_DEVICES += redmi_ax6 - -define Device/tplink_xtr10890 - $(call Device/FitImage) - $(call Device/UbiFit) - DEVICE_VENDOR := TPLINK - DEVICE_MODEL := XTR10890 - BLOCKSIZE := 128k - PAGESIZE := 2048 - DEVICE_DTS_CONFIG := config@hk01.c6 - SOC := ipq8078 - DEVICE_PACKAGES := ipq-wifi-tplink_xtr10890 uboot-envtools -endef -TARGET_DEVICES += tplink_xtr10890 - -define Device/xiaomi_ax3600 - $(call Device/FitImage) - $(call Device/UbiFit) - DEVICE_VENDOR := Xiaomi - DEVICE_MODEL := AX3600 - BLOCKSIZE := 128k - PAGESIZE := 2048 - DEVICE_DTS_CONFIG := config@ac04 - SOC := ipq8071 - DEVICE_PACKAGES := ipq-wifi-xiaomi_ax3600 kmod-ath10k-ct-smallbuffers ath10k-firmware-qca9887-ct -endef -TARGET_DEVICES += xiaomi_ax3600 - -define Device/xiaomi_ax9000 - $(call Device/FitImage) - $(call Device/UbiFit) - DEVICE_VENDOR := Xiaomi - DEVICE_MODEL := AX9000 - BLOCKSIZE := 128k - PAGESIZE := 2048 - DEVICE_DTS_CONFIG := config@hk14 - SOC := ipq8072 - DEVICE_PACKAGES := ipq-wifi-xiaomi_ax9000 kmod-ath11k-pci ath11k-firmware-qcn9074 \ - kmod-ath10k-ct ath10k-firmware-qca9887-ct -endef -TARGET_DEVICES += xiaomi_ax9000 - -define Device/zte_mf269 - $(call Device/FitImage) - $(call Device/UbiFit) - DEVICE_VENDOR := ZTE - DEVICE_MODEL := MF269 - BLOCKSIZE := 128k - PAGESIZE := 2048 - DEVICE_DTS_CONFIG := config@ac04 - SOC := ipq8071 - DEVICE_PACKAGES := ipq-wifi-zte_mf269 uboot-envtools -endef -TARGET_DEVICES += zte_mf269 - -define Device/zyxel_nbg7815 - $(call Device/FitImage) - DEVICE_VENDOR := ZYXEL - DEVICE_MODEL := NBG7815 - DEVICE_TITLE := Zyxel Armor G5 (NBG7815) - DEVICE_DTS_CONFIG := config@nbg7815 - BLOCKSIZE := 128k - PAGESIZE := 2048 - SOC := ipq8074 - IMAGES += factory.bin sysupgrade.bin - IMAGE/factory.bin := append-rootfs | pad-rootfs | pad-to 64k - IMAGE/sysupgrade.bin/squashfs := append-rootfs | pad-to 64k | sysupgrade-tar rootfs=$$$$@ | append-metadata - DEVICE_PACKAGES := ipq-wifi-zyxel_nbg7815 kmod-ath11k-pci e2fsprogs kmod-fs-ext4 losetup kmod-hwmon-tmp103 -endef -TARGET_DEVICES += zyxel_nbg7815 - diff --git a/target/linux/ipq807x/patches-5.10/001-v5.11-remoteproc-sysmon-Expose-the-shutdown-result.patch b/target/linux/ipq807x/patches-5.10/001-v5.11-remoteproc-sysmon-Expose-the-shutdown-result.patch deleted file mode 100644 index f2d8211d5..000000000 --- a/target/linux/ipq807x/patches-5.10/001-v5.11-remoteproc-sysmon-Expose-the-shutdown-result.patch +++ /dev/null @@ -1,222 +0,0 @@ -From c47b1e60f043925ecce585f8c5340c049deda25e Mon Sep 17 00:00:00 2001 -From: Bjorn Andersson -Date: Sat, 21 Nov 2020 21:41:33 -0800 -Subject: [PATCH] remoteproc: sysmon: Expose the shutdown result - -A graceful shutdown of the Qualcomm remote processors where -traditionally performed by invoking a shared memory state signal and -waiting for the associated ack. - -This was later superseded by the "sysmon" mechanism, where some form of -shared memory bus is used to send a "graceful shutdown request" message -and one of more signals comes back to indicate its success. - -But when this newer mechanism is in effect the firmware is shut down by -the time the older mechanism, implemented in the remoteproc drivers, -attempts to perform a graceful shutdown - and as such it will never -receive an ack back. - -This patch therefor track the success of the latest shutdown attempt in -sysmon and exposes a new function in the API that the remoteproc driver -can use to query the success and the necessity of invoking the older -mechanism. - -Tested-by: Steev Klimaszewski -Reviewed-by: Rishabh Bhatnagar -Link: https://lore.kernel.org/r/20201122054135.802935-3-bjorn.andersson@linaro.org -Signed-off-by: Bjorn Andersson ---- - drivers/remoteproc/qcom_common.h | 6 +++ - drivers/remoteproc/qcom_sysmon.c | 82 ++++++++++++++++++++++++-------- - 2 files changed, 69 insertions(+), 19 deletions(-) - ---- a/drivers/remoteproc/qcom_common.h -+++ b/drivers/remoteproc/qcom_common.h -@@ -51,6 +51,7 @@ struct qcom_sysmon *qcom_add_sysmon_subd - const char *name, - int ssctl_instance); - void qcom_remove_sysmon_subdev(struct qcom_sysmon *sysmon); -+bool qcom_sysmon_shutdown_acked(struct qcom_sysmon *sysmon); - #else - static inline struct qcom_sysmon *qcom_add_sysmon_subdev(struct rproc *rproc, - const char *name, -@@ -62,6 +63,11 @@ static inline struct qcom_sysmon *qcom_a - static inline void qcom_remove_sysmon_subdev(struct qcom_sysmon *sysmon) - { - } -+ -+static inline bool qcom_sysmon_shutdown_acked(struct qcom_sysmon *sysmon) -+{ -+ return false; -+} - #endif - - #endif ---- a/drivers/remoteproc/qcom_sysmon.c -+++ b/drivers/remoteproc/qcom_sysmon.c -@@ -45,6 +45,7 @@ struct qcom_sysmon { - struct mutex lock; - - bool ssr_ack; -+ bool shutdown_acked; - - struct qmi_handle qmi; - struct sockaddr_qrtr ssctl; -@@ -116,10 +117,13 @@ out_unlock: - /** - * sysmon_request_shutdown() - request graceful shutdown of remote - * @sysmon: sysmon context -+ * -+ * Return: boolean indicator of the remote processor acking the request - */ --static void sysmon_request_shutdown(struct qcom_sysmon *sysmon) -+static bool sysmon_request_shutdown(struct qcom_sysmon *sysmon) - { - char *req = "ssr:shutdown"; -+ bool acked = false; - int ret; - - mutex_lock(&sysmon->lock); -@@ -142,9 +146,13 @@ static void sysmon_request_shutdown(stru - if (!sysmon->ssr_ack) - dev_err(sysmon->dev, - "unexpected response to sysmon shutdown request\n"); -+ else -+ acked = true; - - out_unlock: - mutex_unlock(&sysmon->lock); -+ -+ return acked; - } - - static int sysmon_callback(struct rpmsg_device *rpdev, void *data, int count, -@@ -298,14 +306,33 @@ static struct qmi_msg_handler qmi_indica - {} - }; - -+static bool ssctl_request_shutdown_wait(struct qcom_sysmon *sysmon) -+{ -+ int ret; -+ -+ ret = wait_for_completion_timeout(&sysmon->shutdown_comp, 10 * HZ); -+ if (ret) -+ return true; -+ -+ ret = try_wait_for_completion(&sysmon->ind_comp); -+ if (ret) -+ return true; -+ -+ dev_err(sysmon->dev, "timeout waiting for shutdown ack\n"); -+ return false; -+} -+ - /** - * ssctl_request_shutdown() - request shutdown via SSCTL QMI service - * @sysmon: sysmon context -+ * -+ * Return: boolean indicator of the remote processor acking the request - */ --static void ssctl_request_shutdown(struct qcom_sysmon *sysmon) -+static bool ssctl_request_shutdown(struct qcom_sysmon *sysmon) - { - struct ssctl_shutdown_resp resp; - struct qmi_txn txn; -+ bool acked = false; - int ret; - - reinit_completion(&sysmon->ind_comp); -@@ -313,7 +340,7 @@ static void ssctl_request_shutdown(struc - ret = qmi_txn_init(&sysmon->qmi, &txn, ssctl_shutdown_resp_ei, &resp); - if (ret < 0) { - dev_err(sysmon->dev, "failed to allocate QMI txn\n"); -- return; -+ return false; - } - - ret = qmi_send_request(&sysmon->qmi, &sysmon->ssctl, &txn, -@@ -321,27 +348,23 @@ static void ssctl_request_shutdown(struc - if (ret < 0) { - dev_err(sysmon->dev, "failed to send shutdown request\n"); - qmi_txn_cancel(&txn); -- return; -+ return false; - } - - ret = qmi_txn_wait(&txn, 5 * HZ); -- if (ret < 0) -+ if (ret < 0) { - dev_err(sysmon->dev, "failed receiving QMI response\n"); -- else if (resp.resp.result) -+ } else if (resp.resp.result) { - dev_err(sysmon->dev, "shutdown request failed\n"); -- else -+ } else { - dev_dbg(sysmon->dev, "shutdown request completed\n"); -- -- if (sysmon->shutdown_irq > 0) { -- ret = wait_for_completion_timeout(&sysmon->shutdown_comp, -- 10 * HZ); -- if (!ret) { -- ret = try_wait_for_completion(&sysmon->ind_comp); -- if (!ret) -- dev_err(sysmon->dev, -- "timeout waiting for shutdown ack\n"); -- } -+ acked = true; - } -+ -+ if (sysmon->shutdown_irq > 0) -+ return ssctl_request_shutdown_wait(sysmon); -+ -+ return acked; - } - - /** -@@ -514,6 +537,9 @@ static void sysmon_stop(struct rproc_sub - .subsys_name = sysmon->name, - .ssr_event = SSCTL_SSR_EVENT_BEFORE_SHUTDOWN - }; -+ bool acked; -+ -+ sysmon->shutdown_acked = false; - - mutex_lock(&sysmon->state_lock); - sysmon->state = SSCTL_SSR_EVENT_BEFORE_SHUTDOWN; -@@ -530,9 +556,11 @@ static void sysmon_stop(struct rproc_sub - } - - if (sysmon->ssctl_version) -- ssctl_request_shutdown(sysmon); -+ acked = ssctl_request_shutdown(sysmon); - else if (sysmon->ept) -- sysmon_request_shutdown(sysmon); -+ acked = sysmon_request_shutdown(sysmon); -+ -+ sysmon->shutdown_acked = acked; - } - - static void sysmon_unprepare(struct rproc_subdev *subdev) -@@ -695,6 +723,22 @@ void qcom_remove_sysmon_subdev(struct qc - EXPORT_SYMBOL_GPL(qcom_remove_sysmon_subdev); - - /** -+ * qcom_sysmon_shutdown_acked() - query the success of the last shutdown -+ * @sysmon: sysmon context -+ * -+ * When sysmon is used to request a graceful shutdown of the remote processor -+ * this can be used by the remoteproc driver to query the success, in order to -+ * know if it should fall back to other means of requesting a shutdown. -+ * -+ * Return: boolean indicator of the success of the last shutdown request -+ */ -+bool qcom_sysmon_shutdown_acked(struct qcom_sysmon *sysmon) -+{ -+ return sysmon && sysmon->shutdown_acked; -+} -+EXPORT_SYMBOL_GPL(qcom_sysmon_shutdown_acked); -+ -+/** - * sysmon_probe() - probe sys_mon channel - * @rpdev: rpmsg device handle - * diff --git a/target/linux/ipq807x/patches-5.10/002-v5.11-remoteproc-qcom-q6v5-Query-sysmon-before-graceful-sh.patch b/target/linux/ipq807x/patches-5.10/002-v5.11-remoteproc-qcom-q6v5-Query-sysmon-before-graceful-sh.patch deleted file mode 100644 index fc4108e57..000000000 --- a/target/linux/ipq807x/patches-5.10/002-v5.11-remoteproc-qcom-q6v5-Query-sysmon-before-graceful-sh.patch +++ /dev/null @@ -1,120 +0,0 @@ -From 47c815630294b6d2284fff10377d808f376de2b2 Mon Sep 17 00:00:00 2001 -From: Bjorn Andersson -Date: Sat, 21 Nov 2020 21:41:34 -0800 -Subject: [PATCH 01/16] remoteproc: qcom: q6v5: Query sysmon before graceful - shutdown - -Requesting a graceful shutdown through the shared memory state signals -will not be acked in the event that sysmon has already successfully shut -down the remote firmware. So extend the stop request API to optionally -take the remoteproc's sysmon instance and query if there's already been -a successful shutdown attempt, before doing the signal dance. - -Tested-by: Steev Klimaszewski -Reviewed-by: Rishabh Bhatnagar -Link: https://lore.kernel.org/r/20201122054135.802935-4-bjorn.andersson@linaro.org -Signed-off-by: Bjorn Andersson ---- - drivers/remoteproc/qcom_q6v5.c | 8 +++++++- - drivers/remoteproc/qcom_q6v5.h | 3 ++- - drivers/remoteproc/qcom_q6v5_adsp.c | 2 +- - drivers/remoteproc/qcom_q6v5_mss.c | 2 +- - drivers/remoteproc/qcom_q6v5_pas.c | 2 +- - drivers/remoteproc/qcom_q6v5_wcss.c | 2 +- - 6 files changed, 13 insertions(+), 6 deletions(-) - ---- a/drivers/remoteproc/qcom_q6v5.c -+++ b/drivers/remoteproc/qcom_q6v5.c -@@ -13,6 +13,7 @@ - #include - #include - #include -+#include "qcom_common.h" - #include "qcom_q6v5.h" - - #define Q6V5_PANIC_DELAY_MS 200 -@@ -146,15 +147,20 @@ static irqreturn_t q6v5_stop_interrupt(i - /** - * qcom_q6v5_request_stop() - request the remote processor to stop - * @q6v5: reference to qcom_q6v5 context -+ * @sysmon: reference to the remote's sysmon instance, or NULL - * - * Return: 0 on success, negative errno on failure - */ --int qcom_q6v5_request_stop(struct qcom_q6v5 *q6v5) -+int qcom_q6v5_request_stop(struct qcom_q6v5 *q6v5, struct qcom_sysmon *sysmon) - { - int ret; - - q6v5->running = false; - -+ /* Don't perform SMP2P dance if sysmon already shut down the remote */ -+ if (qcom_sysmon_shutdown_acked(sysmon)) -+ return 0; -+ - qcom_smem_state_update_bits(q6v5->state, - BIT(q6v5->stop_bit), BIT(q6v5->stop_bit)); - ---- a/drivers/remoteproc/qcom_q6v5.h -+++ b/drivers/remoteproc/qcom_q6v5.h -@@ -8,6 +8,7 @@ - - struct rproc; - struct qcom_smem_state; -+struct qcom_sysmon; - - struct qcom_q6v5 { - struct device *dev; -@@ -40,7 +41,7 @@ int qcom_q6v5_init(struct qcom_q6v5 *q6v - - int qcom_q6v5_prepare(struct qcom_q6v5 *q6v5); - int qcom_q6v5_unprepare(struct qcom_q6v5 *q6v5); --int qcom_q6v5_request_stop(struct qcom_q6v5 *q6v5); -+int qcom_q6v5_request_stop(struct qcom_q6v5 *q6v5, struct qcom_sysmon *sysmon); - int qcom_q6v5_wait_for_start(struct qcom_q6v5 *q6v5, int timeout); - unsigned long qcom_q6v5_panic(struct qcom_q6v5 *q6v5); - ---- a/drivers/remoteproc/qcom_q6v5_adsp.c -+++ b/drivers/remoteproc/qcom_q6v5_adsp.c -@@ -266,7 +266,7 @@ static int adsp_stop(struct rproc *rproc - int handover; - int ret; - -- ret = qcom_q6v5_request_stop(&adsp->q6v5); -+ ret = qcom_q6v5_request_stop(&adsp->q6v5, adsp->sysmon); - if (ret == -ETIMEDOUT) - dev_err(adsp->dev, "timed out on wait\n"); - ---- a/drivers/remoteproc/qcom_q6v5_mss.c -+++ b/drivers/remoteproc/qcom_q6v5_mss.c -@@ -1402,7 +1402,7 @@ static int q6v5_stop(struct rproc *rproc - struct q6v5 *qproc = (struct q6v5 *)rproc->priv; - int ret; - -- ret = qcom_q6v5_request_stop(&qproc->q6v5); -+ ret = qcom_q6v5_request_stop(&qproc->q6v5, qproc->sysmon); - if (ret == -ETIMEDOUT) - dev_err(qproc->dev, "timed out on wait\n"); - ---- a/drivers/remoteproc/qcom_q6v5_pas.c -+++ b/drivers/remoteproc/qcom_q6v5_pas.c -@@ -217,7 +217,7 @@ static int adsp_stop(struct rproc *rproc - int handover; - int ret; - -- ret = qcom_q6v5_request_stop(&adsp->q6v5); -+ ret = qcom_q6v5_request_stop(&adsp->q6v5, adsp->sysmon); - if (ret == -ETIMEDOUT) - dev_err(adsp->dev, "timed out on wait\n"); - ---- a/drivers/remoteproc/qcom_q6v5_wcss.c -+++ b/drivers/remoteproc/qcom_q6v5_wcss.c -@@ -390,7 +390,7 @@ static int q6v5_wcss_stop(struct rproc * - int ret; - - /* WCSS powerdown */ -- ret = qcom_q6v5_request_stop(&wcss->q6v5); -+ ret = qcom_q6v5_request_stop(&wcss->q6v5, NULL); - if (ret == -ETIMEDOUT) { - dev_err(wcss->dev, "timed out on wait\n"); - return ret; diff --git a/target/linux/ipq807x/patches-5.10/003-v5.13-remoteproc-qcom-wcss-populate-hardcoded-param-using-.patch b/target/linux/ipq807x/patches-5.10/003-v5.13-remoteproc-qcom-wcss-populate-hardcoded-param-using-.patch deleted file mode 100644 index b7f9bd425..000000000 --- a/target/linux/ipq807x/patches-5.10/003-v5.13-remoteproc-qcom-wcss-populate-hardcoded-param-using-.patch +++ /dev/null @@ -1,104 +0,0 @@ -From 6a83f257a5a10b24c7311475f19d58399c475476 Mon Sep 17 00:00:00 2001 -From: Govind Singh -Date: Fri, 29 Jan 2021 00:18:12 +0530 -Subject: [PATCH 02/16] remoteproc: qcom: wcss: populate hardcoded param using - driver data - -Q6 based WiFi fw loading is supported across -different targets, ex: IPQ8074/QCS404. In order to -support different fw names/pas id etc, populate -hardcoded param using driver data. - -Signed-off-by: Govind Singh -Signed-off-by: Gokul Sriram Palanisamy -Link: https://lore.kernel.org/r/1611859695-11824-2-git-send-email-gokulsri@codeaurora.org -Signed-off-by: Bjorn Andersson ---- - drivers/remoteproc/qcom_q6v5_wcss.c | 29 ++++++++++++++++++++++++----- - 1 file changed, 24 insertions(+), 5 deletions(-) - ---- a/drivers/remoteproc/qcom_q6v5_wcss.c -+++ b/drivers/remoteproc/qcom_q6v5_wcss.c -@@ -71,6 +71,11 @@ - #define TCSR_WCSS_CLK_MASK 0x1F - #define TCSR_WCSS_CLK_ENABLE 0x14 - -+struct wcss_data { -+ const char *firmware_name; -+ unsigned int crash_reason_smem; -+}; -+ - struct q6v5_wcss { - struct device *dev; - -@@ -93,6 +98,8 @@ struct q6v5_wcss { - void *mem_region; - size_t mem_size; - -+ unsigned int crash_reason_smem; -+ - struct qcom_rproc_glink glink_subdev; - struct qcom_rproc_ssr ssr_subdev; - }; -@@ -438,7 +445,7 @@ static int q6v5_wcss_load(struct rproc * - return ret; - } - --static const struct rproc_ops q6v5_wcss_ops = { -+static const struct rproc_ops q6v5_wcss_ipq8074_ops = { - .start = q6v5_wcss_start, - .stop = q6v5_wcss_stop, - .da_to_va = q6v5_wcss_da_to_va, -@@ -538,12 +545,17 @@ static int q6v5_alloc_memory_region(stru - - static int q6v5_wcss_probe(struct platform_device *pdev) - { -+ const struct wcss_data *desc; - struct q6v5_wcss *wcss; - struct rproc *rproc; - int ret; - -- rproc = rproc_alloc(&pdev->dev, pdev->name, &q6v5_wcss_ops, -- "IPQ8074/q6_fw.mdt", sizeof(*wcss)); -+ desc = device_get_match_data(&pdev->dev); -+ if (!desc) -+ return -EINVAL; -+ -+ rproc = rproc_alloc(&pdev->dev, pdev->name, &q6v5_wcss_ipq8074_ops, -+ desc->firmware_name, sizeof(*wcss)); - if (!rproc) { - dev_err(&pdev->dev, "failed to allocate rproc\n"); - return -ENOMEM; -@@ -551,6 +563,7 @@ static int q6v5_wcss_probe(struct platfo - - wcss = rproc->priv; - wcss->dev = &pdev->dev; -+ wcss->crash_reason_smem = desc->crash_reason_smem; - - ret = q6v5_wcss_init_mmio(wcss, pdev); - if (ret) -@@ -564,7 +577,8 @@ static int q6v5_wcss_probe(struct platfo - if (ret) - goto free_rproc; - -- ret = qcom_q6v5_init(&wcss->q6v5, pdev, rproc, WCSS_CRASH_REASON, NULL); -+ ret = qcom_q6v5_init(&wcss->q6v5, pdev, rproc, desc->crash_reason_smem, -+ NULL); - if (ret) - goto free_rproc; - -@@ -595,8 +609,13 @@ static int q6v5_wcss_remove(struct platf - return 0; - } - -+static const struct wcss_data wcss_ipq8074_res_init = { -+ .firmware_name = "IPQ8074/q6_fw.mdt", -+ .crash_reason_smem = WCSS_CRASH_REASON, -+}; -+ - static const struct of_device_id q6v5_wcss_of_match[] = { -- { .compatible = "qcom,ipq8074-wcss-pil" }, -+ { .compatible = "qcom,ipq8074-wcss-pil", .data = &wcss_ipq8074_res_init }, - { }, - }; - MODULE_DEVICE_TABLE(of, q6v5_wcss_of_match); diff --git a/target/linux/ipq807x/patches-5.10/004-v5.13-remoteproc-qcom-wcss-Add-non-pas-wcss-Q6-support-for.patch b/target/linux/ipq807x/patches-5.10/004-v5.13-remoteproc-qcom-wcss-Add-non-pas-wcss-Q6-support-for.patch deleted file mode 100644 index 00b9cec66..000000000 --- a/target/linux/ipq807x/patches-5.10/004-v5.13-remoteproc-qcom-wcss-Add-non-pas-wcss-Q6-support-for.patch +++ /dev/null @@ -1,764 +0,0 @@ -From 155940892f022482c7e7a33c917fd766519d031b Mon Sep 17 00:00:00 2001 -From: Govind Singh -Date: Fri, 29 Jan 2021 00:18:14 +0530 -Subject: [PATCH 03/16] remoteproc: qcom: wcss: Add non pas wcss Q6 support for - QCS404 - -Add non PAS WCSS remoteproc driver support for QCS404 SOC. -Add WCSS q6 bootup and shutdown sequence handled from -Application Processor SubSystem(APSS). - -Signed-off-by: Govind Singh -Signed-off-by: Gokul Sriram Palanisamy -Link: https://lore.kernel.org/r/1611859695-11824-4-git-send-email-gokulsri@codeaurora.org -Signed-off-by: Bjorn Andersson ---- - drivers/remoteproc/qcom_q6v5_wcss.c | 566 ++++++++++++++++++++++++++-- - 1 file changed, 528 insertions(+), 38 deletions(-) - ---- a/drivers/remoteproc/qcom_q6v5_wcss.c -+++ b/drivers/remoteproc/qcom_q6v5_wcss.c -@@ -4,13 +4,18 @@ - * Copyright (C) 2014 Sony Mobile Communications AB - * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. - */ -+#include -+#include -+#include - #include - #include - #include - #include -+#include - #include - #include - #include -+#include - #include - #include - #include "qcom_common.h" -@@ -24,6 +29,9 @@ - #define Q6SS_GFMUX_CTL_REG 0x020 - #define Q6SS_PWR_CTL_REG 0x030 - #define Q6SS_MEM_PWR_CTL 0x0B0 -+#define Q6SS_STRAP_ACC 0x110 -+#define Q6SS_CGC_OVERRIDE 0x034 -+#define Q6SS_BCR_REG 0x6000 - - /* AXI Halt Register Offsets */ - #define AXI_HALTREQ_REG 0x0 -@@ -37,14 +45,19 @@ - #define Q6SS_CORE_ARES BIT(1) - #define Q6SS_BUS_ARES_ENABLE BIT(2) - -+/* Q6SS_BRC_RESET */ -+#define Q6SS_BRC_BLK_ARES BIT(0) -+ - /* Q6SS_GFMUX_CTL */ - #define Q6SS_CLK_ENABLE BIT(1) -+#define Q6SS_SWITCH_CLK_SRC BIT(8) - - /* Q6SS_PWR_CTL */ - #define Q6SS_L2DATA_STBY_N BIT(18) - #define Q6SS_SLP_RET_N BIT(19) - #define Q6SS_CLAMP_IO BIT(20) - #define QDSS_BHS_ON BIT(21) -+#define QDSS_Q6_MEMORIES GENMASK(15, 0) - - /* Q6SS parameters */ - #define Q6SS_LDO_BYP BIT(25) -@@ -53,6 +66,7 @@ - #define Q6SS_CLAMP_QMC_MEM BIT(22) - #define HALT_CHECK_MAX_LOOPS 200 - #define Q6SS_XO_CBCR GENMASK(5, 3) -+#define Q6SS_SLEEP_CBCR GENMASK(5, 2) - - /* Q6SS config/status registers */ - #define TCSR_GLOBAL_CFG0 0x0 -@@ -71,9 +85,23 @@ - #define TCSR_WCSS_CLK_MASK 0x1F - #define TCSR_WCSS_CLK_ENABLE 0x14 - -+#define MAX_HALT_REG 3 -+enum { -+ WCSS_IPQ8074, -+ 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 { -@@ -87,9 +115,26 @@ struct q6v5_wcss { - u32 halt_wcss; - u32 halt_nc; - -+ struct clk *xo; -+ struct clk *ahbfabric_cbcr_clk; -+ struct clk *gcc_abhs_cbcr; -+ struct clk *gcc_axim_cbcr; -+ struct clk *lcc_csr_cbcr; -+ struct clk *ahbs_cbcr; -+ struct clk *tcm_slave_cbcr; -+ struct clk *qdsp6ss_abhm_cbcr; -+ struct clk *qdsp6ss_sleep_cbcr; -+ struct clk *qdsp6ss_axim_cbcr; -+ struct clk *qdsp6ss_xo_cbcr; -+ struct clk *qdsp6ss_core_gfmux; -+ struct clk *lcc_bcr_sleep; -+ struct regulator *cx_supply; -+ struct qcom_sysmon *sysmon; -+ - struct reset_control *wcss_aon_reset; - struct reset_control *wcss_reset; - struct reset_control *wcss_q6_reset; -+ struct reset_control *wcss_q6_bcr_reset; - - struct qcom_q6v5 q6v5; - -@@ -99,6 +144,8 @@ struct q6v5_wcss { - size_t mem_size; - - unsigned int crash_reason_smem; -+ u32 version; -+ bool requires_force_stop; - - struct qcom_rproc_glink glink_subdev; - struct qcom_rproc_ssr ssr_subdev; -@@ -244,6 +291,207 @@ wcss_reset: - return ret; - } - -+static int q6v5_wcss_qcs404_power_on(struct q6v5_wcss *wcss) -+{ -+ unsigned long val; -+ int ret, idx; -+ -+ /* Toggle the restart */ -+ reset_control_assert(wcss->wcss_reset); -+ usleep_range(200, 300); -+ reset_control_deassert(wcss->wcss_reset); -+ usleep_range(200, 300); -+ -+ /* Enable GCC_WDSP_Q6SS_AHBS_CBCR clock */ -+ ret = clk_prepare_enable(wcss->gcc_abhs_cbcr); -+ if (ret) -+ return ret; -+ -+ /* Remove reset to the WCNSS QDSP6SS */ -+ reset_control_deassert(wcss->wcss_q6_bcr_reset); -+ -+ /* Enable Q6SSTOP_AHBFABRIC_CBCR clock */ -+ ret = clk_prepare_enable(wcss->ahbfabric_cbcr_clk); -+ if (ret) -+ goto disable_gcc_abhs_cbcr_clk; -+ -+ /* Enable the LCCCSR CBC clock, Q6SSTOP_Q6SSTOP_LCC_CSR_CBCR clock */ -+ ret = clk_prepare_enable(wcss->lcc_csr_cbcr); -+ if (ret) -+ goto disable_ahbfabric_cbcr_clk; -+ -+ /* Enable the Q6AHBS CBC, Q6SSTOP_Q6SS_AHBS_CBCR clock */ -+ ret = clk_prepare_enable(wcss->ahbs_cbcr); -+ if (ret) -+ goto disable_csr_cbcr_clk; -+ -+ /* Enable the TCM slave CBC, Q6SSTOP_Q6SS_TCM_SLAVE_CBCR clock */ -+ ret = clk_prepare_enable(wcss->tcm_slave_cbcr); -+ if (ret) -+ goto disable_ahbs_cbcr_clk; -+ -+ /* Enable the Q6SS AHB master CBC, Q6SSTOP_Q6SS_AHBM_CBCR clock */ -+ ret = clk_prepare_enable(wcss->qdsp6ss_abhm_cbcr); -+ if (ret) -+ goto disable_tcm_slave_cbcr_clk; -+ -+ /* Enable the Q6SS AXI master CBC, Q6SSTOP_Q6SS_AXIM_CBCR clock */ -+ ret = clk_prepare_enable(wcss->qdsp6ss_axim_cbcr); -+ if (ret) -+ goto disable_abhm_cbcr_clk; -+ -+ /* Enable the Q6SS XO CBC */ -+ val = readl(wcss->reg_base + Q6SS_XO_CBCR); -+ val |= BIT(0); -+ writel(val, wcss->reg_base + Q6SS_XO_CBCR); -+ /* 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); -+ if (ret) { -+ dev_err(wcss->dev, -+ "xo cbcr enabling timed out (rc:%d)\n", ret); -+ return ret; -+ } -+ -+ writel(0, wcss->reg_base + Q6SS_CGC_OVERRIDE); -+ -+ /* Enable QDSP6 sleep clock clock */ -+ val = readl(wcss->reg_base + Q6SS_SLEEP_CBCR); -+ val |= BIT(0); -+ writel(val, wcss->reg_base + Q6SS_SLEEP_CBCR); -+ -+ /* Enable the Enable the Q6 AXI clock, GCC_WDSP_Q6SS_AXIM_CBCR*/ -+ ret = clk_prepare_enable(wcss->gcc_axim_cbcr); -+ if (ret) -+ goto disable_sleep_cbcr_clk; -+ -+ /* Assert resets, stop core */ -+ val = readl(wcss->reg_base + Q6SS_RESET_REG); -+ val |= Q6SS_CORE_ARES | Q6SS_BUS_ARES_ENABLE | Q6SS_STOP_CORE; -+ writel(val, wcss->reg_base + Q6SS_RESET_REG); -+ -+ /* Program the QDSP6SS PWR_CTL register */ -+ writel(0x01700000, wcss->reg_base + Q6SS_PWR_CTL_REG); -+ -+ writel(0x03700000, wcss->reg_base + Q6SS_PWR_CTL_REG); -+ -+ writel(0x03300000, wcss->reg_base + Q6SS_PWR_CTL_REG); -+ -+ writel(0x033C0000, wcss->reg_base + Q6SS_PWR_CTL_REG); -+ -+ /* -+ * Enable memories by turning on the QDSP6 memory foot/head switch, one -+ * bank at a time to avoid in-rush current -+ */ -+ for (idx = 28; idx >= 0; idx--) { -+ writel((readl(wcss->reg_base + Q6SS_MEM_PWR_CTL) | -+ (1 << idx)), wcss->reg_base + Q6SS_MEM_PWR_CTL); -+ } -+ -+ writel(0x031C0000, wcss->reg_base + Q6SS_PWR_CTL_REG); -+ writel(0x030C0000, wcss->reg_base + Q6SS_PWR_CTL_REG); -+ -+ val = readl(wcss->reg_base + Q6SS_RESET_REG); -+ val &= ~Q6SS_CORE_ARES; -+ writel(val, wcss->reg_base + Q6SS_RESET_REG); -+ -+ /* Enable the Q6 core clock at the GFM, Q6SSTOP_QDSP6SS_GFMUX_CTL */ -+ val = readl(wcss->reg_base + Q6SS_GFMUX_CTL_REG); -+ val |= Q6SS_CLK_ENABLE | Q6SS_SWITCH_CLK_SRC; -+ writel(val, wcss->reg_base + Q6SS_GFMUX_CTL_REG); -+ -+ /* Enable sleep clock branch needed for BCR circuit */ -+ ret = clk_prepare_enable(wcss->lcc_bcr_sleep); -+ if (ret) -+ goto disable_core_gfmux_clk; -+ -+ return 0; -+ -+disable_core_gfmux_clk: -+ val = readl(wcss->reg_base + Q6SS_GFMUX_CTL_REG); -+ val &= ~(Q6SS_CLK_ENABLE | Q6SS_SWITCH_CLK_SRC); -+ writel(val, wcss->reg_base + Q6SS_GFMUX_CTL_REG); -+ clk_disable_unprepare(wcss->gcc_axim_cbcr); -+disable_sleep_cbcr_clk: -+ val = readl(wcss->reg_base + Q6SS_SLEEP_CBCR); -+ val &= ~Q6SS_CLK_ENABLE; -+ writel(val, wcss->reg_base + Q6SS_SLEEP_CBCR); -+ val = readl(wcss->reg_base + Q6SS_XO_CBCR); -+ val &= ~Q6SS_CLK_ENABLE; -+ writel(val, wcss->reg_base + Q6SS_XO_CBCR); -+ clk_disable_unprepare(wcss->qdsp6ss_axim_cbcr); -+disable_abhm_cbcr_clk: -+ clk_disable_unprepare(wcss->qdsp6ss_abhm_cbcr); -+disable_tcm_slave_cbcr_clk: -+ clk_disable_unprepare(wcss->tcm_slave_cbcr); -+disable_ahbs_cbcr_clk: -+ clk_disable_unprepare(wcss->ahbs_cbcr); -+disable_csr_cbcr_clk: -+ clk_disable_unprepare(wcss->lcc_csr_cbcr); -+disable_ahbfabric_cbcr_clk: -+ clk_disable_unprepare(wcss->ahbfabric_cbcr_clk); -+disable_gcc_abhs_cbcr_clk: -+ clk_disable_unprepare(wcss->gcc_abhs_cbcr); -+ -+ return ret; -+} -+ -+static inline int q6v5_wcss_qcs404_reset(struct q6v5_wcss *wcss) -+{ -+ unsigned long val; -+ -+ writel(0x80800000, wcss->reg_base + Q6SS_STRAP_ACC); -+ -+ /* Start core execution */ -+ val = readl(wcss->reg_base + Q6SS_RESET_REG); -+ val &= ~Q6SS_STOP_CORE; -+ writel(val, wcss->reg_base + Q6SS_RESET_REG); -+ -+ return 0; -+} -+ -+static int q6v5_qcs404_wcss_start(struct rproc *rproc) -+{ -+ struct q6v5_wcss *wcss = rproc->priv; -+ int ret; -+ -+ ret = clk_prepare_enable(wcss->xo); -+ if (ret) -+ return ret; -+ -+ ret = regulator_enable(wcss->cx_supply); -+ if (ret) -+ goto disable_xo_clk; -+ -+ qcom_q6v5_prepare(&wcss->q6v5); -+ -+ ret = q6v5_wcss_qcs404_power_on(wcss); -+ if (ret) { -+ dev_err(wcss->dev, "wcss clk_enable failed\n"); -+ goto disable_cx_supply; -+ } -+ -+ writel(rproc->bootaddr >> 4, wcss->reg_base + Q6SS_RST_EVB); -+ -+ q6v5_wcss_qcs404_reset(wcss); -+ -+ ret = qcom_q6v5_wait_for_start(&wcss->q6v5, 5 * HZ); -+ if (ret == -ETIMEDOUT) { -+ dev_err(wcss->dev, "start timed out\n"); -+ goto disable_cx_supply; -+ } -+ -+ return 0; -+ -+disable_cx_supply: -+ regulator_disable(wcss->cx_supply); -+disable_xo_clk: -+ clk_disable_unprepare(wcss->xo); -+ -+ return ret; -+} -+ - static void q6v5_wcss_halt_axi_port(struct q6v5_wcss *wcss, - struct regmap *halt_map, - u32 offset) -@@ -278,6 +526,70 @@ static void q6v5_wcss_halt_axi_port(stru - regmap_write(halt_map, offset + AXI_HALTREQ_REG, 0); - } - -+static int q6v5_qcs404_wcss_shutdown(struct q6v5_wcss *wcss) -+{ -+ unsigned long val; -+ int ret; -+ -+ q6v5_wcss_halt_axi_port(wcss, wcss->halt_map, wcss->halt_wcss); -+ -+ /* assert clamps to avoid MX current inrush */ -+ val = readl(wcss->reg_base + Q6SS_PWR_CTL_REG); -+ val |= (Q6SS_CLAMP_IO | Q6SS_CLAMP_WL | Q6SS_CLAMP_QMC_MEM); -+ writel(val, wcss->reg_base + Q6SS_PWR_CTL_REG); -+ -+ /* Disable memories by turning off memory foot/headswitch */ -+ writel((readl(wcss->reg_base + Q6SS_MEM_PWR_CTL) & -+ ~QDSS_Q6_MEMORIES), -+ wcss->reg_base + Q6SS_MEM_PWR_CTL); -+ -+ /* Clear the BHS_ON bit */ -+ val = readl(wcss->reg_base + Q6SS_PWR_CTL_REG); -+ val &= ~Q6SS_BHS_ON; -+ writel(val, wcss->reg_base + Q6SS_PWR_CTL_REG); -+ -+ clk_disable_unprepare(wcss->ahbfabric_cbcr_clk); -+ clk_disable_unprepare(wcss->lcc_csr_cbcr); -+ clk_disable_unprepare(wcss->tcm_slave_cbcr); -+ clk_disable_unprepare(wcss->qdsp6ss_abhm_cbcr); -+ clk_disable_unprepare(wcss->qdsp6ss_axim_cbcr); -+ -+ val = readl(wcss->reg_base + Q6SS_SLEEP_CBCR); -+ val &= ~BIT(0); -+ writel(val, wcss->reg_base + Q6SS_SLEEP_CBCR); -+ -+ val = readl(wcss->reg_base + Q6SS_XO_CBCR); -+ val &= ~BIT(0); -+ writel(val, wcss->reg_base + Q6SS_XO_CBCR); -+ -+ clk_disable_unprepare(wcss->ahbs_cbcr); -+ clk_disable_unprepare(wcss->lcc_bcr_sleep); -+ -+ val = readl(wcss->reg_base + Q6SS_GFMUX_CTL_REG); -+ val &= ~(Q6SS_CLK_ENABLE | Q6SS_SWITCH_CLK_SRC); -+ writel(val, wcss->reg_base + Q6SS_GFMUX_CTL_REG); -+ -+ clk_disable_unprepare(wcss->gcc_abhs_cbcr); -+ -+ ret = reset_control_assert(wcss->wcss_reset); -+ if (ret) { -+ dev_err(wcss->dev, "wcss_reset failed\n"); -+ return ret; -+ } -+ usleep_range(200, 300); -+ -+ ret = reset_control_deassert(wcss->wcss_reset); -+ if (ret) { -+ dev_err(wcss->dev, "wcss_reset failed\n"); -+ return ret; -+ } -+ usleep_range(200, 300); -+ -+ clk_disable_unprepare(wcss->gcc_axim_cbcr); -+ -+ return 0; -+} -+ - static int q6v5_wcss_powerdown(struct q6v5_wcss *wcss) - { - int ret; -@@ -397,20 +709,28 @@ static int q6v5_wcss_stop(struct rproc * - int ret; - - /* WCSS powerdown */ -- ret = qcom_q6v5_request_stop(&wcss->q6v5, NULL); -- if (ret == -ETIMEDOUT) { -- dev_err(wcss->dev, "timed out on wait\n"); -- return ret; -+ if (wcss->requires_force_stop) { -+ ret = qcom_q6v5_request_stop(&wcss->q6v5, NULL); -+ if (ret == -ETIMEDOUT) { -+ dev_err(wcss->dev, "timed out on wait\n"); -+ return ret; -+ } - } - -- ret = q6v5_wcss_powerdown(wcss); -- if (ret) -- return ret; -- -- /* Q6 Power down */ -- ret = q6v5_q6_powerdown(wcss); -- if (ret) -- return ret; -+ if (wcss->version == WCSS_QCS404) { -+ ret = q6v5_qcs404_wcss_shutdown(wcss); -+ if (ret) -+ return ret; -+ } else { -+ ret = q6v5_wcss_powerdown(wcss); -+ if (ret) -+ return ret; -+ -+ /* Q6 Power down */ -+ ret = q6v5_q6_powerdown(wcss); -+ if (ret) -+ return ret; -+ } - - qcom_q6v5_unprepare(&wcss->q6v5); - -@@ -453,14 +773,26 @@ static const struct rproc_ops q6v5_wcss_ - .get_boot_addr = rproc_elf_get_boot_addr, - }; - --static int q6v5_wcss_init_reset(struct q6v5_wcss *wcss) -+static const struct rproc_ops q6v5_wcss_qcs404_ops = { -+ .start = q6v5_qcs404_wcss_start, -+ .stop = q6v5_wcss_stop, -+ .da_to_va = q6v5_wcss_da_to_va, -+ .load = q6v5_wcss_load, -+ .get_boot_addr = rproc_elf_get_boot_addr, -+ .parse_fw = qcom_register_dump_segments, -+}; -+ -+static int q6v5_wcss_init_reset(struct q6v5_wcss *wcss, -+ const struct wcss_data *desc) - { - struct device *dev = wcss->dev; - -- wcss->wcss_aon_reset = devm_reset_control_get(dev, "wcss_aon_reset"); -- if (IS_ERR(wcss->wcss_aon_reset)) { -- dev_err(wcss->dev, "unable to acquire wcss_aon_reset\n"); -- return PTR_ERR(wcss->wcss_aon_reset); -+ if (desc->aon_reset_required) { -+ wcss->wcss_aon_reset = devm_reset_control_get(dev, "wcss_aon_reset"); -+ if (IS_ERR(wcss->wcss_aon_reset)) { -+ dev_err(wcss->dev, "fail to acquire wcss_aon_reset\n"); -+ return PTR_ERR(wcss->wcss_aon_reset); -+ } - } - - wcss->wcss_reset = devm_reset_control_get(dev, "wcss_reset"); -@@ -469,10 +801,18 @@ static int q6v5_wcss_init_reset(struct q - return PTR_ERR(wcss->wcss_reset); - } - -- wcss->wcss_q6_reset = devm_reset_control_get(dev, "wcss_q6_reset"); -- if (IS_ERR(wcss->wcss_q6_reset)) { -- dev_err(wcss->dev, "unable to acquire wcss_q6_reset\n"); -- return PTR_ERR(wcss->wcss_q6_reset); -+ if (desc->wcss_q6_reset_required) { -+ wcss->wcss_q6_reset = devm_reset_control_get(dev, "wcss_q6_reset"); -+ if (IS_ERR(wcss->wcss_q6_reset)) { -+ dev_err(wcss->dev, "unable to acquire wcss_q6_reset\n"); -+ return PTR_ERR(wcss->wcss_q6_reset); -+ } -+ } -+ -+ 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; -@@ -481,35 +821,48 @@ static int q6v5_wcss_init_reset(struct q - static int q6v5_wcss_init_mmio(struct q6v5_wcss *wcss, - struct platform_device *pdev) - { -- struct of_phandle_args args; -+ unsigned int halt_reg[MAX_HALT_REG] = {0}; -+ struct device_node *syscon; - struct resource *res; - int ret; - - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "qdsp6"); -- wcss->reg_base = devm_ioremap_resource(&pdev->dev, res); -+ wcss->reg_base = devm_ioremap(&pdev->dev, res->start, -+ resource_size(res)); - if (IS_ERR(wcss->reg_base)) - return PTR_ERR(wcss->reg_base); - -- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rmb"); -- wcss->rmb_base = devm_ioremap_resource(&pdev->dev, res); -- if (IS_ERR(wcss->rmb_base)) -- return PTR_ERR(wcss->rmb_base); -+ if (wcss->version == WCSS_IPQ8074) { -+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rmb"); -+ wcss->rmb_base = devm_ioremap_resource(&pdev->dev, res); -+ if (IS_ERR(wcss->rmb_base)) -+ return PTR_ERR(wcss->rmb_base); -+ } - -- ret = of_parse_phandle_with_fixed_args(pdev->dev.of_node, -- "qcom,halt-regs", 3, 0, &args); -- if (ret < 0) { -+ syscon = of_parse_phandle(pdev->dev.of_node, -+ "qcom,halt-regs", 0); -+ if (!syscon) { - dev_err(&pdev->dev, "failed to parse qcom,halt-regs\n"); - return -EINVAL; - } - -- wcss->halt_map = syscon_node_to_regmap(args.np); -- of_node_put(args.np); -+ wcss->halt_map = syscon_node_to_regmap(syscon); -+ of_node_put(syscon); - if (IS_ERR(wcss->halt_map)) - return PTR_ERR(wcss->halt_map); - -- wcss->halt_q6 = args.args[0]; -- wcss->halt_wcss = args.args[1]; -- wcss->halt_nc = args.args[2]; -+ ret = of_property_read_variable_u32_array(pdev->dev.of_node, -+ "qcom,halt-regs", -+ halt_reg, 0, -+ MAX_HALT_REG); -+ if (ret < 0) { -+ dev_err(&pdev->dev, "failed to parse qcom,halt-regs\n"); -+ return -EINVAL; -+ } -+ -+ wcss->halt_q6 = halt_reg[0]; -+ wcss->halt_wcss = halt_reg[1]; -+ wcss->halt_nc = halt_reg[2]; - - return 0; - } -@@ -543,6 +896,107 @@ static int q6v5_alloc_memory_region(stru - return 0; - } - -+static int q6v5_wcss_init_clock(struct q6v5_wcss *wcss) -+{ -+ int ret; -+ -+ wcss->xo = devm_clk_get(wcss->dev, "xo"); -+ if (IS_ERR(wcss->xo)) { -+ ret = PTR_ERR(wcss->xo); -+ if (ret != -EPROBE_DEFER) -+ dev_err(wcss->dev, "failed to get xo clock"); -+ return ret; -+ } -+ -+ wcss->gcc_abhs_cbcr = devm_clk_get(wcss->dev, "gcc_abhs_cbcr"); -+ if (IS_ERR(wcss->gcc_abhs_cbcr)) { -+ ret = PTR_ERR(wcss->gcc_abhs_cbcr); -+ if (ret != -EPROBE_DEFER) -+ dev_err(wcss->dev, "failed to get gcc abhs clock"); -+ return PTR_ERR(wcss->gcc_abhs_cbcr); -+ } -+ -+ wcss->gcc_axim_cbcr = devm_clk_get(wcss->dev, "gcc_axim_cbcr"); -+ if (IS_ERR(wcss->gcc_axim_cbcr)) { -+ ret = PTR_ERR(wcss->gcc_axim_cbcr); -+ if (ret != -EPROBE_DEFER) -+ dev_err(wcss->dev, "failed to get gcc axim clock\n"); -+ return PTR_ERR(wcss->gcc_axim_cbcr); -+ } -+ -+ wcss->ahbfabric_cbcr_clk = devm_clk_get(wcss->dev, -+ "lcc_ahbfabric_cbc"); -+ if (IS_ERR(wcss->ahbfabric_cbcr_clk)) { -+ ret = PTR_ERR(wcss->ahbfabric_cbcr_clk); -+ if (ret != -EPROBE_DEFER) -+ dev_err(wcss->dev, "failed to get ahbfabric clock\n"); -+ return PTR_ERR(wcss->ahbfabric_cbcr_clk); -+ } -+ -+ wcss->lcc_csr_cbcr = devm_clk_get(wcss->dev, "tcsr_lcc_cbc"); -+ if (IS_ERR(wcss->lcc_csr_cbcr)) { -+ ret = PTR_ERR(wcss->lcc_csr_cbcr); -+ if (ret != -EPROBE_DEFER) -+ dev_err(wcss->dev, "failed to get csr cbcr clk\n"); -+ return PTR_ERR(wcss->lcc_csr_cbcr); -+ } -+ -+ wcss->ahbs_cbcr = devm_clk_get(wcss->dev, -+ "lcc_abhs_cbc"); -+ if (IS_ERR(wcss->ahbs_cbcr)) { -+ ret = PTR_ERR(wcss->ahbs_cbcr); -+ if (ret != -EPROBE_DEFER) -+ dev_err(wcss->dev, "failed to get ahbs_cbcr clk\n"); -+ return PTR_ERR(wcss->ahbs_cbcr); -+ } -+ -+ wcss->tcm_slave_cbcr = devm_clk_get(wcss->dev, -+ "lcc_tcm_slave_cbc"); -+ if (IS_ERR(wcss->tcm_slave_cbcr)) { -+ ret = PTR_ERR(wcss->tcm_slave_cbcr); -+ if (ret != -EPROBE_DEFER) -+ dev_err(wcss->dev, "failed to get tcm cbcr clk\n"); -+ return PTR_ERR(wcss->tcm_slave_cbcr); -+ } -+ -+ wcss->qdsp6ss_abhm_cbcr = devm_clk_get(wcss->dev, "lcc_abhm_cbc"); -+ if (IS_ERR(wcss->qdsp6ss_abhm_cbcr)) { -+ ret = PTR_ERR(wcss->qdsp6ss_abhm_cbcr); -+ if (ret != -EPROBE_DEFER) -+ dev_err(wcss->dev, "failed to get abhm cbcr clk\n"); -+ return PTR_ERR(wcss->qdsp6ss_abhm_cbcr); -+ } -+ -+ wcss->qdsp6ss_axim_cbcr = devm_clk_get(wcss->dev, "lcc_axim_cbc"); -+ if (IS_ERR(wcss->qdsp6ss_axim_cbcr)) { -+ ret = PTR_ERR(wcss->qdsp6ss_axim_cbcr); -+ if (ret != -EPROBE_DEFER) -+ dev_err(wcss->dev, "failed to get axim cbcr clk\n"); -+ return PTR_ERR(wcss->qdsp6ss_abhm_cbcr); -+ } -+ -+ wcss->lcc_bcr_sleep = devm_clk_get(wcss->dev, "lcc_bcr_sleep"); -+ if (IS_ERR(wcss->lcc_bcr_sleep)) { -+ ret = PTR_ERR(wcss->lcc_bcr_sleep); -+ if (ret != -EPROBE_DEFER) -+ dev_err(wcss->dev, "failed to get bcr cbcr clk\n"); -+ return PTR_ERR(wcss->lcc_bcr_sleep); -+ } -+ -+ return 0; -+} -+ -+static int q6v5_wcss_init_regulator(struct q6v5_wcss *wcss) -+{ -+ wcss->cx_supply = devm_regulator_get(wcss->dev, "cx"); -+ if (IS_ERR(wcss->cx_supply)) -+ return PTR_ERR(wcss->cx_supply); -+ -+ regulator_set_load(wcss->cx_supply, 100000); -+ -+ return 0; -+} -+ - static int q6v5_wcss_probe(struct platform_device *pdev) - { - const struct wcss_data *desc; -@@ -554,7 +1008,7 @@ static int q6v5_wcss_probe(struct platfo - if (!desc) - return -EINVAL; - -- rproc = rproc_alloc(&pdev->dev, pdev->name, &q6v5_wcss_ipq8074_ops, -+ rproc = rproc_alloc(&pdev->dev, pdev->name, desc->ops, - desc->firmware_name, sizeof(*wcss)); - if (!rproc) { - dev_err(&pdev->dev, "failed to allocate rproc\n"); -@@ -563,7 +1017,10 @@ static int q6v5_wcss_probe(struct platfo - - wcss = rproc->priv; - wcss->dev = &pdev->dev; -- wcss->crash_reason_smem = desc->crash_reason_smem; -+ wcss->version = desc->version; -+ -+ wcss->version = desc->version; -+ wcss->requires_force_stop = desc->requires_force_stop; - - ret = q6v5_wcss_init_mmio(wcss, pdev); - if (ret) -@@ -573,7 +1030,17 @@ static int q6v5_wcss_probe(struct platfo - if (ret) - goto free_rproc; - -- ret = q6v5_wcss_init_reset(wcss); -+ if (wcss->version == WCSS_QCS404) { -+ ret = q6v5_wcss_init_clock(wcss); -+ if (ret) -+ goto free_rproc; -+ -+ ret = q6v5_wcss_init_regulator(wcss); -+ if (ret) -+ goto free_rproc; -+ } -+ -+ ret = q6v5_wcss_init_reset(wcss, desc); - if (ret) - goto free_rproc; - -@@ -585,6 +1052,11 @@ static int q6v5_wcss_probe(struct platfo - qcom_add_glink_subdev(rproc, &wcss->glink_subdev, "q6wcss"); - qcom_add_ssr_subdev(rproc, &wcss->ssr_subdev, "q6wcss"); - -+ if (desc->ssctl_id) -+ wcss->sysmon = qcom_add_sysmon_subdev(rproc, -+ desc->sysmon_name, -+ desc->ssctl_id); -+ - ret = rproc_add(rproc); - if (ret) - goto free_rproc; -@@ -612,10 +1084,28 @@ static int q6v5_wcss_remove(struct platf - static const struct wcss_data wcss_ipq8074_res_init = { - .firmware_name = "IPQ8074/q6_fw.mdt", - .crash_reason_smem = WCSS_CRASH_REASON, -+ .aon_reset_required = true, -+ .wcss_q6_reset_required = true, -+ .ops = &q6v5_wcss_ipq8074_ops, -+ .requires_force_stop = true, -+}; -+ -+static const struct wcss_data wcss_qcs404_res_init = { -+ .crash_reason_smem = WCSS_CRASH_REASON, -+ .firmware_name = "wcnss.mdt", -+ .version = WCSS_QCS404, -+ .aon_reset_required = false, -+ .wcss_q6_reset_required = false, -+ .ssr_name = "mpss", -+ .sysmon_name = "wcnss", -+ .ssctl_id = 0x12, -+ .ops = &q6v5_wcss_qcs404_ops, -+ .requires_force_stop = false, - }; - - static const struct of_device_id q6v5_wcss_of_match[] = { - { .compatible = "qcom,ipq8074-wcss-pil", .data = &wcss_ipq8074_res_init }, -+ { .compatible = "qcom,qcs404-wcss-pil", .data = &wcss_qcs404_res_init }, - { }, - }; - MODULE_DEVICE_TABLE(of, q6v5_wcss_of_match); diff --git a/target/linux/ipq807x/patches-5.10/005-v5.13-remoteproc-qcom-wcss-explicitly-request-exclusive-re.patch b/target/linux/ipq807x/patches-5.10/005-v5.13-remoteproc-qcom-wcss-explicitly-request-exclusive-re.patch deleted file mode 100644 index 3b09a6dd2..000000000 --- a/target/linux/ipq807x/patches-5.10/005-v5.13-remoteproc-qcom-wcss-explicitly-request-exclusive-re.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 7b230496f6b45e840bc7b13e7df2a8676bab9230 Mon Sep 17 00:00:00 2001 -From: Govind Singh -Date: Fri, 29 Jan 2021 00:18:15 +0530 -Subject: [PATCH 04/16] remoteproc: qcom: wcss: explicitly request exclusive - reset control - -Use request exclusive reset control for wcss reset controls. - -Signed-off-by: Govind Singh -Signed-off-by: Gokul Sriram Palanisamy -Link: https://lore.kernel.org/r/1611859695-11824-5-git-send-email-gokulsri@codeaurora.org -Signed-off-by: Bjorn Andersson ---- - drivers/remoteproc/qcom_q6v5_wcss.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - ---- a/drivers/remoteproc/qcom_q6v5_wcss.c -+++ b/drivers/remoteproc/qcom_q6v5_wcss.c -@@ -788,21 +788,21 @@ static int q6v5_wcss_init_reset(struct q - struct device *dev = wcss->dev; - - if (desc->aon_reset_required) { -- wcss->wcss_aon_reset = devm_reset_control_get(dev, "wcss_aon_reset"); -+ wcss->wcss_aon_reset = devm_reset_control_get_exclusive(dev, "wcss_aon_reset"); - if (IS_ERR(wcss->wcss_aon_reset)) { - dev_err(wcss->dev, "fail to acquire wcss_aon_reset\n"); - return PTR_ERR(wcss->wcss_aon_reset); - } - } - -- wcss->wcss_reset = devm_reset_control_get(dev, "wcss_reset"); -+ wcss->wcss_reset = devm_reset_control_get_exclusive(dev, "wcss_reset"); - if (IS_ERR(wcss->wcss_reset)) { - dev_err(wcss->dev, "unable to acquire wcss_reset\n"); - return PTR_ERR(wcss->wcss_reset); - } - - if (desc->wcss_q6_reset_required) { -- wcss->wcss_q6_reset = devm_reset_control_get(dev, "wcss_q6_reset"); -+ wcss->wcss_q6_reset = devm_reset_control_get_exclusive(dev, "wcss_q6_reset"); - if (IS_ERR(wcss->wcss_q6_reset)) { - dev_err(wcss->dev, "unable to acquire wcss_q6_reset\n"); - return PTR_ERR(wcss->wcss_q6_reset); diff --git a/target/linux/ipq807x/patches-5.10/006-v5.13-remoteproc-qcom-wcss-Fix-return-value-check-in-q6v5_.patch b/target/linux/ipq807x/patches-5.10/006-v5.13-remoteproc-qcom-wcss-Fix-return-value-check-in-q6v5_.patch deleted file mode 100644 index fe5e33c23..000000000 --- a/target/linux/ipq807x/patches-5.10/006-v5.13-remoteproc-qcom-wcss-Fix-return-value-check-in-q6v5_.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 5b8b0967576f04d2ee3ea36310c078a3d50e7339 Mon Sep 17 00:00:00 2001 -From: Wei Yongjun -Date: Fri, 19 Mar 2021 09:41:00 +0000 -Subject: [PATCH 05/16] remoteproc: qcom: wcss: Fix return value check in - q6v5_wcss_init_mmio() - -In case of error, the function devm_ioremap() returns NULL pointer -not ERR_PTR(). The IS_ERR() test in the return value check should -be replaced with NULL test. - -Fixes: 0af65b9b915e ("remoteproc: qcom: wcss: Add non pas wcss Q6 support for QCS404") -Reported-by: Hulk Robot -Signed-off-by: Wei Yongjun -Link: https://lore.kernel.org/r/20210319094100.4185044-1-weiyongjun1@huawei.com -Signed-off-by: Bjorn Andersson ---- - drivers/remoteproc/qcom_q6v5_wcss.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/drivers/remoteproc/qcom_q6v5_wcss.c -+++ b/drivers/remoteproc/qcom_q6v5_wcss.c -@@ -829,8 +829,8 @@ static int q6v5_wcss_init_mmio(struct q6 - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "qdsp6"); - wcss->reg_base = devm_ioremap(&pdev->dev, res->start, - resource_size(res)); -- if (IS_ERR(wcss->reg_base)) -- return PTR_ERR(wcss->reg_base); -+ if (!wcss->reg_base) -+ return -ENOMEM; - - if (wcss->version == WCSS_IPQ8074) { - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rmb"); diff --git a/target/linux/ipq807x/patches-5.10/007-v5.13-remoteproc-qcom-wcss-Fix-wrong-pointer-passed-to-PTR.patch b/target/linux/ipq807x/patches-5.10/007-v5.13-remoteproc-qcom-wcss-Fix-wrong-pointer-passed-to-PTR.patch deleted file mode 100644 index 65676cf11..000000000 --- a/target/linux/ipq807x/patches-5.10/007-v5.13-remoteproc-qcom-wcss-Fix-wrong-pointer-passed-to-PTR.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 6a52dbbde0e741e84f217cf762233589cc3efd13 Mon Sep 17 00:00:00 2001 -From: Wei Yongjun -Date: Fri, 26 Mar 2021 02:47:41 +0000 -Subject: [PATCH 06/16] remoteproc: qcom: wcss: Fix wrong pointer passed to - PTR_ERR() - -PTR_ERR should access the value just tested by IS_ERR, otherwise -the wrong error code will be returned. - -This commit fix it by return 'ret' directly. - -Reviewed-by: Dan Carpenter -Fixes: 0af65b9b915e ("remoteproc: qcom: wcss: Add non pas wcss Q6 support for QCS404") -Reported-by: Hulk Robot -Signed-off-by: Wei Yongjun -Link: https://lore.kernel.org/r/20210326024741.841267-1-weiyongjun1@huawei.com -Signed-off-by: Bjorn Andersson ---- - drivers/remoteproc/qcom_q6v5_wcss.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/remoteproc/qcom_q6v5_wcss.c -+++ b/drivers/remoteproc/qcom_q6v5_wcss.c -@@ -972,7 +972,7 @@ static int q6v5_wcss_init_clock(struct q - ret = PTR_ERR(wcss->qdsp6ss_axim_cbcr); - if (ret != -EPROBE_DEFER) - dev_err(wcss->dev, "failed to get axim cbcr clk\n"); -- return PTR_ERR(wcss->qdsp6ss_abhm_cbcr); -+ return ret; - } - - wcss->lcc_bcr_sleep = devm_clk_get(wcss->dev, "lcc_bcr_sleep"); diff --git a/target/linux/ipq807x/patches-5.10/008-v5.13-remoteproc-qcom-wcss-Remove-unnecessary-PTR_ERR.patch b/target/linux/ipq807x/patches-5.10/008-v5.13-remoteproc-qcom-wcss-Remove-unnecessary-PTR_ERR.patch deleted file mode 100644 index dff8bda73..000000000 --- a/target/linux/ipq807x/patches-5.10/008-v5.13-remoteproc-qcom-wcss-Remove-unnecessary-PTR_ERR.patch +++ /dev/null @@ -1,89 +0,0 @@ -From 00f24490f498db0ea67715a4dfe6c4a6ca11c6a0 Mon Sep 17 00:00:00 2001 -From: Junlin Yang -Date: Thu, 8 Apr 2021 22:33:22 +0800 -Subject: [PATCH 07/16] remoteproc: qcom: wcss: Remove unnecessary PTR_ERR() - -Remove unnecessary PTR_ERR(), it has been assigned to ret before, -so return ret directly. - -Signed-off-by: Junlin Yang -Link: https://lore.kernel.org/r/20210408143322.1647-1-angkery@163.com -Signed-off-by: Bjorn Andersson ---- - drivers/remoteproc/qcom_q6v5_wcss.c | 16 ++++++++-------- - 1 file changed, 8 insertions(+), 8 deletions(-) - ---- a/drivers/remoteproc/qcom_q6v5_wcss.c -+++ b/drivers/remoteproc/qcom_q6v5_wcss.c -@@ -913,7 +913,7 @@ static int q6v5_wcss_init_clock(struct q - ret = PTR_ERR(wcss->gcc_abhs_cbcr); - if (ret != -EPROBE_DEFER) - dev_err(wcss->dev, "failed to get gcc abhs clock"); -- return PTR_ERR(wcss->gcc_abhs_cbcr); -+ return ret; - } - - wcss->gcc_axim_cbcr = devm_clk_get(wcss->dev, "gcc_axim_cbcr"); -@@ -921,7 +921,7 @@ static int q6v5_wcss_init_clock(struct q - ret = PTR_ERR(wcss->gcc_axim_cbcr); - if (ret != -EPROBE_DEFER) - dev_err(wcss->dev, "failed to get gcc axim clock\n"); -- return PTR_ERR(wcss->gcc_axim_cbcr); -+ return ret; - } - - wcss->ahbfabric_cbcr_clk = devm_clk_get(wcss->dev, -@@ -930,7 +930,7 @@ static int q6v5_wcss_init_clock(struct q - ret = PTR_ERR(wcss->ahbfabric_cbcr_clk); - if (ret != -EPROBE_DEFER) - dev_err(wcss->dev, "failed to get ahbfabric clock\n"); -- return PTR_ERR(wcss->ahbfabric_cbcr_clk); -+ return ret; - } - - wcss->lcc_csr_cbcr = devm_clk_get(wcss->dev, "tcsr_lcc_cbc"); -@@ -938,7 +938,7 @@ static int q6v5_wcss_init_clock(struct q - ret = PTR_ERR(wcss->lcc_csr_cbcr); - if (ret != -EPROBE_DEFER) - dev_err(wcss->dev, "failed to get csr cbcr clk\n"); -- return PTR_ERR(wcss->lcc_csr_cbcr); -+ return ret; - } - - wcss->ahbs_cbcr = devm_clk_get(wcss->dev, -@@ -947,7 +947,7 @@ static int q6v5_wcss_init_clock(struct q - ret = PTR_ERR(wcss->ahbs_cbcr); - if (ret != -EPROBE_DEFER) - dev_err(wcss->dev, "failed to get ahbs_cbcr clk\n"); -- return PTR_ERR(wcss->ahbs_cbcr); -+ return ret; - } - - wcss->tcm_slave_cbcr = devm_clk_get(wcss->dev, -@@ -956,7 +956,7 @@ static int q6v5_wcss_init_clock(struct q - ret = PTR_ERR(wcss->tcm_slave_cbcr); - if (ret != -EPROBE_DEFER) - dev_err(wcss->dev, "failed to get tcm cbcr clk\n"); -- return PTR_ERR(wcss->tcm_slave_cbcr); -+ return ret; - } - - wcss->qdsp6ss_abhm_cbcr = devm_clk_get(wcss->dev, "lcc_abhm_cbc"); -@@ -964,7 +964,7 @@ static int q6v5_wcss_init_clock(struct q - ret = PTR_ERR(wcss->qdsp6ss_abhm_cbcr); - if (ret != -EPROBE_DEFER) - dev_err(wcss->dev, "failed to get abhm cbcr clk\n"); -- return PTR_ERR(wcss->qdsp6ss_abhm_cbcr); -+ return ret; - } - - wcss->qdsp6ss_axim_cbcr = devm_clk_get(wcss->dev, "lcc_axim_cbc"); -@@ -980,7 +980,7 @@ static int q6v5_wcss_init_clock(struct q - ret = PTR_ERR(wcss->lcc_bcr_sleep); - if (ret != -EPROBE_DEFER) - dev_err(wcss->dev, "failed to get bcr cbcr clk\n"); -- return PTR_ERR(wcss->lcc_bcr_sleep); -+ return ret; - } - - return 0; diff --git a/target/linux/ipq807x/patches-5.10/009-5.12-mtd-parsers-Add-Qcom-SMEM-parser.patch b/target/linux/ipq807x/patches-5.10/009-5.12-mtd-parsers-Add-Qcom-SMEM-parser.patch deleted file mode 100644 index 8079c1935..000000000 --- a/target/linux/ipq807x/patches-5.10/009-5.12-mtd-parsers-Add-Qcom-SMEM-parser.patch +++ /dev/null @@ -1,217 +0,0 @@ -From 803eb124e1a64e42888542c3444bfe6dac412c7f Mon Sep 17 00:00:00 2001 -From: Manivannan Sadhasivam -Date: Mon, 4 Jan 2021 09:41:35 +0530 -Subject: mtd: parsers: Add Qcom SMEM parser - -NAND based Qualcomm platforms have the partition table populated in the -Shared Memory (SMEM). Hence, add a parser for parsing the partitions -from it. - -Signed-off-by: Manivannan Sadhasivam -Signed-off-by: Miquel Raynal -Link: https://lore.kernel.org/linux-mtd/20210104041137.113075-3-manivannan.sadhasivam@linaro.org ---- - drivers/mtd/parsers/Kconfig | 8 ++ - drivers/mtd/parsers/Makefile | 1 + - drivers/mtd/parsers/qcomsmempart.c | 170 +++++++++++++++++++++++++++++++++++++ - 3 files changed, 179 insertions(+) - create mode 100644 drivers/mtd/parsers/qcomsmempart.c - ---- a/drivers/mtd/parsers/Kconfig -+++ b/drivers/mtd/parsers/Kconfig -@@ -205,6 +205,14 @@ config MTD_SERCOMM_PARTS - offsets, which may differ from device to device depending on the - number and location of bad blocks on NAND. - -+config MTD_QCOMSMEM_PARTS -+ tristate "Qualcomm SMEM NAND flash partition parser" -+ depends on MTD_NAND_QCOM || COMPILE_TEST -+ depends on QCOM_SMEM -+ help -+ This provides support for parsing partitions from Shared Memory (SMEM) -+ for NAND flash on Qualcomm platforms. -+ - config MTD_ROUTERBOOT_PARTS - tristate "RouterBoot flash partition parser" - depends on MTD && OF ---- a/drivers/mtd/parsers/Makefile -+++ b/drivers/mtd/parsers/Makefile -@@ -14,4 +14,5 @@ obj-$(CONFIG_MTD_PARSER_TRX) += parser_ - obj-$(CONFIG_MTD_SERCOMM_PARTS) += scpart.o - obj-$(CONFIG_MTD_SHARPSL_PARTS) += sharpslpart.o - obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o -+obj-$(CONFIG_MTD_QCOMSMEM_PARTS) += qcomsmempart.o - obj-$(CONFIG_MTD_ROUTERBOOT_PARTS) += routerbootpart.o ---- /dev/null -+++ b/drivers/mtd/parsers/qcomsmempart.c -@@ -0,0 +1,170 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* -+ * Qualcomm SMEM NAND flash partition parser -+ * -+ * Copyright (C) 2020, Linaro Ltd. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define SMEM_AARM_PARTITION_TABLE 9 -+#define SMEM_APPS 0 -+ -+#define SMEM_FLASH_PART_MAGIC1 0x55ee73aa -+#define SMEM_FLASH_PART_MAGIC2 0xe35ebddb -+#define SMEM_FLASH_PTABLE_V3 3 -+#define SMEM_FLASH_PTABLE_V4 4 -+#define SMEM_FLASH_PTABLE_MAX_PARTS_V3 16 -+#define SMEM_FLASH_PTABLE_MAX_PARTS_V4 48 -+#define SMEM_FLASH_PTABLE_HDR_LEN (4 * sizeof(u32)) -+#define SMEM_FLASH_PTABLE_NAME_SIZE 16 -+ -+/** -+ * struct smem_flash_pentry - SMEM Flash partition entry -+ * @name: Name of the partition -+ * @offset: Offset in blocks -+ * @length: Length of the partition in blocks -+ * @attr: Flags for this partition -+ */ -+struct smem_flash_pentry { -+ char name[SMEM_FLASH_PTABLE_NAME_SIZE]; -+ __le32 offset; -+ __le32 length; -+ u8 attr; -+} __packed __aligned(4); -+ -+/** -+ * struct smem_flash_ptable - SMEM Flash partition table -+ * @magic1: Partition table Magic 1 -+ * @magic2: Partition table Magic 2 -+ * @version: Partition table version -+ * @numparts: Number of partitions in this ptable -+ * @pentry: Flash partition entries belonging to this ptable -+ */ -+struct smem_flash_ptable { -+ __le32 magic1; -+ __le32 magic2; -+ __le32 version; -+ __le32 numparts; -+ struct smem_flash_pentry pentry[SMEM_FLASH_PTABLE_MAX_PARTS_V4]; -+} __packed __aligned(4); -+ -+static int parse_qcomsmem_part(struct mtd_info *mtd, -+ const struct mtd_partition **pparts, -+ struct mtd_part_parser_data *data) -+{ -+ struct smem_flash_pentry *pentry; -+ struct smem_flash_ptable *ptable; -+ size_t len = SMEM_FLASH_PTABLE_HDR_LEN; -+ struct mtd_partition *parts; -+ int ret, i, numparts; -+ char *name, *c; -+ -+ pr_debug("Parsing partition table info from SMEM\n"); -+ ptable = qcom_smem_get(SMEM_APPS, SMEM_AARM_PARTITION_TABLE, &len); -+ if (IS_ERR(ptable)) { -+ pr_err("Error reading partition table header\n"); -+ return PTR_ERR(ptable); -+ } -+ -+ /* Verify ptable magic */ -+ if (le32_to_cpu(ptable->magic1) != SMEM_FLASH_PART_MAGIC1 || -+ le32_to_cpu(ptable->magic2) != SMEM_FLASH_PART_MAGIC2) { -+ pr_err("Partition table magic verification failed\n"); -+ return -EINVAL; -+ } -+ -+ /* Ensure that # of partitions is less than the max we have allocated */ -+ numparts = le32_to_cpu(ptable->numparts); -+ if (numparts > SMEM_FLASH_PTABLE_MAX_PARTS_V4) { -+ pr_err("Partition numbers exceed the max limit\n"); -+ return -EINVAL; -+ } -+ -+ /* Find out length of partition data based on table version */ -+ if (le32_to_cpu(ptable->version) <= SMEM_FLASH_PTABLE_V3) { -+ len = SMEM_FLASH_PTABLE_HDR_LEN + SMEM_FLASH_PTABLE_MAX_PARTS_V3 * -+ sizeof(struct smem_flash_pentry); -+ } else if (le32_to_cpu(ptable->version) == SMEM_FLASH_PTABLE_V4) { -+ len = SMEM_FLASH_PTABLE_HDR_LEN + SMEM_FLASH_PTABLE_MAX_PARTS_V4 * -+ sizeof(struct smem_flash_pentry); -+ } else { -+ pr_err("Unknown ptable version (%d)", le32_to_cpu(ptable->version)); -+ return -EINVAL; -+ } -+ -+ /* -+ * Now that the partition table header has been parsed, verified -+ * and the length of the partition table calculated, read the -+ * complete partition table -+ */ -+ ptable = qcom_smem_get(SMEM_APPS, SMEM_AARM_PARTITION_TABLE, &len); -+ if (IS_ERR_OR_NULL(ptable)) { -+ pr_err("Error reading partition table\n"); -+ return PTR_ERR(ptable); -+ } -+ -+ parts = kcalloc(numparts, sizeof(*parts), GFP_KERNEL); -+ if (!parts) -+ return -ENOMEM; -+ -+ for (i = 0; i < numparts; i++) { -+ pentry = &ptable->pentry[i]; -+ if (pentry->name[0] == '\0') -+ continue; -+ -+ name = kstrdup(pentry->name, GFP_KERNEL); -+ if (!name) { -+ ret = -ENOMEM; -+ goto out_free_parts; -+ } -+ -+ /* Convert name to lower case */ -+ for (c = name; *c != '\0'; c++) -+ *c = tolower(*c); -+ -+ parts[i].name = name; -+ parts[i].offset = le32_to_cpu(pentry->offset) * mtd->erasesize; -+ parts[i].mask_flags = pentry->attr; -+ parts[i].size = le32_to_cpu(pentry->length) * mtd->erasesize; -+ pr_debug("%d: %s offs=0x%08x size=0x%08x attr:0x%08x\n", -+ i, pentry->name, le32_to_cpu(pentry->offset), -+ le32_to_cpu(pentry->length), pentry->attr); -+ } -+ -+ pr_debug("SMEM partition table found: ver: %d len: %d\n", -+ le32_to_cpu(ptable->version), numparts); -+ *pparts = parts; -+ -+ return numparts; -+ -+out_free_parts: -+ while (--i >= 0) -+ kfree(parts[i].name); -+ kfree(parts); -+ *pparts = NULL; -+ -+ return ret; -+} -+ -+static const struct of_device_id qcomsmem_of_match_table[] = { -+ { .compatible = "qcom,smem-part" }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, qcomsmem_of_match_table); -+ -+static struct mtd_part_parser mtd_parser_qcomsmem = { -+ .parse_fn = parse_qcomsmem_part, -+ .name = "qcomsmem", -+ .of_match_table = qcomsmem_of_match_table, -+}; -+module_mtd_part_parser(mtd_parser_qcomsmem); -+ -+MODULE_LICENSE("GPL v2"); -+MODULE_AUTHOR("Manivannan Sadhasivam "); -+MODULE_DESCRIPTION("Qualcomm SMEM NAND flash partition parser"); diff --git a/target/linux/ipq807x/patches-5.10/010-v5.11-PCI-dwc-Drop-the-.set_num_vectors-host-op.patch b/target/linux/ipq807x/patches-5.10/010-v5.11-PCI-dwc-Drop-the-.set_num_vectors-host-op.patch deleted file mode 100644 index 18c933c40..000000000 --- a/target/linux/ipq807x/patches-5.10/010-v5.11-PCI-dwc-Drop-the-.set_num_vectors-host-op.patch +++ /dev/null @@ -1,120 +0,0 @@ -From 80b960829a85e555b96bfd4e31f31b3db3e8f5da Mon Sep 17 00:00:00 2001 -From: Rob Herring -Date: Thu, 5 Nov 2020 15:11:50 -0600 -Subject: [PATCH 1/5] PCI: dwc: Drop the .set_num_vectors() host op - -There's no reason for the .set_num_vectors() host op. Drivers needing a -non-default value can just initialize pcie_port.num_vectors directly. - -Link: https://lore.kernel.org/r/20201105211159.1814485-8-robh@kernel.org -Tested-by: Marek Szyprowski -Signed-off-by: Rob Herring -Signed-off-by: Lorenzo Pieralisi -Acked-by: Jingoo Han -Cc: Gustavo Pimentel -Cc: Lorenzo Pieralisi -Cc: Bjorn Helgaas -Cc: Thierry Reding -Cc: Jonathan Hunter -Cc: linux-tegra@vger.kernel.org ---- - .../pci/controller/dwc/pcie-designware-host.c | 19 ++++--------------- - .../pci/controller/dwc/pcie-designware-plat.c | 7 +------ - drivers/pci/controller/dwc/pcie-designware.h | 1 - - drivers/pci/controller/dwc/pcie-tegra194.c | 7 +------ - 4 files changed, 6 insertions(+), 28 deletions(-) - ---- a/drivers/pci/controller/dwc/pcie-designware-host.c -+++ b/drivers/pci/controller/dwc/pcie-designware-host.c -@@ -358,22 +358,11 @@ int dw_pcie_host_init(struct pcie_port * - pci->link_gen = of_pci_get_max_link_speed(np); - - if (pci_msi_enabled()) { -- /* -- * If a specific SoC driver needs to change the -- * default number of vectors, it needs to implement -- * the set_num_vectors callback. -- */ -- if (!pp->ops->set_num_vectors) { -+ if (!pp->num_vectors) { - pp->num_vectors = MSI_DEF_NUM_VECTORS; -- } else { -- pp->ops->set_num_vectors(pp); -- -- if (pp->num_vectors > MAX_MSI_IRQS || -- pp->num_vectors == 0) { -- dev_err(dev, -- "Invalid number of vectors\n"); -- return -EINVAL; -- } -+ } else if (pp->num_vectors > MAX_MSI_IRQS) { -+ dev_err(dev, "Invalid number of vectors\n"); -+ return -EINVAL; - } - - if (!pp->ops->msi_host_init) { ---- a/drivers/pci/controller/dwc/pcie-designware-plat.c -+++ b/drivers/pci/controller/dwc/pcie-designware-plat.c -@@ -44,14 +44,8 @@ static int dw_plat_pcie_host_init(struct - return 0; - } - --static void dw_plat_set_num_vectors(struct pcie_port *pp) --{ -- pp->num_vectors = MAX_MSI_IRQS; --} -- - static const struct dw_pcie_host_ops dw_plat_pcie_host_ops = { - .host_init = dw_plat_pcie_host_init, -- .set_num_vectors = dw_plat_set_num_vectors, - }; - - static int dw_plat_pcie_establish_link(struct dw_pcie *pci) -@@ -128,6 +122,7 @@ static int dw_plat_add_pcie_port(struct - return pp->msi_irq; - } - -+ pp->num_vectors = MAX_MSI_IRQS; - pp->ops = &dw_plat_pcie_host_ops; - - ret = dw_pcie_host_init(pp); ---- a/drivers/pci/controller/dwc/pcie-designware.h -+++ b/drivers/pci/controller/dwc/pcie-designware.h -@@ -174,7 +174,6 @@ enum dw_pcie_device_mode { - - struct dw_pcie_host_ops { - int (*host_init)(struct pcie_port *pp); -- void (*set_num_vectors)(struct pcie_port *pp); - int (*msi_host_init)(struct pcie_port *pp); - }; - ---- a/drivers/pci/controller/dwc/pcie-tegra194.c -+++ b/drivers/pci/controller/dwc/pcie-tegra194.c -@@ -996,11 +996,6 @@ static int tegra_pcie_dw_link_up(struct - return !!(val & PCI_EXP_LNKSTA_DLLLA); - } - --static void tegra_pcie_set_msi_vec_num(struct pcie_port *pp) --{ -- pp->num_vectors = MAX_MSI_IRQS; --} -- - static int tegra_pcie_dw_start_link(struct dw_pcie *pci) - { - struct tegra_pcie_dw *pcie = to_tegra_pcie(pci); -@@ -1025,7 +1020,6 @@ static const struct dw_pcie_ops tegra_dw - - static struct dw_pcie_host_ops tegra_pcie_dw_host_ops = { - .host_init = tegra_pcie_dw_host_init, -- .set_num_vectors = tegra_pcie_set_msi_vec_num, - }; - - static void tegra_pcie_disable_phy(struct tegra_pcie_dw *pcie) -@@ -2010,6 +2004,7 @@ static int tegra_pcie_dw_probe(struct pl - pci->n_fts[1] = FTS_VAL; - - pp = &pci->pp; -+ pp->num_vectors = MAX_MSI_IRQS; - pcie->dev = &pdev->dev; - pcie->mode = (enum dw_pcie_device_mode)data->mode; - diff --git a/target/linux/ipq807x/patches-5.10/011-v5.11-PCI-dwc-Move-MSI-interrupt-setup-into-DWC-common-cod.patch b/target/linux/ipq807x/patches-5.10/011-v5.11-PCI-dwc-Move-MSI-interrupt-setup-into-DWC-common-cod.patch deleted file mode 100644 index d4d31eb0f..000000000 --- a/target/linux/ipq807x/patches-5.10/011-v5.11-PCI-dwc-Move-MSI-interrupt-setup-into-DWC-common-cod.patch +++ /dev/null @@ -1,288 +0,0 @@ -From 264b6fd7baa53bfaef2a6d41067b9568dff7163a Mon Sep 17 00:00:00 2001 -From: Rob Herring -Date: Thu, 5 Nov 2020 15:11:51 -0600 -Subject: [PATCH 2/5] PCI: dwc: Move MSI interrupt setup into DWC common code - -Platforms using the built-in DWC MSI controller all have a dedicated -interrupt with "msi" name or at index 0, so let's move setting up the -interrupt to the common DWC code. - -spear13xx and dra7xx are the 2 oddballs with muxed interrupts, so -we need to prevent configuring the MSI interrupt by setting msi_irq -to negative. - -Link: https://lore.kernel.org/r/20201105211159.1814485-9-robh@kernel.org -Tested-by: Marek Szyprowski -Signed-off-by: Rob Herring -Signed-off-by: Lorenzo Pieralisi -Acked-by: Jingoo Han -Cc: Lorenzo Pieralisi -Cc: Bjorn Helgaas -Cc: Kukjin Kim -Cc: Krzysztof Kozlowski -Cc: Richard Zhu -Cc: Lucas Stach -Cc: Shawn Guo -Cc: Sascha Hauer -Cc: Pengutronix Kernel Team -Cc: Fabio Estevam -Cc: NXP Linux Team -Cc: Yue Wang -Cc: Kevin Hilman -Cc: Neil Armstrong -Cc: Jerome Brunet -Cc: Martin Blumenstingl -Cc: Jesper Nilsson -Cc: Gustavo Pimentel -Cc: Xiaowei Song -Cc: Binghui Wang -Cc: Stanimir Varbanov -Cc: Andy Gross -Cc: Bjorn Andersson -Cc: Pratyush Anand -Cc: Thierry Reding -Cc: Jonathan Hunter -Cc: Kunihiko Hayashi -Cc: Masahiro Yamada -Cc: linux-samsung-soc@vger.kernel.org -Cc: linux-amlogic@lists.infradead.org -Cc: linux-arm-kernel@axis.com -Cc: linux-arm-msm@vger.kernel.org -Cc: linux-tegra@vger.kernel.org ---- - drivers/pci/controller/dwc/pci-dra7xx.c | 3 +++ - drivers/pci/controller/dwc/pci-exynos.c | 6 ----- - drivers/pci/controller/dwc/pci-imx6.c | 6 ----- - drivers/pci/controller/dwc/pci-meson.c | 6 ----- - drivers/pci/controller/dwc/pcie-artpec6.c | 6 ----- - .../pci/controller/dwc/pcie-designware-host.c | 11 +++++++++- - .../pci/controller/dwc/pcie-designware-plat.c | 6 ----- - drivers/pci/controller/dwc/pcie-histb.c | 6 ----- - drivers/pci/controller/dwc/pcie-kirin.c | 22 ------------------- - drivers/pci/controller/dwc/pcie-qcom.c | 8 ------- - drivers/pci/controller/dwc/pcie-spear13xx.c | 1 + - drivers/pci/controller/dwc/pcie-tegra194.c | 8 ------- - drivers/pci/controller/dwc/pcie-uniphier.c | 6 ----- - 13 files changed, 14 insertions(+), 81 deletions(-) - ---- a/drivers/pci/controller/dwc/pci-dra7xx.c -+++ b/drivers/pci/controller/dwc/pci-dra7xx.c -@@ -622,6 +622,9 @@ static int __init dra7xx_add_pcie_port(s - if (pp->irq < 0) - return pp->irq; - -+ /* MSI IRQ is muxed */ -+ pp->msi_irq = -ENODEV; -+ - ret = dra7xx_pcie_init_irq_domain(pp); - if (ret < 0) - return ret; ---- a/drivers/pci/controller/dwc/pci-exynos.c -+++ b/drivers/pci/controller/dwc/pci-exynos.c -@@ -415,12 +415,6 @@ static int __init exynos_add_pcie_port(s - return ret; - } - -- if (IS_ENABLED(CONFIG_PCI_MSI)) { -- pp->msi_irq = platform_get_irq(pdev, 0); -- if (pp->msi_irq < 0) -- return pp->msi_irq; -- } -- - pp->ops = &exynos_pcie_host_ops; - - ret = dw_pcie_host_init(pp); ---- a/drivers/pci/controller/dwc/pci-imx6.c -+++ b/drivers/pci/controller/dwc/pci-imx6.c -@@ -858,12 +858,6 @@ static int imx6_add_pcie_port(struct imx - struct device *dev = &pdev->dev; - int ret; - -- if (IS_ENABLED(CONFIG_PCI_MSI)) { -- pp->msi_irq = platform_get_irq_byname(pdev, "msi"); -- if (pp->msi_irq < 0) -- return pp->msi_irq; -- } -- - pp->ops = &imx6_pcie_host_ops; - - ret = dw_pcie_host_init(pp); ---- a/drivers/pci/controller/dwc/pci-meson.c -+++ b/drivers/pci/controller/dwc/pci-meson.c -@@ -405,12 +405,6 @@ static int meson_add_pcie_port(struct me - struct device *dev = &pdev->dev; - int ret; - -- if (IS_ENABLED(CONFIG_PCI_MSI)) { -- pp->msi_irq = platform_get_irq(pdev, 0); -- if (pp->msi_irq < 0) -- return pp->msi_irq; -- } -- - pp->ops = &meson_pcie_host_ops; - - ret = dw_pcie_host_init(pp); ---- a/drivers/pci/controller/dwc/pcie-artpec6.c -+++ b/drivers/pci/controller/dwc/pcie-artpec6.c -@@ -348,12 +348,6 @@ static int artpec6_add_pcie_port(struct - struct device *dev = pci->dev; - int ret; - -- if (IS_ENABLED(CONFIG_PCI_MSI)) { -- pp->msi_irq = platform_get_irq_byname(pdev, "msi"); -- if (pp->msi_irq < 0) -- return pp->msi_irq; -- } -- - pp->ops = &artpec6_pcie_host_ops; - - ret = dw_pcie_host_init(pp); ---- a/drivers/pci/controller/dwc/pcie-designware-host.c -+++ b/drivers/pci/controller/dwc/pcie-designware-host.c -@@ -366,13 +366,22 @@ int dw_pcie_host_init(struct pcie_port * - } - - if (!pp->ops->msi_host_init) { -+ if (!pp->msi_irq) { -+ pp->msi_irq = platform_get_irq_byname_optional(pdev, "msi"); -+ if (pp->msi_irq < 0) { -+ pp->msi_irq = platform_get_irq(pdev, 0); -+ if (pp->msi_irq < 0) -+ return pp->msi_irq; -+ } -+ } -+ - pp->msi_irq_chip = &dw_pci_msi_bottom_irq_chip; - - ret = dw_pcie_allocate_domains(pp); - if (ret) - return ret; - -- if (pp->msi_irq) -+ if (pp->msi_irq > 0) - irq_set_chained_handler_and_data(pp->msi_irq, - dw_chained_msi_isr, - pp); ---- a/drivers/pci/controller/dwc/pcie-designware-plat.c -+++ b/drivers/pci/controller/dwc/pcie-designware-plat.c -@@ -116,12 +116,6 @@ static int dw_plat_add_pcie_port(struct - if (pp->irq < 0) - return pp->irq; - -- if (IS_ENABLED(CONFIG_PCI_MSI)) { -- pp->msi_irq = platform_get_irq(pdev, 0); -- if (pp->msi_irq < 0) -- return pp->msi_irq; -- } -- - pp->num_vectors = MAX_MSI_IRQS; - pp->ops = &dw_plat_pcie_host_ops; - ---- a/drivers/pci/controller/dwc/pcie-histb.c -+++ b/drivers/pci/controller/dwc/pcie-histb.c -@@ -400,12 +400,6 @@ static int histb_pcie_probe(struct platf - return PTR_ERR(hipcie->bus_reset); - } - -- if (IS_ENABLED(CONFIG_PCI_MSI)) { -- pp->msi_irq = platform_get_irq_byname(pdev, "msi"); -- if (pp->msi_irq < 0) -- return pp->msi_irq; -- } -- - hipcie->phy = devm_phy_get(dev, "phy"); - if (IS_ERR(hipcie->phy)) { - dev_info(dev, "no pcie-phy found\n"); ---- a/drivers/pci/controller/dwc/pcie-kirin.c -+++ b/drivers/pci/controller/dwc/pcie-kirin.c -@@ -444,31 +444,9 @@ static const struct dw_pcie_host_ops kir - .host_init = kirin_pcie_host_init, - }; - --static int kirin_pcie_add_msi(struct dw_pcie *pci, -- struct platform_device *pdev) --{ -- int irq; -- -- if (IS_ENABLED(CONFIG_PCI_MSI)) { -- irq = platform_get_irq(pdev, 0); -- if (irq < 0) -- return irq; -- -- pci->pp.msi_irq = irq; -- } -- -- return 0; --} -- - static int kirin_add_pcie_port(struct dw_pcie *pci, - struct platform_device *pdev) - { -- int ret; -- -- ret = kirin_pcie_add_msi(pci, pdev); -- if (ret) -- return ret; -- - pci->pp.ops = &kirin_pcie_host_ops; - - return dw_pcie_host_init(&pci->pp); ---- a/drivers/pci/controller/dwc/pcie-qcom.c -+++ b/drivers/pci/controller/dwc/pcie-qcom.c -@@ -1424,14 +1424,6 @@ static int qcom_pcie_probe(struct platfo - - pp->ops = &qcom_pcie_dw_ops; - -- if (IS_ENABLED(CONFIG_PCI_MSI)) { -- pp->msi_irq = platform_get_irq_byname(pdev, "msi"); -- if (pp->msi_irq < 0) { -- ret = pp->msi_irq; -- goto err_pm_runtime_put; -- } -- } -- - ret = phy_init(pcie->phy); - if (ret) - goto err_pm_runtime_put; ---- a/drivers/pci/controller/dwc/pcie-spear13xx.c -+++ b/drivers/pci/controller/dwc/pcie-spear13xx.c -@@ -183,6 +183,7 @@ static int spear13xx_add_pcie_port(struc - } - - pp->ops = &spear13xx_pcie_host_ops; -+ pp->msi_irq = -ENODEV; - - ret = dw_pcie_host_init(pp); - if (ret) { ---- a/drivers/pci/controller/dwc/pcie-tegra194.c -+++ b/drivers/pci/controller/dwc/pcie-tegra194.c -@@ -1560,14 +1560,6 @@ static int tegra_pcie_config_rp(struct t - char *name; - int ret; - -- if (IS_ENABLED(CONFIG_PCI_MSI)) { -- pp->msi_irq = of_irq_get_byname(dev->of_node, "msi"); -- if (!pp->msi_irq) { -- dev_err(dev, "Failed to get MSI interrupt\n"); -- return -ENODEV; -- } -- } -- - pm_runtime_enable(dev); - - ret = pm_runtime_get_sync(dev); ---- a/drivers/pci/controller/dwc/pcie-uniphier.c -+++ b/drivers/pci/controller/dwc/pcie-uniphier.c -@@ -335,12 +335,6 @@ static int uniphier_add_pcie_port(struct - - pp->ops = &uniphier_pcie_host_ops; - -- if (IS_ENABLED(CONFIG_PCI_MSI)) { -- pp->msi_irq = platform_get_irq_byname(pdev, "msi"); -- if (pp->msi_irq < 0) -- return pp->msi_irq; -- } -- - ret = dw_pcie_host_init(pp); - if (ret) { - dev_err(dev, "Failed to initialize host (%d)\n", ret); diff --git a/target/linux/ipq807x/patches-5.10/012-v5.11-PCI-dwc-Rework-MSI-initialization.patch b/target/linux/ipq807x/patches-5.10/012-v5.11-PCI-dwc-Rework-MSI-initialization.patch deleted file mode 100644 index a92518725..000000000 --- a/target/linux/ipq807x/patches-5.10/012-v5.11-PCI-dwc-Rework-MSI-initialization.patch +++ /dev/null @@ -1,199 +0,0 @@ -From ed016f820e3f1b980dfe0ef6137069e008f99109 Mon Sep 17 00:00:00 2001 -From: Rob Herring -Date: Thu, 5 Nov 2020 15:11:52 -0600 -Subject: [PATCH 3/5] PCI: dwc: Rework MSI initialization - -There are 3 possible MSI implementations for the DWC host. The first is -using the built-in DWC MSI controller. The 2nd is a custom MSI -controller as part of the PCI host (keystone only). The 3rd is an -external MSI controller (typically GICv3 ITS). Currently, the last 2 -are distinguished with a .msi_host_init() hook with the 3rd option using -an empty function. However we can detect the 3rd case with the presence -of 'msi-parent' or 'msi-map' properties, so let's do that instead and -remove the empty functions. - -Link: https://lore.kernel.org/r/20201105211159.1814485-10-robh@kernel.org -Tested-by: Marek Szyprowski -Signed-off-by: Rob Herring -Signed-off-by: Lorenzo Pieralisi -Acked-by: Jingoo Han -Cc: Murali Karicheri -Cc: Lorenzo Pieralisi -Cc: Bjorn Helgaas -Cc: Minghuan Lian -Cc: Mingkai Hu -Cc: Roy Zang -Cc: Gustavo Pimentel -Cc: linuxppc-dev@lists.ozlabs.org ---- - drivers/pci/controller/dwc/pci-keystone.c | 9 ------- - drivers/pci/controller/dwc/pci-layerscape.c | 25 ------------------- - .../pci/controller/dwc/pcie-designware-host.c | 20 +++++++++------ - drivers/pci/controller/dwc/pcie-designware.h | 1 + - drivers/pci/controller/dwc/pcie-intel-gw.c | 9 ------- - 5 files changed, 13 insertions(+), 51 deletions(-) - ---- a/drivers/pci/controller/dwc/pci-keystone.c -+++ b/drivers/pci/controller/dwc/pci-keystone.c -@@ -272,14 +272,6 @@ static void ks_pcie_handle_legacy_irq(st - ks_pcie_app_writel(ks_pcie, IRQ_EOI, offset); - } - --/* -- * Dummy function so that DW core doesn't configure MSI -- */ --static int ks_pcie_am654_msi_host_init(struct pcie_port *pp) --{ -- return 0; --} -- - static void ks_pcie_enable_error_irq(struct keystone_pcie *ks_pcie) - { - ks_pcie_app_writel(ks_pcie, ERR_IRQ_ENABLE_SET, ERR_IRQ_ALL); -@@ -855,7 +847,6 @@ static const struct dw_pcie_host_ops ks_ - - static const struct dw_pcie_host_ops ks_pcie_am654_host_ops = { - .host_init = ks_pcie_host_init, -- .msi_host_init = ks_pcie_am654_msi_host_init, - }; - - static irqreturn_t ks_pcie_err_irq_handler(int irq, void *priv) ---- a/drivers/pci/controller/dwc/pci-layerscape.c -+++ b/drivers/pci/controller/dwc/pci-layerscape.c -@@ -182,37 +182,12 @@ static int ls1021_pcie_host_init(struct - return ls_pcie_host_init(pp); - } - --static int ls_pcie_msi_host_init(struct pcie_port *pp) --{ -- struct dw_pcie *pci = to_dw_pcie_from_pp(pp); -- struct device *dev = pci->dev; -- struct device_node *np = dev->of_node; -- struct device_node *msi_node; -- -- /* -- * The MSI domain is set by the generic of_msi_configure(). This -- * .msi_host_init() function keeps us from doing the default MSI -- * domain setup in dw_pcie_host_init() and also enforces the -- * requirement that "msi-parent" exists. -- */ -- msi_node = of_parse_phandle(np, "msi-parent", 0); -- if (!msi_node) { -- dev_err(dev, "failed to find msi-parent\n"); -- return -EINVAL; -- } -- -- of_node_put(msi_node); -- return 0; --} -- - static const struct dw_pcie_host_ops ls1021_pcie_host_ops = { - .host_init = ls1021_pcie_host_init, -- .msi_host_init = ls_pcie_msi_host_init, - }; - - static const struct dw_pcie_host_ops ls_pcie_host_ops = { - .host_init = ls_pcie_host_init, -- .msi_host_init = ls_pcie_msi_host_init, - }; - - static const struct dw_pcie_ops dw_ls1021_pcie_ops = { ---- a/drivers/pci/controller/dwc/pcie-designware-host.c -+++ b/drivers/pci/controller/dwc/pcie-designware-host.c -@@ -358,6 +358,10 @@ int dw_pcie_host_init(struct pcie_port * - pci->link_gen = of_pci_get_max_link_speed(np); - - if (pci_msi_enabled()) { -+ pp->has_msi_ctrl = !(pp->ops->msi_host_init || -+ of_property_read_bool(np, "msi-parent") || -+ of_property_read_bool(np, "msi-map")); -+ - if (!pp->num_vectors) { - pp->num_vectors = MSI_DEF_NUM_VECTORS; - } else if (pp->num_vectors > MAX_MSI_IRQS) { -@@ -365,7 +369,11 @@ int dw_pcie_host_init(struct pcie_port * - return -EINVAL; - } - -- if (!pp->ops->msi_host_init) { -+ if (pp->ops->msi_host_init) { -+ ret = pp->ops->msi_host_init(pp); -+ if (ret < 0) -+ return ret; -+ } else if (pp->has_msi_ctrl) { - if (!pp->msi_irq) { - pp->msi_irq = platform_get_irq_byname_optional(pdev, "msi"); - if (pp->msi_irq < 0) { -@@ -396,10 +404,6 @@ int dw_pcie_host_init(struct pcie_port * - pp->msi_data = 0; - goto err_free_msi; - } -- } else { -- ret = pp->ops->msi_host_init(pp); -- if (ret < 0) -- return ret; - } - } - -@@ -420,7 +424,7 @@ int dw_pcie_host_init(struct pcie_port * - return 0; - - err_free_msi: -- if (pci_msi_enabled() && !pp->ops->msi_host_init) -+ if (pp->has_msi_ctrl) - dw_pcie_free_msi(pp); - return ret; - } -@@ -430,7 +434,7 @@ void dw_pcie_host_deinit(struct pcie_por - { - pci_stop_root_bus(pp->bridge->bus); - pci_remove_root_bus(pp->bridge->bus); -- if (pci_msi_enabled() && !pp->ops->msi_host_init) -+ if (pp->has_msi_ctrl) - dw_pcie_free_msi(pp); - } - EXPORT_SYMBOL_GPL(dw_pcie_host_deinit); -@@ -541,7 +545,7 @@ void dw_pcie_setup_rc(struct pcie_port * - - dw_pcie_setup(pci); - -- if (pci_msi_enabled() && !pp->ops->msi_host_init) { -+ if (pp->has_msi_ctrl) { - num_ctrls = pp->num_vectors / MAX_MSI_IRQS_PER_CTRL; - - /* Initialize IRQ Status array */ ---- a/drivers/pci/controller/dwc/pcie-designware.h -+++ b/drivers/pci/controller/dwc/pcie-designware.h -@@ -178,6 +178,7 @@ struct dw_pcie_host_ops { - }; - - struct pcie_port { -+ bool has_msi_ctrl:1; - u64 cfg0_base; - void __iomem *va_cfg0_base; - u32 cfg0_size; ---- a/drivers/pci/controller/dwc/pcie-intel-gw.c -+++ b/drivers/pci/controller/dwc/pcie-intel-gw.c -@@ -403,14 +403,6 @@ static int intel_pcie_rc_init(struct pci - return intel_pcie_host_setup(lpp); - } - --/* -- * Dummy function so that DW core doesn't configure MSI -- */ --static int intel_pcie_msi_init(struct pcie_port *pp) --{ -- return 0; --} -- - static u64 intel_pcie_cpu_addr(struct dw_pcie *pcie, u64 cpu_addr) - { - return cpu_addr + BUS_IATU_OFFSET; -@@ -422,7 +414,6 @@ static const struct dw_pcie_ops intel_pc - - static const struct dw_pcie_host_ops intel_pcie_dw_ops = { - .host_init = intel_pcie_rc_init, -- .msi_host_init = intel_pcie_msi_init, - }; - - static const struct intel_pcie_soc pcie_data = { diff --git a/target/linux/ipq807x/patches-5.10/013-v5.11-PCI-dwc-Move-link-handling-into-common-code.patch b/target/linux/ipq807x/patches-5.10/013-v5.11-PCI-dwc-Move-link-handling-into-common-code.patch deleted file mode 100644 index 383820e23..000000000 --- a/target/linux/ipq807x/patches-5.10/013-v5.11-PCI-dwc-Move-link-handling-into-common-code.patch +++ /dev/null @@ -1,603 +0,0 @@ -From 533bee2aeda70c212a3fb5547d5beb6406e3ccf7 Mon Sep 17 00:00:00 2001 -From: Rob Herring -Date: Thu, 5 Nov 2020 15:11:53 -0600 -Subject: [PATCH 4/5] PCI: dwc: Move link handling into common code - -All the DWC drivers do link setup and checks at roughly the same time. -Let's use the existing .start_link() hook (currently only used in EP -mode) and move the link handling to the core code. - -The behavior for a link down was inconsistent as some drivers would fail -probe in that case while others succeed. Let's standardize this to -succeed as there are usecases where devices (and the link) appear later -even without hotplug. For example, a reconfigured FPGA device. - -Link: https://lore.kernel.org/r/20201105211159.1814485-11-robh@kernel.org -Tested-by: Marek Szyprowski -Signed-off-by: Rob Herring -Signed-off-by: Lorenzo Pieralisi -Acked-by: Jingoo Han -Cc: Kishon Vijay Abraham I -Cc: Lorenzo Pieralisi -Cc: Bjorn Helgaas -Cc: Kukjin Kim -Cc: Krzysztof Kozlowski -Cc: Richard Zhu -Cc: Lucas Stach -Cc: Shawn Guo -Cc: Sascha Hauer -Cc: Pengutronix Kernel Team -Cc: Fabio Estevam -Cc: NXP Linux Team -Cc: Murali Karicheri -Cc: Yue Wang -Cc: Kevin Hilman -Cc: Neil Armstrong -Cc: Jerome Brunet -Cc: Martin Blumenstingl -Cc: Thomas Petazzoni -Cc: Jesper Nilsson -Cc: Gustavo Pimentel -Cc: Xiaowei Song -Cc: Binghui Wang -Cc: Andy Gross -Cc: Bjorn Andersson -Cc: Stanimir Varbanov -Cc: Pratyush Anand -Cc: Thierry Reding -Cc: Jonathan Hunter -Cc: Kunihiko Hayashi -Cc: Masahiro Yamada -Cc: linux-omap@vger.kernel.org -Cc: linux-samsung-soc@vger.kernel.org -Cc: linux-amlogic@lists.infradead.org -Cc: linux-arm-kernel@axis.com -Cc: linux-arm-msm@vger.kernel.org -Cc: linux-tegra@vger.kernel.org ---- - drivers/pci/controller/dwc/pci-dra7xx.c | 2 - - drivers/pci/controller/dwc/pci-exynos.c | 41 +++++++---------- - drivers/pci/controller/dwc/pci-imx6.c | 9 ++-- - drivers/pci/controller/dwc/pci-keystone.c | 9 ---- - drivers/pci/controller/dwc/pci-meson.c | 24 ++++------ - drivers/pci/controller/dwc/pcie-armada8k.c | 39 +++++++--------- - drivers/pci/controller/dwc/pcie-artpec6.c | 2 - - .../pci/controller/dwc/pcie-designware-host.c | 9 ++++ - .../pci/controller/dwc/pcie-designware-plat.c | 3 -- - drivers/pci/controller/dwc/pcie-histb.c | 34 +++++++------- - drivers/pci/controller/dwc/pcie-kirin.c | 23 ++-------- - drivers/pci/controller/dwc/pcie-qcom.c | 19 ++------ - drivers/pci/controller/dwc/pcie-spear13xx.c | 46 ++++++++----------- - drivers/pci/controller/dwc/pcie-tegra194.c | 1 - - drivers/pci/controller/dwc/pcie-uniphier.c | 13 ++---- - 15 files changed, 103 insertions(+), 171 deletions(-) - ---- a/drivers/pci/controller/dwc/pci-dra7xx.c -+++ b/drivers/pci/controller/dwc/pci-dra7xx.c -@@ -183,8 +183,6 @@ static int dra7xx_pcie_host_init(struct - - dw_pcie_setup_rc(pp); - -- dra7xx_pcie_establish_link(pci); -- dw_pcie_wait_for_link(pci); - dw_pcie_msi_init(pp); - dra7xx_pcie_enable_interrupts(dra7xx); - ---- a/drivers/pci/controller/dwc/pci-exynos.c -+++ b/drivers/pci/controller/dwc/pci-exynos.c -@@ -229,30 +229,9 @@ static void exynos_pcie_assert_reset(str - GPIOF_OUT_INIT_HIGH, "RESET"); - } - --static int exynos_pcie_establish_link(struct exynos_pcie *ep) -+static int exynos_pcie_start_link(struct dw_pcie *pci) - { -- struct dw_pcie *pci = ep->pci; -- struct pcie_port *pp = &pci->pp; -- struct device *dev = pci->dev; -- -- if (dw_pcie_link_up(pci)) { -- dev_err(dev, "Link already up\n"); -- return 0; -- } -- -- exynos_pcie_assert_core_reset(ep); -- -- phy_reset(ep->phy); -- -- exynos_pcie_writel(ep->mem_res->elbi_base, 1, -- PCIE_PWR_RESET); -- -- phy_power_on(ep->phy); -- phy_init(ep->phy); -- -- exynos_pcie_deassert_core_reset(ep); -- dw_pcie_setup_rc(pp); -- exynos_pcie_assert_reset(ep); -+ struct exynos_pcie *ep = to_exynos_pcie(pci); - - /* assert LTSSM enable */ - exynos_pcie_writel(ep->mem_res->elbi_base, PCIE_ELBI_LTSSM_ENABLE, -@@ -386,7 +365,20 @@ static int exynos_pcie_host_init(struct - - pp->bridge->ops = &exynos_pci_ops; - -- exynos_pcie_establish_link(ep); -+ exynos_pcie_assert_core_reset(ep); -+ -+ phy_reset(ep->phy); -+ -+ exynos_pcie_writel(ep->mem_res->elbi_base, 1, -+ PCIE_PWR_RESET); -+ -+ phy_power_on(ep->phy); -+ phy_init(ep->phy); -+ -+ exynos_pcie_deassert_core_reset(ep); -+ dw_pcie_setup_rc(pp); -+ exynos_pcie_assert_reset(ep); -+ - exynos_pcie_enable_interrupts(ep); - - return 0; -@@ -430,6 +422,7 @@ static const struct dw_pcie_ops dw_pcie_ - .read_dbi = exynos_pcie_read_dbi, - .write_dbi = exynos_pcie_write_dbi, - .link_up = exynos_pcie_link_up, -+ .start_link = exynos_pcie_start_link, - }; - - static int __init exynos_pcie_probe(struct platform_device *pdev) ---- a/drivers/pci/controller/dwc/pci-imx6.c -+++ b/drivers/pci/controller/dwc/pci-imx6.c -@@ -750,9 +750,9 @@ static void imx6_pcie_ltssm_enable(struc - } - } - --static int imx6_pcie_establish_link(struct imx6_pcie *imx6_pcie) -+static int imx6_pcie_start_link(struct dw_pcie *pci) - { -- struct dw_pcie *pci = imx6_pcie->pci; -+ struct imx6_pcie *imx6_pcie = to_imx6_pcie(pci); - struct device *dev = pci->dev; - u8 offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP); - u32 tmp; -@@ -840,7 +840,6 @@ static int imx6_pcie_host_init(struct pc - imx6_pcie_deassert_core_reset(imx6_pcie); - imx6_setup_phy_mpll(imx6_pcie); - dw_pcie_setup_rc(pp); -- imx6_pcie_establish_link(imx6_pcie); - dw_pcie_msi_init(pp); - - return 0; -@@ -870,7 +869,7 @@ static int imx6_add_pcie_port(struct imx - } - - static const struct dw_pcie_ops dw_pcie_ops = { -- /* No special ops needed, but pcie-designware still expects this struct */ -+ .start_link = imx6_pcie_start_link, - }; - - #ifdef CONFIG_PM_SLEEP -@@ -979,7 +978,7 @@ static int imx6_pcie_resume_noirq(struct - imx6_pcie_deassert_core_reset(imx6_pcie); - dw_pcie_setup_rc(pp); - -- ret = imx6_pcie_establish_link(imx6_pcie); -+ ret = imx6_pcie_start_link(imx6_pcie->pci); - if (ret < 0) - dev_info(dev, "pcie link is down after resume.\n"); - ---- a/drivers/pci/controller/dwc/pci-keystone.c -+++ b/drivers/pci/controller/dwc/pci-keystone.c -@@ -511,14 +511,8 @@ static void ks_pcie_stop_link(struct dw_ - static int ks_pcie_start_link(struct dw_pcie *pci) - { - struct keystone_pcie *ks_pcie = to_keystone_pcie(pci); -- struct device *dev = pci->dev; - u32 val; - -- if (dw_pcie_link_up(pci)) { -- dev_dbg(dev, "link is already up\n"); -- return 0; -- } -- - /* Initiate Link Training */ - val = ks_pcie_app_readl(ks_pcie, CMD_STATUS); - ks_pcie_app_writel(ks_pcie, CMD_STATUS, LTSSM_EN_VAL | val); -@@ -834,9 +828,6 @@ static int __init ks_pcie_host_init(stru - "Asynchronous external abort"); - #endif - -- ks_pcie_start_link(pci); -- dw_pcie_wait_for_link(pci); -- - return 0; - } - ---- a/drivers/pci/controller/dwc/pci-meson.c -+++ b/drivers/pci/controller/dwc/pci-meson.c -@@ -231,7 +231,7 @@ static void meson_pcie_assert_reset(stru - gpiod_set_value_cansleep(mp->reset_gpio, 0); - } - --static void meson_pcie_init_dw(struct meson_pcie *mp) -+static void meson_pcie_ltssm_enable(struct meson_pcie *mp) - { - u32 val; - -@@ -289,20 +289,14 @@ static void meson_set_max_rd_req_size(st - dw_pcie_writel_dbi(pci, offset + PCI_EXP_DEVCTL, val); - } - --static int meson_pcie_establish_link(struct meson_pcie *mp) -+static int meson_pcie_start_link(struct dw_pcie *pci) - { -- struct dw_pcie *pci = &mp->pci; -- struct pcie_port *pp = &pci->pp; -- -- meson_pcie_init_dw(mp); -- meson_set_max_payload(mp, MAX_PAYLOAD_SIZE); -- meson_set_max_rd_req_size(mp, MAX_READ_REQ_SIZE); -- -- dw_pcie_setup_rc(pp); -+ struct meson_pcie *mp = to_meson_pcie(pci); - -+ meson_pcie_ltssm_enable(mp); - meson_pcie_assert_reset(mp); - -- return dw_pcie_wait_for_link(pci); -+ return 0; - } - - static int meson_pcie_rd_own_conf(struct pci_bus *bus, u32 devfn, -@@ -380,14 +374,13 @@ static int meson_pcie_host_init(struct p - { - struct dw_pcie *pci = to_dw_pcie_from_pp(pp); - struct meson_pcie *mp = to_meson_pcie(pci); -- int ret; - - pp->bridge->ops = &meson_pci_ops; - -- ret = meson_pcie_establish_link(mp); -- if (ret) -- return ret; -+ meson_set_max_payload(mp, MAX_PAYLOAD_SIZE); -+ meson_set_max_rd_req_size(mp, MAX_READ_REQ_SIZE); - -+ dw_pcie_setup_rc(pp); - dw_pcie_msi_init(pp); - - return 0; -@@ -418,6 +411,7 @@ static int meson_add_pcie_port(struct me - - static const struct dw_pcie_ops dw_pcie_ops = { - .link_up = meson_pcie_link_up, -+ .start_link = meson_pcie_start_link, - }; - - static int meson_pcie_probe(struct platform_device *pdev) ---- a/drivers/pci/controller/dwc/pcie-armada8k.c -+++ b/drivers/pci/controller/dwc/pcie-armada8k.c -@@ -154,10 +154,24 @@ static int armada8k_pcie_link_up(struct - return 0; - } - --static void armada8k_pcie_establish_link(struct armada8k_pcie *pcie) -+static int armada8k_pcie_start_link(struct dw_pcie *pci) -+{ -+ u32 reg; -+ -+ /* Start LTSSM */ -+ reg = dw_pcie_readl_dbi(pci, PCIE_GLOBAL_CONTROL_REG); -+ reg |= PCIE_APP_LTSSM_EN; -+ dw_pcie_writel_dbi(pci, PCIE_GLOBAL_CONTROL_REG, reg); -+ -+ return 0; -+} -+ -+static int armada8k_pcie_host_init(struct pcie_port *pp) - { -- struct dw_pcie *pci = pcie->pci; - u32 reg; -+ struct dw_pcie *pci = to_dw_pcie_from_pp(pp); -+ -+ dw_pcie_setup_rc(pp); - - if (!dw_pcie_link_up(pci)) { - /* Disable LTSSM state machine to enable configuration */ -@@ -193,26 +207,6 @@ static void armada8k_pcie_establish_link - PCIE_INT_C_ASSERT_MASK | PCIE_INT_D_ASSERT_MASK; - dw_pcie_writel_dbi(pci, PCIE_GLOBAL_INT_MASK1_REG, reg); - -- if (!dw_pcie_link_up(pci)) { -- /* Configuration done. Start LTSSM */ -- reg = dw_pcie_readl_dbi(pci, PCIE_GLOBAL_CONTROL_REG); -- reg |= PCIE_APP_LTSSM_EN; -- dw_pcie_writel_dbi(pci, PCIE_GLOBAL_CONTROL_REG, reg); -- } -- -- /* Wait until the link becomes active again */ -- if (dw_pcie_wait_for_link(pci)) -- dev_err(pci->dev, "Link not up after reconfiguration\n"); --} -- --static int armada8k_pcie_host_init(struct pcie_port *pp) --{ -- struct dw_pcie *pci = to_dw_pcie_from_pp(pp); -- struct armada8k_pcie *pcie = to_armada8k_pcie(pci); -- -- dw_pcie_setup_rc(pp); -- armada8k_pcie_establish_link(pcie); -- - return 0; - } - -@@ -269,6 +263,7 @@ static int armada8k_add_pcie_port(struct - - static const struct dw_pcie_ops dw_pcie_ops = { - .link_up = armada8k_pcie_link_up, -+ .start_link = armada8k_pcie_start_link, - }; - - static int armada8k_pcie_probe(struct platform_device *pdev) ---- a/drivers/pci/controller/dwc/pcie-artpec6.c -+++ b/drivers/pci/controller/dwc/pcie-artpec6.c -@@ -329,8 +329,6 @@ static int artpec6_pcie_host_init(struct - artpec6_pcie_deassert_core_reset(artpec6_pcie); - artpec6_pcie_wait_for_phy(artpec6_pcie); - dw_pcie_setup_rc(pp); -- artpec6_pcie_establish_link(pci); -- dw_pcie_wait_for_link(pci); - dw_pcie_msi_init(pp); - - return 0; ---- a/drivers/pci/controller/dwc/pcie-designware-host.c -+++ b/drivers/pci/controller/dwc/pcie-designware-host.c -@@ -417,6 +417,15 @@ int dw_pcie_host_init(struct pcie_port * - goto err_free_msi; - } - -+ if (!dw_pcie_link_up(pci) && pci->ops->start_link) { -+ ret = pci->ops->start_link(pci); -+ if (ret) -+ goto err_free_msi; -+ } -+ -+ /* Ignore errors, the link may come up later */ -+ dw_pcie_wait_for_link(pci); -+ - bridge->sysdata = pp; - - ret = pci_host_probe(bridge); ---- a/drivers/pci/controller/dwc/pcie-designware-plat.c -+++ b/drivers/pci/controller/dwc/pcie-designware-plat.c -@@ -35,10 +35,7 @@ static const struct of_device_id dw_plat - - static int dw_plat_pcie_host_init(struct pcie_port *pp) - { -- struct dw_pcie *pci = to_dw_pcie_from_pp(pp); -- - dw_pcie_setup_rc(pp); -- dw_pcie_wait_for_link(pci); - dw_pcie_msi_init(pp); - - return 0; ---- a/drivers/pci/controller/dwc/pcie-histb.c -+++ b/drivers/pci/controller/dwc/pcie-histb.c -@@ -169,39 +169,36 @@ static int histb_pcie_link_up(struct dw_ - return 0; - } - --static int histb_pcie_establish_link(struct pcie_port *pp) -+static int histb_pcie_start_link(struct dw_pcie *pci) - { -- struct dw_pcie *pci = to_dw_pcie_from_pp(pp); - struct histb_pcie *hipcie = to_histb_pcie(pci); - u32 regval; - -- if (dw_pcie_link_up(pci)) { -- dev_info(pci->dev, "Link already up\n"); -- return 0; -- } -- -- /* PCIe RC work mode */ -- regval = histb_pcie_readl(hipcie, PCIE_SYS_CTRL0); -- regval &= ~PCIE_DEVICE_TYPE_MASK; -- regval |= PCIE_WM_RC; -- histb_pcie_writel(hipcie, PCIE_SYS_CTRL0, regval); -- -- /* setup root complex */ -- dw_pcie_setup_rc(pp); -- - /* assert LTSSM enable */ - regval = histb_pcie_readl(hipcie, PCIE_SYS_CTRL7); - regval |= PCIE_APP_LTSSM_ENABLE; - histb_pcie_writel(hipcie, PCIE_SYS_CTRL7, regval); - -- return dw_pcie_wait_for_link(pci); -+ return 0; - } - - static int histb_pcie_host_init(struct pcie_port *pp) - { -+ struct dw_pcie *pci = to_dw_pcie_from_pp(pp); -+ struct histb_pcie *hipcie = to_histb_pcie(pci); -+ u32 regval; -+ - pp->bridge->ops = &histb_pci_ops; - -- histb_pcie_establish_link(pp); -+ /* PCIe RC work mode */ -+ regval = histb_pcie_readl(hipcie, PCIE_SYS_CTRL0); -+ regval &= ~PCIE_DEVICE_TYPE_MASK; -+ regval |= PCIE_WM_RC; -+ histb_pcie_writel(hipcie, PCIE_SYS_CTRL0, regval); -+ -+ /* setup root complex */ -+ dw_pcie_setup_rc(pp); -+ - dw_pcie_msi_init(pp); - - return 0; -@@ -300,6 +297,7 @@ static const struct dw_pcie_ops dw_pcie_ - .read_dbi = histb_pcie_read_dbi, - .write_dbi = histb_pcie_write_dbi, - .link_up = histb_pcie_link_up, -+ .start_link = histb_pcie_start_link, - }; - - static int histb_pcie_probe(struct platform_device *pdev) ---- a/drivers/pci/controller/dwc/pcie-kirin.c -+++ b/drivers/pci/controller/dwc/pcie-kirin.c -@@ -395,32 +395,14 @@ static int kirin_pcie_link_up(struct dw_ - return 0; - } - --static int kirin_pcie_establish_link(struct pcie_port *pp) -+static int kirin_pcie_start_link(struct dw_pcie *pci) - { -- struct dw_pcie *pci = to_dw_pcie_from_pp(pp); - struct kirin_pcie *kirin_pcie = to_kirin_pcie(pci); -- struct device *dev = kirin_pcie->pci->dev; -- int count = 0; -- -- if (kirin_pcie_link_up(pci)) -- return 0; -- -- dw_pcie_setup_rc(pp); - - /* assert LTSSM enable */ - kirin_apb_ctrl_writel(kirin_pcie, PCIE_LTSSM_ENABLE_BIT, - PCIE_APP_LTSSM_ENABLE); - -- /* check if the link is up or not */ -- while (!kirin_pcie_link_up(pci)) { -- usleep_range(LINK_WAIT_MIN, LINK_WAIT_MAX); -- count++; -- if (count == 1000) { -- dev_err(dev, "Link Fail\n"); -- return -EINVAL; -- } -- } -- - return 0; - } - -@@ -428,7 +410,7 @@ static int kirin_pcie_host_init(struct p - { - pp->bridge->ops = &kirin_pci_ops; - -- kirin_pcie_establish_link(pp); -+ dw_pcie_setup_rc(pp); - dw_pcie_msi_init(pp); - - return 0; -@@ -438,6 +420,7 @@ static const struct dw_pcie_ops kirin_dw - .read_dbi = kirin_pcie_read_dbi, - .write_dbi = kirin_pcie_write_dbi, - .link_up = kirin_pcie_link_up, -+ .start_link = kirin_pcie_start_link, - }; - - static const struct dw_pcie_host_ops kirin_pcie_host_ops = { ---- a/drivers/pci/controller/dwc/pcie-qcom.c -+++ b/drivers/pci/controller/dwc/pcie-qcom.c -@@ -207,18 +207,15 @@ static void qcom_ep_reset_deassert(struc - usleep_range(PERST_DELAY_US, PERST_DELAY_US + 500); - } - --static int qcom_pcie_establish_link(struct qcom_pcie *pcie) -+static int qcom_pcie_start_link(struct dw_pcie *pci) - { -- struct dw_pcie *pci = pcie->pci; -- -- if (dw_pcie_link_up(pci)) -- return 0; -+ struct qcom_pcie *pcie = to_qcom_pcie(pci); - - /* Enable Link Training state machine */ - if (pcie->ops->ltssm_enable) - pcie->ops->ltssm_enable(pcie); - -- return dw_pcie_wait_for_link(pci); -+ return 0; - } - - static void qcom_pcie_2_1_0_ltssm_enable(struct qcom_pcie *pcie) -@@ -1280,15 +1277,8 @@ static int qcom_pcie_host_init(struct pc - - qcom_ep_reset_deassert(pcie); - -- ret = qcom_pcie_establish_link(pcie); -- if (ret) -- goto err; -- - return 0; --err: -- qcom_ep_reset_assert(pcie); -- if (pcie->ops->post_deinit) -- pcie->ops->post_deinit(pcie); -+ - err_disable_phy: - phy_power_off(pcie->phy); - err_deinit: -@@ -1355,6 +1345,7 @@ static const struct qcom_pcie_ops ops_2_ - - static const struct dw_pcie_ops dw_pcie_ops = { - .link_up = qcom_pcie_link_up, -+ .start_link = qcom_pcie_start_link, - }; - - static int qcom_pcie_probe(struct platform_device *pdev) ---- a/drivers/pci/controller/dwc/pcie-tegra194.c -+++ b/drivers/pci/controller/dwc/pcie-tegra194.c -@@ -1555,7 +1555,6 @@ static int tegra_pcie_deinit_controller( - - static int tegra_pcie_config_rp(struct tegra_pcie_dw *pcie) - { -- struct pcie_port *pp = &pcie->pci.pp; - struct device *dev = pcie->dev; - char *name; - int ret; ---- a/drivers/pci/controller/dwc/pcie-uniphier.c -+++ b/drivers/pci/controller/dwc/pcie-uniphier.c -@@ -146,16 +146,13 @@ static int uniphier_pcie_link_up(struct - return (val & mask) == mask; - } - --static int uniphier_pcie_establish_link(struct dw_pcie *pci) -+static int uniphier_pcie_start_link(struct dw_pcie *pci) - { - struct uniphier_pcie_priv *priv = to_uniphier_pcie(pci); - -- if (dw_pcie_link_up(pci)) -- return 0; -- - uniphier_pcie_ltssm_enable(priv, true); - -- return dw_pcie_wait_for_link(pci); -+ return 0; - } - - static void uniphier_pcie_stop_link(struct dw_pcie *pci) -@@ -312,10 +309,6 @@ static int uniphier_pcie_host_init(struc - uniphier_pcie_irq_enable(priv); - - dw_pcie_setup_rc(pp); -- ret = uniphier_pcie_establish_link(pci); -- if (ret) -- return ret; -- - dw_pcie_msi_init(pp); - - return 0; -@@ -379,7 +372,7 @@ out_clk_disable: - } - - static const struct dw_pcie_ops dw_pcie_ops = { -- .start_link = uniphier_pcie_establish_link, -+ .start_link = uniphier_pcie_start_link, - .stop_link = uniphier_pcie_stop_link, - .link_up = uniphier_pcie_link_up, - }; diff --git a/target/linux/ipq807x/patches-5.10/014-v5.11-PCI-dwc-Move-dw_pcie_msi_init-into-core.patch b/target/linux/ipq807x/patches-5.10/014-v5.11-PCI-dwc-Move-dw_pcie_msi_init-into-core.patch deleted file mode 100644 index 425f2ed80..000000000 --- a/target/linux/ipq807x/patches-5.10/014-v5.11-PCI-dwc-Move-dw_pcie_msi_init-into-core.patch +++ /dev/null @@ -1,272 +0,0 @@ -From 02c98d70da854cd4d145afe800194768c5eefe1d Mon Sep 17 00:00:00 2001 -From: Rob Herring -Date: Thu, 5 Nov 2020 15:11:54 -0600 -Subject: [PATCH 5/5] PCI: dwc: Move dw_pcie_msi_init() into core - -The host drivers which call dw_pcie_msi_init() are all the ones using -the built-in MSI controller, so let's move it into the common DWC code. - -Link: https://lore.kernel.org/r/20201105211159.1814485-12-robh@kernel.org -Tested-by: Marek Szyprowski -Signed-off-by: Rob Herring -Signed-off-by: Lorenzo Pieralisi -Acked-by: Jingoo Han -Cc: Kishon Vijay Abraham I -Cc: Lorenzo Pieralisi -Cc: Bjorn Helgaas -Cc: Kukjin Kim -Cc: Krzysztof Kozlowski -Cc: Richard Zhu -Cc: Lucas Stach -Cc: Shawn Guo -Cc: Sascha Hauer -Cc: Pengutronix Kernel Team -Cc: Fabio Estevam -Cc: NXP Linux Team -Cc: Yue Wang -Cc: Kevin Hilman -Cc: Neil Armstrong -Cc: Jerome Brunet -Cc: Martin Blumenstingl -Cc: Jesper Nilsson -Cc: Gustavo Pimentel -Cc: Xiaowei Song -Cc: Binghui Wang -Cc: Stanimir Varbanov -Cc: Andy Gross -Cc: Bjorn Andersson -Cc: Pratyush Anand -Cc: Thierry Reding -Cc: Jonathan Hunter -Cc: Kunihiko Hayashi -Cc: Masahiro Yamada -Cc: linux-omap@vger.kernel.org -Cc: linux-samsung-soc@vger.kernel.org -Cc: linux-amlogic@lists.infradead.org -Cc: linux-arm-kernel@axis.com -Cc: linux-arm-msm@vger.kernel.org -Cc: linux-tegra@vger.kernel.org ---- - drivers/pci/controller/dwc/pci-dra7xx.c | 2 -- - drivers/pci/controller/dwc/pci-exynos.c | 4 ---- - drivers/pci/controller/dwc/pci-imx6.c | 1 - - drivers/pci/controller/dwc/pci-meson.c | 1 - - drivers/pci/controller/dwc/pcie-artpec6.c | 1 - - drivers/pci/controller/dwc/pcie-designware-host.c | 9 +++++---- - drivers/pci/controller/dwc/pcie-designware-plat.c | 1 - - drivers/pci/controller/dwc/pcie-designware.h | 10 ---------- - drivers/pci/controller/dwc/pcie-histb.c | 2 -- - drivers/pci/controller/dwc/pcie-kirin.c | 1 - - drivers/pci/controller/dwc/pcie-qcom.c | 2 -- - drivers/pci/controller/dwc/pcie-spear13xx.c | 6 +----- - drivers/pci/controller/dwc/pcie-tegra194.c | 2 -- - drivers/pci/controller/dwc/pcie-uniphier.c | 1 - - 14 files changed, 6 insertions(+), 37 deletions(-) - ---- a/drivers/pci/controller/dwc/pci-dra7xx.c -+++ b/drivers/pci/controller/dwc/pci-dra7xx.c -@@ -182,8 +182,6 @@ static int dra7xx_pcie_host_init(struct - struct dra7xx_pcie *dra7xx = to_dra7xx_pcie(pci); - - dw_pcie_setup_rc(pp); -- -- dw_pcie_msi_init(pp); - dra7xx_pcie_enable_interrupts(dra7xx); - - return 0; ---- a/drivers/pci/controller/dwc/pci-exynos.c -+++ b/drivers/pci/controller/dwc/pci-exynos.c -@@ -273,12 +273,8 @@ static irqreturn_t exynos_pcie_irq_handl - - static void exynos_pcie_msi_init(struct exynos_pcie *ep) - { -- struct dw_pcie *pci = ep->pci; -- struct pcie_port *pp = &pci->pp; - u32 val; - -- dw_pcie_msi_init(pp); -- - /* enable MSI interrupt */ - val = exynos_pcie_readl(ep->mem_res->elbi_base, PCIE_IRQ_EN_LEVEL); - val |= IRQ_MSI_ENABLE; ---- a/drivers/pci/controller/dwc/pci-imx6.c -+++ b/drivers/pci/controller/dwc/pci-imx6.c -@@ -840,7 +840,6 @@ static int imx6_pcie_host_init(struct pc - imx6_pcie_deassert_core_reset(imx6_pcie); - imx6_setup_phy_mpll(imx6_pcie); - dw_pcie_setup_rc(pp); -- dw_pcie_msi_init(pp); - - return 0; - } ---- a/drivers/pci/controller/dwc/pci-meson.c -+++ b/drivers/pci/controller/dwc/pci-meson.c -@@ -381,7 +381,6 @@ static int meson_pcie_host_init(struct p - meson_set_max_rd_req_size(mp, MAX_READ_REQ_SIZE); - - dw_pcie_setup_rc(pp); -- dw_pcie_msi_init(pp); - - return 0; - } ---- a/drivers/pci/controller/dwc/pcie-artpec6.c -+++ b/drivers/pci/controller/dwc/pcie-artpec6.c -@@ -329,7 +329,6 @@ static int artpec6_pcie_host_init(struct - artpec6_pcie_deassert_core_reset(artpec6_pcie); - artpec6_pcie_wait_for_phy(artpec6_pcie); - dw_pcie_setup_rc(pp); -- dw_pcie_msi_init(pp); - - return 0; - } ---- a/drivers/pci/controller/dwc/pcie-designware-host.c -+++ b/drivers/pci/controller/dwc/pcie-designware-host.c -@@ -256,7 +256,7 @@ int dw_pcie_allocate_domains(struct pcie - return 0; - } - --void dw_pcie_free_msi(struct pcie_port *pp) -+static void dw_pcie_free_msi(struct pcie_port *pp) - { - if (pp->msi_irq) { - irq_set_chained_handler(pp->msi_irq, NULL); -@@ -275,19 +275,18 @@ void dw_pcie_free_msi(struct pcie_port * - } - } - --void dw_pcie_msi_init(struct pcie_port *pp) -+static void dw_pcie_msi_init(struct pcie_port *pp) - { - struct dw_pcie *pci = to_dw_pcie_from_pp(pp); - u64 msi_target = (u64)pp->msi_data; - -- if (!IS_ENABLED(CONFIG_PCI_MSI)) -+ if (!pci_msi_enabled() || !pp->has_msi_ctrl) - return; - - /* Program the msi_data */ - dw_pcie_writel_dbi(pci, PCIE_MSI_ADDR_LO, lower_32_bits(msi_target)); - dw_pcie_writel_dbi(pci, PCIE_MSI_ADDR_HI, upper_32_bits(msi_target)); - } --EXPORT_SYMBOL_GPL(dw_pcie_msi_init); - - int dw_pcie_host_init(struct pcie_port *pp) - { -@@ -417,6 +416,8 @@ int dw_pcie_host_init(struct pcie_port * - goto err_free_msi; - } - -+ dw_pcie_msi_init(pp); -+ - if (!dw_pcie_link_up(pci) && pci->ops->start_link) { - ret = pci->ops->start_link(pci); - if (ret) ---- a/drivers/pci/controller/dwc/pcie-designware-plat.c -+++ b/drivers/pci/controller/dwc/pcie-designware-plat.c -@@ -36,7 +36,6 @@ static const struct of_device_id dw_plat - static int dw_plat_pcie_host_init(struct pcie_port *pp) - { - dw_pcie_setup_rc(pp); -- dw_pcie_msi_init(pp); - - return 0; - } ---- a/drivers/pci/controller/dwc/pcie-designware.h -+++ b/drivers/pci/controller/dwc/pcie-designware.h -@@ -365,8 +365,6 @@ static inline void dw_pcie_dbi_ro_wr_dis - - #ifdef CONFIG_PCIE_DW_HOST - irqreturn_t dw_handle_msi_irq(struct pcie_port *pp); --void dw_pcie_msi_init(struct pcie_port *pp); --void dw_pcie_free_msi(struct pcie_port *pp); - void dw_pcie_setup_rc(struct pcie_port *pp); - int dw_pcie_host_init(struct pcie_port *pp); - void dw_pcie_host_deinit(struct pcie_port *pp); -@@ -379,14 +377,6 @@ static inline irqreturn_t dw_handle_msi_ - return IRQ_NONE; - } - --static inline void dw_pcie_msi_init(struct pcie_port *pp) --{ --} -- --static inline void dw_pcie_free_msi(struct pcie_port *pp) --{ --} -- - static inline void dw_pcie_setup_rc(struct pcie_port *pp) - { - } ---- a/drivers/pci/controller/dwc/pcie-histb.c -+++ b/drivers/pci/controller/dwc/pcie-histb.c -@@ -199,8 +199,6 @@ static int histb_pcie_host_init(struct p - /* setup root complex */ - dw_pcie_setup_rc(pp); - -- dw_pcie_msi_init(pp); -- - return 0; - } - ---- a/drivers/pci/controller/dwc/pcie-kirin.c -+++ b/drivers/pci/controller/dwc/pcie-kirin.c -@@ -411,7 +411,6 @@ static int kirin_pcie_host_init(struct p - pp->bridge->ops = &kirin_pci_ops; - - dw_pcie_setup_rc(pp); -- dw_pcie_msi_init(pp); - - return 0; - } ---- a/drivers/pci/controller/dwc/pcie-qcom.c -+++ b/drivers/pci/controller/dwc/pcie-qcom.c -@@ -1273,8 +1273,6 @@ static int qcom_pcie_host_init(struct pc - } - - dw_pcie_setup_rc(pp); -- dw_pcie_msi_init(pp); -- - qcom_ep_reset_deassert(pcie); - - return 0; ---- a/drivers/pci/controller/dwc/pcie-spear13xx.c -+++ b/drivers/pci/controller/dwc/pcie-spear13xx.c -@@ -124,16 +124,12 @@ static irqreturn_t spear13xx_pcie_irq_ha - - static void spear13xx_pcie_enable_interrupts(struct spear13xx_pcie *spear13xx_pcie) - { -- struct dw_pcie *pci = spear13xx_pcie->pci; -- struct pcie_port *pp = &pci->pp; - struct pcie_app_reg *app_reg = spear13xx_pcie->app_base; - - /* Enable MSI interrupt */ -- if (IS_ENABLED(CONFIG_PCI_MSI)) { -- dw_pcie_msi_init(pp); -+ if (IS_ENABLED(CONFIG_PCI_MSI)) - writel(readl(&app_reg->int_mask) | - MSI_CTRL_INT, &app_reg->int_mask); -- } - } - - static int spear13xx_pcie_link_up(struct dw_pcie *pci) ---- a/drivers/pci/controller/dwc/pcie-tegra194.c -+++ b/drivers/pci/controller/dwc/pcie-tegra194.c -@@ -767,8 +767,6 @@ static void tegra_pcie_enable_msi_interr - struct tegra_pcie_dw *pcie = to_tegra_pcie(pci); - u32 val; - -- dw_pcie_msi_init(pp); -- - /* Enable MSI interrupt generation */ - val = appl_readl(pcie, APPL_INTR_EN_L0_0); - val |= APPL_INTR_EN_L0_0_SYS_MSI_INTR_EN; ---- a/drivers/pci/controller/dwc/pcie-uniphier.c -+++ b/drivers/pci/controller/dwc/pcie-uniphier.c -@@ -309,7 +309,6 @@ static int uniphier_pcie_host_init(struc - uniphier_pcie_irq_enable(priv); - - dw_pcie_setup_rc(pp); -- dw_pcie_msi_init(pp); - - return 0; - } diff --git a/target/linux/ipq807x/patches-5.10/101-arm64-dts-ipq8074-add-crypto-nodes.patch b/target/linux/ipq807x/patches-5.10/101-arm64-dts-ipq8074-add-crypto-nodes.patch deleted file mode 100644 index e0c8f5f23..000000000 --- a/target/linux/ipq807x/patches-5.10/101-arm64-dts-ipq8074-add-crypto-nodes.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 69581d91675df8c0d9b5f746de7c2f3d73344280 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Tue, 11 May 2021 15:10:37 +0200 -Subject: [PATCH] arm64: dts: ipq8074: add crypto nodes - -IPQ8074 uses Qualcom QCE crypto engine v5.1 -which is already supported. - -So simply add nodes for its DMA and QCE itself. - -Signed-off-by: Robert Marko ---- - arch/arm64/boot/dts/qcom/ipq8074.dtsi | 24 ++++++++++++++++++++++++ - 1 file changed, 24 insertions(+) - ---- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -224,6 +224,30 @@ - }; - }; - -+ cryptobam: dma@704000 { -+ compatible = "qcom,bam-v1.7.0"; -+ reg = <0x00704000 0x20000>; -+ interrupts = ; -+ clocks = <&gcc GCC_CRYPTO_AHB_CLK>; -+ clock-names = "bam_clk"; -+ #dma-cells = <1>; -+ qcom,ee = <1>; -+ qcom,controlled-remotely = <1>; -+ status = "disabled"; -+ }; -+ -+ crypto: crypto@73a000 { -+ compatible = "qcom,crypto-v5.1"; -+ reg = <0x0073a000 0x6000>; -+ clocks = <&gcc GCC_CRYPTO_AHB_CLK>, -+ <&gcc GCC_CRYPTO_AXI_CLK>, -+ <&gcc GCC_CRYPTO_CLK>; -+ clock-names = "iface", "bus", "core"; -+ dmas = <&cryptobam 2>, <&cryptobam 3>; -+ dma-names = "rx", "tx"; -+ status = "disabled"; -+ }; -+ - tlmm: pinctrl@1000000 { - compatible = "qcom,ipq8074-pinctrl"; - reg = <0x01000000 0x300000>; diff --git a/target/linux/ipq807x/patches-5.10/102-arm64-dts-ipq8074-add-PRNG-node.patch b/target/linux/ipq807x/patches-5.10/102-arm64-dts-ipq8074-add-PRNG-node.patch deleted file mode 100644 index 585fe8884..000000000 --- a/target/linux/ipq807x/patches-5.10/102-arm64-dts-ipq8074-add-PRNG-node.patch +++ /dev/null @@ -1,30 +0,0 @@ -From ff46c62852e862ac360aeb1054180c8e715fbeb4 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Tue, 11 May 2021 15:23:53 +0200 -Subject: [PATCH] arm64: dts: ipq8074: add PRNG node - -PRNG insinde of IPQ8074 is already supported, -so simply add the node for it. - -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 -@@ -224,6 +224,14 @@ - }; - }; - -+ prng: rng@e3000 { -+ compatible = "qcom,prng-ee"; -+ reg = <0x000e3000 0x1000>; -+ clocks = <&gcc GCC_PRNG_AHB_CLK>; -+ clock-names = "core"; -+ status = "disabled"; -+ }; -+ - cryptobam: dma@704000 { - compatible = "qcom,bam-v1.7.0"; - reg = <0x00704000 0x20000>; diff --git a/target/linux/ipq807x/patches-5.10/103-remoteproc-qcom-Add-PRNG-proxy-clock.patch b/target/linux/ipq807x/patches-5.10/103-remoteproc-qcom-Add-PRNG-proxy-clock.patch deleted file mode 100644 index b8e842b30..000000000 --- a/target/linux/ipq807x/patches-5.10/103-remoteproc-qcom-Add-PRNG-proxy-clock.patch +++ /dev/null @@ -1,155 +0,0 @@ -From e0d3c4e232c2b29532f7b894485814782201fdd9 Mon Sep 17 00:00:00 2001 -From: Gokul Sriram Palanisamy -Date: Sat, 30 Jan 2021 10:50:05 +0530 -Subject: [PATCH 08/16] 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 */ -@@ -732,6 +741,7 @@ static int q6v5_wcss_stop(struct rproc * - return ret; - } - -+ clk_disable_unprepare(wcss->prng_clk); - qcom_q6v5_unprepare(&wcss->q6v5); - - return 0; -@@ -896,7 +906,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; - -@@ -986,7 +1010,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)) -@@ -1030,12 +1054,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; - } -@@ -1082,6 +1108,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, -@@ -1091,6 +1118,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/ipq807x/patches-5.10/104-remoteproc-qcom-Add-secure-PIL-support.patch b/target/linux/ipq807x/patches-5.10/104-remoteproc-qcom-Add-secure-PIL-support.patch deleted file mode 100644 index 1931b01e1..000000000 --- a/target/linux/ipq807x/patches-5.10/104-remoteproc-qcom-Add-secure-PIL-support.patch +++ /dev/null @@ -1,143 +0,0 @@ -From a6256ebbd66f3457e4a285b72b362d452bc6854f Mon Sep 17 00:00:00 2001 -From: Gokul Sriram Palanisamy -Date: Sat, 30 Jan 2021 10:50:06 +0530 -Subject: [PATCH 09/16] 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"); -@@ -717,6 +733,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); -@@ -741,6 +766,7 @@ static int q6v5_wcss_stop(struct rproc * - return ret; - } - -+pas_done: - clk_disable_unprepare(wcss->prng_clk); - qcom_q6v5_unprepare(&wcss->q6v5); - -@@ -764,9 +790,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; - -@@ -1032,6 +1064,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) { -@@ -1045,6 +1080,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) -@@ -1115,6 +1151,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/ipq807x/patches-5.10/105-remoteproc-qcom-Add-support-for-split-q6-m3-wlan-fir.patch b/target/linux/ipq807x/patches-5.10/105-remoteproc-qcom-Add-support-for-split-q6-m3-wlan-fir.patch deleted file mode 100644 index fd82c57b5..000000000 --- a/target/linux/ipq807x/patches-5.10/105-remoteproc-qcom-Add-support-for-split-q6-m3-wlan-fir.patch +++ /dev/null @@ -1,104 +0,0 @@ -From ea44aa0384fec6d6fcd5bf6bf52175628bad7319 Mon Sep 17 00:00:00 2001 -From: Gokul Sriram Palanisamy -Date: Sat, 30 Jan 2021 10:50:07 +0530 -Subject: [PATCH 10/16] 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; -@@ -788,8 +790,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, -@@ -1068,7 +1091,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; -@@ -1081,6 +1104,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) -@@ -1145,7 +1169,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, -@@ -1158,7 +1183,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/ipq807x/patches-5.10/106-remoteproc-qcom-Add-ssr-subdevice-identifier.patch b/target/linux/ipq807x/patches-5.10/106-remoteproc-qcom-Add-ssr-subdevice-identifier.patch deleted file mode 100644 index 9307a944a..000000000 --- a/target/linux/ipq807x/patches-5.10/106-remoteproc-qcom-Add-ssr-subdevice-identifier.patch +++ /dev/null @@ -1,24 +0,0 @@ -From dcfc2e3a3e346e0cad4c5b8707aaab96f4bbb59d Mon Sep 17 00:00:00 2001 -From: Gokul Sriram Palanisamy -Date: Sat, 30 Jan 2021 10:50:08 +0530 -Subject: [PATCH 11/16] 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 -@@ -1174,6 +1174,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/ipq807x/patches-5.10/107-remoteproc-qcom-Update-regmap-offsets-for-halt-regis.patch b/target/linux/ipq807x/patches-5.10/107-remoteproc-qcom-Update-regmap-offsets-for-halt-regis.patch deleted file mode 100644 index d844aa7cf..000000000 --- a/target/linux/ipq807x/patches-5.10/107-remoteproc-qcom-Update-regmap-offsets-for-halt-regis.patch +++ /dev/null @@ -1,80 +0,0 @@ -From 543a7093420b500a197fc64361084613f248f07a Mon Sep 17 00:00:00 2001 -From: Gokul Sriram Palanisamy -Date: Sat, 30 Jan 2021 10:50:09 +0530 -Subject: [PATCH 12/16] 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; -@@ -874,10 +875,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; -@@ -925,9 +929,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; - } -@@ -1174,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, -+ .bcr_reset_required = false, - .ssr_name = "q6wcss", - .ops = &q6v5_wcss_ipq8074_ops, - .requires_force_stop = true, -@@ -1188,6 +1193,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/ipq807x/patches-5.10/108-dt-bindings-clock-qcom-Add-reset-for-WCSSAON.patch b/target/linux/ipq807x/patches-5.10/108-dt-bindings-clock-qcom-Add-reset-for-WCSSAON.patch deleted file mode 100644 index 516273ffb..000000000 --- a/target/linux/ipq807x/patches-5.10/108-dt-bindings-clock-qcom-Add-reset-for-WCSSAON.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 12c7588316e1aceb3a4918896735e8bc3757815f Mon Sep 17 00:00:00 2001 -From: Gokul Sriram Palanisamy -Date: Sat, 30 Jan 2021 10:50:10 +0530 -Subject: [PATCH 13/16] 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 -@@ -366,5 +366,6 @@ - #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 - - #endif diff --git a/target/linux/ipq807x/patches-5.10/109-clk-qcom-Add-WCSSAON-reset.patch b/target/linux/ipq807x/patches-5.10/109-clk-qcom-Add-WCSSAON-reset.patch deleted file mode 100644 index b2a95f91d..000000000 --- a/target/linux/ipq807x/patches-5.10/109-clk-qcom-Add-WCSSAON-reset.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 6de5e246382d6b15f297cadbf26bdd78ee7f9fea Mon Sep 17 00:00:00 2001 -From: Gokul Sriram Palanisamy -Date: Sat, 30 Jan 2021 10:50:11 +0530 -Subject: [PATCH 14/16] 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 -@@ -4784,6 +4784,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 const struct of_device_id gcc_ipq8074_match_table[] = { diff --git a/target/linux/ipq807x/patches-5.10/110-arm64-dts-Add-support-for-scm-on-IPQ8074-SoCs.patch b/target/linux/ipq807x/patches-5.10/110-arm64-dts-Add-support-for-scm-on-IPQ8074-SoCs.patch deleted file mode 100644 index 6dbabf1ce..000000000 --- a/target/linux/ipq807x/patches-5.10/110-arm64-dts-Add-support-for-scm-on-IPQ8074-SoCs.patch +++ /dev/null @@ -1,28 +0,0 @@ -From b177148d326cac30723f5fe9c939db2919aab33a Mon Sep 17 00:00:00 2001 -From: Gokul Sriram Palanisamy -Date: Sat, 30 Jan 2021 10:50:12 +0530 -Subject: [PATCH 15/16] arm64: dts: Add support for scm on IPQ8074 SoCs - -Enables scm support, clock is not needed for enabling scm interface. - -Signed-off-by: Gokul Sriram Palanisamy -Signed-off-by: Sricharan R ---- - arch/arm64/boot/dts/qcom/ipq8074.dtsi | 6 ++++++ - 1 file changed, 6 insertions(+) - ---- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -76,6 +76,12 @@ - method = "smc"; - }; - -+ firmware { -+ scm { -+ compatible = "qcom,scm-ipq8074", "qcom,scm"; -+ }; -+ }; -+ - soc: soc { - #address-cells = <0x1>; - #size-cells = <0x1>; diff --git a/target/linux/ipq807x/patches-5.10/111-arm64-dts-qcom-Enable-Q6v5-WCSS-for-ipq8074-SoC.patch b/target/linux/ipq807x/patches-5.10/111-arm64-dts-qcom-Enable-Q6v5-WCSS-for-ipq8074-SoC.patch deleted file mode 100644 index a9df195e9..000000000 --- a/target/linux/ipq807x/patches-5.10/111-arm64-dts-qcom-Enable-Q6v5-WCSS-for-ipq8074-SoC.patch +++ /dev/null @@ -1,158 +0,0 @@ -From 9428cd325c99212b25407df8035284012d65acdb Mon Sep 17 00:00:00 2001 -From: Gokul Sriram Palanisamy -Date: Sat, 30 Jan 2021 10:50:13 +0530 -Subject: [PATCH 16/16] arm64: dts: qcom: Enable Q6v5 WCSS for ipq8074 SoC - -Enable remoteproc WCSS PIL driver with glink -and ssr subdevices. Also configures shared memory -and enables smp2p and mailboxes required for IPC. - -Signed-off-by: Gokul Sriram Palanisamy -Signed-off-by: Sricharan R -Signed-off-by: Nikhil Prakash V ---- - arch/arm64/boot/dts/qcom/ipq8074.dtsi | 121 ++++++++++++++++++++++++++ - 1 file changed, 121 insertions(+) - ---- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -76,12 +76,66 @@ - method = "smc"; - }; - -+ reserved-memory { -+ #address-cells = <2>; -+ #size-cells = <2>; -+ ranges; -+ -+ smem_region: memory@4ab00000 { -+ no-map; -+ reg = <0x0 0x4ab00000 0x0 0x00100000>; -+ }; -+ -+ q6_region: memory@4b000000 { -+ no-map; -+ reg = <0x0 0x4b000000 0x0 0x05f00000>; -+ }; -+ }; -+ - firmware { - scm { - compatible = "qcom,scm-ipq8074", "qcom,scm"; - }; - }; - -+ tcsr_mutex: hwlock@193d000 { -+ compatible = "qcom,tcsr-mutex"; -+ syscon = <&tcsr_mutex_regs 0 0x80>; -+ #hwlock-cells = <1>; -+ }; -+ -+ smem { -+ compatible = "qcom,smem"; -+ memory-region = <&smem_region>; -+ hwlocks = <&tcsr_mutex 0>; -+ }; -+ -+ 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>; -@@ -754,5 +808,72 @@ - "axi_s_sticky"; - status = "disabled"; - }; -+ -+ tcsr_q6: syscon@1945000 { -+ compatible = "syscon"; -+ reg = <0x01945000 0xe000>; -+ }; -+ -+ tcsr_mutex_regs: syscon@193d000 { -+ compatible = "syscon"; -+ reg = <0x01905000 0x8000>; -+ }; -+ -+ apcs_glb: mailbox@b111000 { -+ compatible = "qcom,ipq8074-apcs-apps-global"; -+ reg = <0x0b111000 0x1000>; -+ -+ #mbox-cells = <1>; -+ }; -+ -+ 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"; -+ }; -+ }; -+ }; - }; - }; diff --git a/target/linux/ipq807x/patches-5.10/112-qcom-socinfo-Add-IPQ8074-SoC-family-ID-s.patch b/target/linux/ipq807x/patches-5.10/112-qcom-socinfo-Add-IPQ8074-SoC-family-ID-s.patch deleted file mode 100644 index 5fa58dbc4..000000000 --- a/target/linux/ipq807x/patches-5.10/112-qcom-socinfo-Add-IPQ8074-SoC-family-ID-s.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 5454294f432c0c095f3e2b54fd45491be779c545 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Tue, 11 May 2021 18:11:13 +0200 -Subject: [PATCH] soc: qcom: socinfo: Add IPQ8074 SoC family ID-s - -Add ID-s for the Qualcomm IPQ8074 SoC family. - -Signed-off-by: Robert Marko ---- - drivers/soc/qcom/socinfo.c | 12 ++++++++++++ - 1 file changed, 12 insertions(+) - ---- a/drivers/soc/qcom/socinfo.c -+++ b/drivers/soc/qcom/socinfo.c -@@ -224,8 +224,20 @@ static const struct soc_id soc_id[] = { - { 312, "APQ8096SG" }, - { 318, "SDM630" }, - { 321, "SDM845" }, -+ { 323, "IPQ8074" }, - { 341, "SDA845" }, -+ { 342, "IPQ8072" }, -+ { 343, "IPQ8076" }, -+ { 344, "IPQ8078" }, - { 356, "SM8250" }, -+ { 375, "IPQ8070" }, -+ { 376, "IPQ8071" }, -+ { 389, "IPQ8072A" }, -+ { 390, "IPQ8074A" }, -+ { 391, "IPQ8076A" }, -+ { 392, "IPQ8078A" }, -+ { 395, "IPQ8070A" }, -+ { 396, "IPQ8071A" }, - { 402, "IPQ6018" }, - { 425, "SC7180" }, - }; diff --git a/target/linux/ipq807x/patches-5.10/113-net-mdio-ipq4019-add-clock-handling.patch b/target/linux/ipq807x/patches-5.10/113-net-mdio-ipq4019-add-clock-handling.patch deleted file mode 100644 index 0476c6f23..000000000 --- a/target/linux/ipq807x/patches-5.10/113-net-mdio-ipq4019-add-clock-handling.patch +++ /dev/null @@ -1,49 +0,0 @@ -From d91c466ec19e5ced30631cec703164c79525b986 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Sun, 27 Dec 2020 18:55:56 +0100 -Subject: [PATCH] net: mdio-ipq4019: add clock handling - -Newer SoC-s like IPQ807x and IPQ60xx use the same MDIO controller, -but have separate MDIO clocks that need to be handled. -So lets add support for doing that. - -Signed-off-by: Robert Marko ---- - drivers/net/mdio/mdio-ipq4019.c | 12 ++++++++++++ - 1 file changed, 12 insertions(+) - ---- a/drivers/net/mdio/mdio-ipq4019.c -+++ b/drivers/net/mdio/mdio-ipq4019.c -@@ -2,6 +2,7 @@ - /* Copyright (c) 2015, The Linux Foundation. All rights reserved. */ - /* Copyright (c) 2020 Sartura Ltd. */ - -+#include - #include - #include - #include -@@ -33,6 +34,7 @@ - - struct ipq4019_mdio_data { - void __iomem *membase; -+ struct clk *clk; - }; - - static int ipq4019_mdio_wait_busy(struct mii_bus *bus) -@@ -187,6 +189,16 @@ static int ipq4019_mdio_probe(struct pla - if (IS_ERR(priv->membase)) - return PTR_ERR(priv->membase); - -+ priv->clk = devm_clk_get_optional(&pdev->dev, "mdio_ahb"); -+ if (IS_ERR(priv->clk)) { -+ dev_err(&pdev->dev, "Failed getting clock!\n"); -+ return PTR_ERR(priv->clk); -+ } -+ -+ ret = clk_prepare_enable(priv->clk); -+ if (ret) -+ return ret; -+ - bus->name = "ipq4019_mdio"; - bus->read = ipq4019_mdio_read; - bus->write = ipq4019_mdio_write; diff --git a/target/linux/ipq807x/patches-5.10/114-arm64-dts-ipq8074-Add-MDIO-support.patch b/target/linux/ipq807x/patches-5.10/114-arm64-dts-ipq8074-Add-MDIO-support.patch deleted file mode 100644 index 88811d353..000000000 --- a/target/linux/ipq807x/patches-5.10/114-arm64-dts-ipq8074-Add-MDIO-support.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 67ba6e563928123fc65dab604592a60da2cce648 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Tue, 11 May 2021 18:24:35 +0200 -Subject: [PATCH] arm64: dts: ipq8074: Add MDIO support - -MDIO controller is the same one as in IPQ4019, so -lets add the node to support it. - -Signed-off-by: Robert Marko ---- - 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 -@@ -284,6 +284,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 = "mdio_ahb"; -+ -+ status = "disabled"; -+ }; -+ - prng: rng@e3000 { - compatible = "qcom,prng-ee"; - reg = <0x000e3000 0x1000>; diff --git a/target/linux/ipq807x/patches-5.10/115-phy-qcom-qmp-Add-IPQ8074-PCIe-Gen3-QMP-PHY-support.patch b/target/linux/ipq807x/patches-5.10/115-phy-qcom-qmp-Add-IPQ8074-PCIe-Gen3-QMP-PHY-support.patch deleted file mode 100644 index f2e45f2f4..000000000 --- a/target/linux/ipq807x/patches-5.10/115-phy-qcom-qmp-Add-IPQ8074-PCIe-Gen3-QMP-PHY-support.patch +++ /dev/null @@ -1,369 +0,0 @@ -From 57887b141d68224dcf4039a2f5215011f43dd9f4 Mon Sep 17 00:00:00 2001 -From: Sivaprakash Murugesan -Date: Wed, 29 Jul 2020 21:00:04 +0530 -Subject: [PATCH] phy: qcom-qmp: Add IPQ8074 PCIe Gen3 QMP PHY support - -IPQ8074 has two PCIe ports, One Gen2 and one Gen3 port. -Since support for Gen2 PHY is already available, add support for -PCIe Gen3 PHY. - -Co-developed-by: Selvam Sathappan Periakaruppan -Signed-off-by: Selvam Sathappan Periakaruppan -Signed-off-by: Sivaprakash Murugesan -Signed-off-by: Robert Marko ---- - drivers/phy/qualcomm/phy-qcom-pcie3-qmp.h | 139 ++++++++++++++++++ - drivers/phy/qualcomm/phy-qcom-qmp.c | 171 +++++++++++++++++++++- - 2 files changed, 308 insertions(+), 2 deletions(-) - create mode 100644 drivers/phy/qualcomm/phy-qcom-pcie3-qmp.h - ---- /dev/null -+++ b/drivers/phy/qualcomm/phy-qcom-pcie3-qmp.h -@@ -0,0 +1,139 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+ -+/* -+ * Copyright (c) 2020, The Linux Foundation. All rights reserved. -+ */ -+ -+#ifndef PHY_QCOM_PCIE_H -+#define PHY_QCOM_PCIE_H -+ -+/* QMP V2 PCIE PHY - Found in IPQ8074 gen3 port - QSERDES PLL registers */ -+#define QSERDES_PLL_BG_TIMER 0x00c -+#define QSERDES_PLL_SSC_PER1 0x01c -+#define QSERDES_PLL_SSC_PER2 0x020 -+#define QSERDES_PLL_SSC_STEP_SIZE1_MODE0 0x024 -+#define QSERDES_PLL_SSC_STEP_SIZE2_MODE0 0x028 -+#define QSERDES_PLL_SSC_STEP_SIZE1_MODE1 0x02c -+#define QSERDES_PLL_SSC_STEP_SIZE2_MODE1 0x030 -+#define QSERDES_PLL_BIAS_EN_CLKBUFLR_EN 0x03c -+#define QSERDES_PLL_CLK_ENABLE1 0x040 -+#define QSERDES_PLL_SYS_CLK_CTRL 0x044 -+#define QSERDES_PLL_SYSCLK_BUF_ENABLE 0x048 -+#define QSERDES_PLL_PLL_IVCO 0x050 -+#define QSERDES_PLL_LOCK_CMP1_MODE0 0x054 -+#define QSERDES_PLL_LOCK_CMP2_MODE0 0x058 -+#define QSERDES_PLL_LOCK_CMP1_MODE1 0x060 -+#define QSERDES_PLL_LOCK_CMP2_MODE1 0x064 -+#define QSERDES_PLL_BG_TRIM 0x074 -+#define QSERDES_PLL_CLK_EP_DIV_MODE0 0x078 -+#define QSERDES_PLL_CLK_EP_DIV_MODE1 0x07c -+#define QSERDES_PLL_CP_CTRL_MODE0 0x080 -+#define QSERDES_PLL_CP_CTRL_MODE1 0x084 -+#define QSERDES_PLL_PLL_RCTRL_MODE0 0x088 -+#define QSERDES_PLL_PLL_RCTRL_MODE1 0x08C -+#define QSERDES_PLL_PLL_CCTRL_MODE0 0x090 -+#define QSERDES_PLL_PLL_CCTRL_MODE1 0x094 -+#define QSERDES_PLL_BIAS_EN_CTRL_BY_PSM 0x0a4 -+#define QSERDES_PLL_SYSCLK_EN_SEL 0x0a8 -+#define QSERDES_PLL_RESETSM_CNTRL 0x0b0 -+#define QSERDES_PLL_LOCK_CMP_EN 0x0c4 -+#define QSERDES_PLL_DEC_START_MODE0 0x0cc -+#define QSERDES_PLL_DEC_START_MODE1 0x0d0 -+#define QSERDES_PLL_DIV_FRAC_START1_MODE0 0x0d8 -+#define QSERDES_PLL_DIV_FRAC_START2_MODE0 0x0dc -+#define QSERDES_PLL_DIV_FRAC_START3_MODE0 0x0e0 -+#define QSERDES_PLL_DIV_FRAC_START1_MODE1 0x0e4 -+#define QSERDES_PLL_DIV_FRAC_START2_MODE1 0x0e8 -+#define QSERDES_PLL_DIV_FRAC_START3_MODE1 0x0eC -+#define QSERDES_PLL_INTEGLOOP_GAIN0_MODE0 0x100 -+#define QSERDES_PLL_INTEGLOOP_GAIN1_MODE0 0x104 -+#define QSERDES_PLL_INTEGLOOP_GAIN0_MODE1 0x108 -+#define QSERDES_PLL_INTEGLOOP_GAIN1_MODE1 0x10c -+#define QSERDES_PLL_VCO_TUNE_MAP 0x120 -+#define QSERDES_PLL_VCO_TUNE1_MODE0 0x124 -+#define QSERDES_PLL_VCO_TUNE2_MODE0 0x128 -+#define QSERDES_PLL_VCO_TUNE1_MODE1 0x12c -+#define QSERDES_PLL_VCO_TUNE2_MODE1 0x130 -+#define QSERDES_PLL_VCO_TUNE_TIMER1 0x13c -+#define QSERDES_PLL_VCO_TUNE_TIMER2 0x140 -+#define QSERDES_PLL_CLK_SELECT 0x16c -+#define QSERDES_PLL_HSCLK_SEL 0x170 -+#define QSERDES_PLL_CORECLK_DIV 0x17c -+#define QSERDES_PLL_CORE_CLK_EN 0x184 -+#define QSERDES_PLL_CMN_CONFIG 0x18c -+#define QSERDES_PLL_SVS_MODE_CLK_SEL 0x194 -+#define QSERDES_PLL_CORECLK_DIV_MODE1 0x1b4 -+ -+/* QMP V2 PCIE PHY - Found in IPQ8074 gen3 port - - QSERDES TX registers */ -+#define QSERDES_TX0_RES_CODE_LANE_OFFSET_TX 0x03c -+#define QSERDES_TX0_HIGHZ_DRVR_EN 0x058 -+#define QSERDES_TX0_LANE_MODE_1 0x084 -+#define QSERDES_TX0_RCV_DETECT_LVL_2 0x09c -+ -+/* QMP V2 PCIE PHY - Found in IPQ8074 gen3 port - QSERDES RX registers */ -+#define QSERDES_RX0_UCDR_FO_GAIN 0x008 -+#define QSERDES_RX0_UCDR_SO_GAIN 0x014 -+#define QSERDES_RX0_UCDR_SO_SATURATION_AND_ENABLE 0x034 -+#define QSERDES_RX0_UCDR_PI_CONTROLS 0x044 -+#define QSERDES_RX0_RX_EQU_ADAPTOR_CNTRL2 0x0ec -+#define QSERDES_RX0_RX_EQU_ADAPTOR_CNTRL3 0x0f0 -+#define QSERDES_RX0_RX_EQU_ADAPTOR_CNTRL4 0x0f4 -+#define QSERDES_RX0_RX_IDAC_TSETTLE_LOW 0x0f8 -+#define QSERDES_RX0_RX_IDAC_TSETTLE_HIGH 0x0fc -+#define QSERDES_RX0_RX_EQ_OFFSET_ADAPTOR_CNTRL1 0x110 -+#define QSERDES_RX0_RX_OFFSET_ADAPTOR_CNTRL2 0x114 -+#define QSERDES_RX0_SIGDET_ENABLES 0x118 -+#define QSERDES_RX0_SIGDET_CNTRL 0x11c -+#define QSERDES_RX0_SIGDET_DEGLITCH_CNTRL 0x124 -+#define QSERDES_RX0_RX_MODE_00_LOW 0x170 -+#define QSERDES_RX0_RX_MODE_00_HIGH 0x174 -+#define QSERDES_RX0_RX_MODE_00_HIGH2 0x178 -+#define QSERDES_RX0_RX_MODE_00_HIGH3 0x17c -+#define QSERDES_RX0_RX_MODE_00_HIGH4 0x180 -+#define QSERDES_RX0_RX_MODE_01_LOW 0x184 -+#define QSERDES_RX0_RX_MODE_01_HIGH 0x188 -+#define QSERDES_RX0_RX_MODE_01_HIGH2 0x18c -+#define QSERDES_RX0_RX_MODE_01_HIGH3 0x190 -+#define QSERDES_RX0_RX_MODE_01_HIGH4 0x194 -+#define QSERDES_RX0_RX_MODE_10_LOW 0x198 -+#define QSERDES_RX0_RX_MODE_10_HIGH 0x19c -+#define QSERDES_RX0_RX_MODE_10_HIGH2 0x1a0 -+#define QSERDES_RX0_RX_MODE_10_HIGH3 0x1a4 -+#define QSERDES_RX0_RX_MODE_10_HIGH4 0x1a8 -+#define QSERDES_RX0_DFE_EN_TIMER 0x1b4 -+ -+/* QMP V2 PCIE PHY - Found in IPQ8074 gen3 port - PCS registers */ -+ -+#define PCS_COM_FLL_CNTRL1 0x098 -+#define PCS_COM_FLL_CNTRL2 0x09c -+#define PCS_COM_FLL_CNT_VAL_L 0x0a0 -+#define PCS_COM_FLL_CNT_VAL_H_TOL 0x0a4 -+#define PCS_COM_FLL_MAN_CODE 0x0a8 -+#define PCS_COM_REFGEN_REQ_CONFIG1 0x0dc -+#define PCS_COM_G12S1_TXDEEMPH_M3P5DB 0x16c -+#define PCS_COM_RX_SIGDET_LVL 0x188 -+#define PCS_COM_P2U3_WAKEUP_DLY_TIME_AUXCLK_L 0x1a4 -+#define PCS_COM_P2U3_WAKEUP_DLY_TIME_AUXCLK_H 0x1a8 -+#define PCS_COM_RX_DCC_CAL_CONFIG 0x1d8 -+#define PCS_COM_EQ_CONFIG5 0x1ec -+ -+/* QMP V2 PCIE PHY - Found in IPQ8074 gen3 port - PCS Misc registers */ -+ -+#define PCS_PCIE_POWER_STATE_CONFIG2 0x40c -+#define PCS_PCIE_POWER_STATE_CONFIG4 0x414 -+#define PCS_PCIE_ENDPOINT_REFCLK_DRIVE 0x41c -+#define PCS_PCIE_L1P1_WAKEUP_DLY_TIME_AUXCLK_L 0x440 -+#define PCS_PCIE_L1P1_WAKEUP_DLY_TIME_AUXCLK_H 0x444 -+#define PCS_PCIE_L1P2_WAKEUP_DLY_TIME_AUXCLK_L 0x448 -+#define PCS_PCIE_L1P2_WAKEUP_DLY_TIME_AUXCLK_H 0x44c -+#define PCS_PCIE_OSC_DTCT_CONFIG2 0x45c -+#define PCS_PCIE_OSC_DTCT_MODE2_CONFIG2 0x478 -+#define PCS_PCIE_OSC_DTCT_MODE2_CONFIG4 0x480 -+#define PCS_PCIE_OSC_DTCT_MODE2_CONFIG5 0x484 -+#define PCS_PCIE_OSC_DTCT_ACTIONS 0x490 -+#define PCS_PCIE_EQ_CONFIG1 0x4a0 -+#define PCS_PCIE_EQ_CONFIG2 0x4a4 -+#define PCS_PCIE_PRESET_P10_PRE 0x4bc -+#define PCS_PCIE_PRESET_P10_POST 0x4e0 -+ -+#endif ---- a/drivers/phy/qualcomm/phy-qcom-qmp.c -+++ b/drivers/phy/qualcomm/phy-qcom-qmp.c -@@ -23,6 +23,7 @@ - #include - - #include "phy-qcom-qmp.h" -+#include "phy-qcom-pcie3-qmp.h" - - /* QPHY_SW_RESET bit */ - #define SW_RESET BIT(0) -@@ -676,6 +677,132 @@ 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), -@@ -2187,6 +2314,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 = qmp_v4_usb3phy_regs_layout, -+ -+ .start_ctrl = SERDES_START | PCS_START, -+ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, -+ -+ .has_phy_com_ctrl = false, -+ .has_lane_rst = false, -+ .has_pwrdn_delay = true, -+ .pwrdn_delay_min = 995, /* us */ -+ .pwrdn_delay_max = 1005, /* us */ -+}; -+ - static const struct qmp_phy_cfg sdm845_qmp_pciephy_cfg = { - .type = PHY_TYPE_PCIE, - .nlanes = 1, -@@ -3476,8 +3633,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 phys use 125MHz pipe clock interface unless -+ * other frequency is specified in dts -+ */ -+ ret = of_property_read_u32(np, "clock-output-rate", -+ (u32 *)&fixed->fixed_rate); -+ if (ret) -+ fixed->fixed_rate = 125000000; -+ - fixed->hw.init = &init; - - ret = devm_clk_hw_register(qmp->dev, &fixed->hw); -@@ -3868,6 +4032,9 @@ static const struct of_device_id qcom_qm - .compatible = "qcom,ipq8074-qmp-pcie-phy", - .data = &ipq8074_pciephy_cfg, - }, { -+ .compatible = "qcom,ipq8074-qmp-pcie-gen3-phy", -+ .data = &ipq8074_pciephy_gen3_cfg, -+ }, { - .compatible = "qcom,sc7180-qmp-usb3-phy", - .data = &sc7180_usb3phy_cfg, - }, { diff --git a/target/linux/ipq807x/patches-5.10/116-PCI-dwc-tegra-move-GEN3_RELATED-DBI-register-to-comm.patch b/target/linux/ipq807x/patches-5.10/116-PCI-dwc-tegra-move-GEN3_RELATED-DBI-register-to-comm.patch deleted file mode 100644 index 3a6f10e21..000000000 --- a/target/linux/ipq807x/patches-5.10/116-PCI-dwc-tegra-move-GEN3_RELATED-DBI-register-to-comm.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 35df745d335bd21094f522dc9dff7eaae92114d9 Mon Sep 17 00:00:00 2001 -From: Baruch Siach -Date: Wed, 5 May 2021 12:18:29 +0300 -Subject: [PATCH] PCI: dwc: tegra: move GEN3_RELATED DBI register to common - header - -These are common dwc macros that will be used for other platforms. - -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/ipq807x/patches-5.10/117-PCI-qcom-add-support-for-IPQ60xx-PCIe-controller.patch b/target/linux/ipq807x/patches-5.10/117-PCI-qcom-add-support-for-IPQ60xx-PCIe-controller.patch deleted file mode 100644 index 8aa63c477..000000000 --- a/target/linux/ipq807x/patches-5.10/117-PCI-qcom-add-support-for-IPQ60xx-PCIe-controller.patch +++ /dev/null @@ -1,230 +0,0 @@ -From 809a720946f720dca2009bac29294992375a31b9 Mon Sep 17 00:00:00 2001 -From: Selvam Sathappan Periakaruppan -Date: Tue, 11 May 2021 21:53:08 +0200 -Subject: [PATCH] PCI: qcom: add support for IPQ60xx PCIe controller - -IPQ60xx series of SoCs have one port of PCIe gen 3. Add support for that -platform. - -The code is based on downstream Codeaurora kernel v5.4. Split out the -DBI registers access part from .init into .post_init. DBI registers are -only accessible after phy_power_on(). - -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 | 150 +++++++++++++++++++ - 2 files changed, 151 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 -@@ -51,6 +51,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 -@@ -92,6 +96,12 @@ - #define SLV_ADDR_SPACE_SZ 0x10000000 - - #define PCIE20_LNK_CONTROL2_LINK_STATUS2 0xa0 -+#define PCIE_CAP_CURR_DEEMPHASIS BIT(16) -+#define SPEED_GEN1 0x1 -+#define SPEED_GEN2 0x2 -+#define SPEED_GEN3 0x3 -+#define AXI_CLK_RATE 200000000 -+#define RCHNG_CLK_RATE 100000000 - - #define DEVICE_TYPE_RC 0x4 - -@@ -161,6 +171,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; -@@ -168,6 +183,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; -@@ -1242,6 +1258,130 @@ 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; -+ } -+ -+ usleep_range(2000, 2500); -+ -+ ret = reset_control_deassert(res->rst); -+ if (ret) { -+ dev_err(dev, "reset deassert failed (%d)\n", ret); -+ return ret; -+ } -+ -+ /* -+ * Don't have a way to see if the reset has completed. -+ * Wait for some time. -+ */ -+ usleep_range(2000, 2500); -+ -+ ret = clk_bulk_prepare_enable(ARRAY_SIZE(res->clks), res->clks); -+ if (ret) -+ goto err_reset; -+ -+ return 0; -+ -+ /* -+ * Not checking for failure, will anyway return -+ * the original failure in 'ret'. -+ */ -+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_LINK1_VAL, pci->dbi_base + offset + PCI_EXP_SLTCAP); -+ -+ /* Configure PCIe link capabilities for ASPM */ -+ 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); -+ -+ writel(PCIE_CAP_CURR_DEEMPHASIS | SPEED_GEN3, -+ 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); -@@ -1341,6 +1481,15 @@ static const struct qcom_pcie_ops ops_2_ - .post_deinit = qcom_pcie_post_deinit_2_7_0, - }; - -+/* 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, -@@ -1446,6 +1595,7 @@ static const struct of_device_id qcom_pc - { .compatible = "qcom,pcie-ipq4019", .data = &ops_2_4_0 }, - { .compatible = "qcom,pcie-qcs404", .data = &ops_2_4_0 }, - { .compatible = "qcom,pcie-sdm845", .data = &ops_2_7_0 }, -+ { .compatible = "qcom,pcie-ipq6018", .data = &ops_2_9_0 }, - { } - }; - diff --git a/target/linux/ipq807x/patches-5.10/119-qcom-backport-register-define.patch b/target/linux/ipq807x/patches-5.10/119-qcom-backport-register-define.patch deleted file mode 100644 index b1e5c82f3..000000000 --- a/target/linux/ipq807x/patches-5.10/119-qcom-backport-register-define.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 5d3f9ed5a9eb305a2531015cc65200d48be5dbf4 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Tue, 11 May 2021 22:21:57 +0200 -Subject: [PATCH 1/2] PCI: qcom: backport register define - -This is used by the pending IPQ6018 PCI support which -uses the same Gen3 IP and the one we are reusing for -IPQ8074. - -Without it compilation will break. - -Signed-off-by: Robert Marko ---- - drivers/pci/controller/dwc/pcie-qcom.c | 1 + - 1 file changed, 1 insertion(+) - ---- a/drivers/pci/controller/dwc/pcie-qcom.c -+++ b/drivers/pci/controller/dwc/pcie-qcom.c -@@ -61,6 +61,7 @@ - #define PCIE20_PARF_SID_OFFSET 0x234 - #define PCIE20_PARF_BDF_TRANSLATE_CFG 0x24C - #define PCIE20_PARF_DEVICE_TYPE 0x1000 -+#define PCIE20_PARF_BDF_TO_SID_TABLE_N 0x2000 - - #define PCIE20_ELBI_SYS_CTRL 0x04 - #define PCIE20_ELBI_SYS_CTRL_LT_ENABLE BIT(0) diff --git a/target/linux/ipq807x/patches-5.10/120-PCI-qcom-Add-IPQ8074-PCIe-Gen3-support.patch b/target/linux/ipq807x/patches-5.10/120-PCI-qcom-Add-IPQ8074-PCIe-Gen3-support.patch deleted file mode 100644 index 7eecc9b6f..000000000 --- a/target/linux/ipq807x/patches-5.10/120-PCI-qcom-Add-IPQ8074-PCIe-Gen3-support.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 9467e9860e72d7351b24dc6d77f0e9fe141ce166 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Wed, 26 May 2021 16:06:32 +0200 -Subject: [PATCH] PCI: qcom: Add IPQ8074 PCIe Gen3 support - -IPQ6018 uses the same v2.9.0 IP for the Gen3 PCIe -controller. - -So, lets reuse that and add clocks that the IPQ6018 -patch missed. - -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 -@@ -173,7 +173,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; - }; - -@@ -1269,8 +1269,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) -@@ -1597,6 +1599,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-ipq6018", .data = &ops_2_9_0 }, -+ { .compatible = "qcom,pcie-ipq8074-gen3", .data = &ops_2_9_0 }, - { } - }; - diff --git a/target/linux/ipq807x/patches-5.10/122-arm64-uaccess-include-scheduler.h.patch b/target/linux/ipq807x/patches-5.10/122-arm64-uaccess-include-scheduler.h.patch deleted file mode 100644 index 40244b080..000000000 --- a/target/linux/ipq807x/patches-5.10/122-arm64-uaccess-include-scheduler.h.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 5fcad0d86d985b068eb97e55b55f7be87cd1b008 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Wed, 12 May 2021 17:01:29 +0200 -Subject: [PATCH] arm64: uaccess: include scheduler.h - -Qualcomm SSDK exposed a bug in which the uaccess is -using a struct and header definition that are not -included. - -So, simply: #include to fix it. - -Signed-off-by: Robert Marko ---- - arch/arm64/include/asm/uaccess.h | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/arch/arm64/include/asm/uaccess.h -+++ b/arch/arm64/include/asm/uaccess.h -@@ -24,6 +24,8 @@ - #include - #include - -+#include -+ - #define get_fs() (current_thread_info()->addr_limit) - - static inline void set_fs(mm_segment_t fs) diff --git a/target/linux/ipq807x/patches-5.10/123-arm64-dts-ipq8074-add-networking-nodes.patch b/target/linux/ipq807x/patches-5.10/123-arm64-dts-ipq8074-add-networking-nodes.patch deleted file mode 100644 index f5b3a676c..000000000 --- a/target/linux/ipq807x/patches-5.10/123-arm64-dts-ipq8074-add-networking-nodes.patch +++ /dev/null @@ -1,170 +0,0 @@ -From f581e7b004d0d997acc1f0fa5b2c454f90f0b2de Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Wed, 12 May 2021 18:49:30 +0200 -Subject: [PATCH] arm64: dts: ipq8074: add networking nodes - -Add networking nodes required for SSDK and NSS-DP. - -Signed-off-by: Robert Marko ---- - arch/arm64/boot/dts/qcom/ipq8074.dtsi | 150 ++++++++++++++++++++++++++ - 1 file changed, 150 insertions(+) - ---- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -887,5 +887,155 @@ - }; - }; - }; -+ -+ ess_switch: ess-switch@3a000000 { -+ compatible = "qcom,ess-switch-ipq807x"; -+ reg = <0x3a000000 0x1000000>; -+ switch_access_mode = "local bus"; -+ switch_cpu_bmp = <0x1>; /* cpu port bitmap */ -+ switch_inner_bmp = <0x80>; /*inner port bitmap*/ -+ mdio-bus = <&mdio>; -+ 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_UNIPHY2_AHB_CLK>, -+ <&gcc GCC_UNIPHY2_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_PORT6_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_NSS_PPE_BTQ_CLK>, -+ <&gcc GCC_NSS_NOC_CLK>, -+ <&gcc GCC_NSSNOC_SNOC_CLK>, -+ <&gcc GCC_MEM_NOC_NSS_AXI_CLK>, -+ <&gcc GCC_NSS_CRYPTO_CLK>, -+ <&gcc GCC_NSS_IMEM_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_NSS_PORT6_RX_CLK>, -+ <&gcc GCC_NSS_PORT6_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 GCC_UNIPHY2_PORT6_RX_CLK>, -+ <&gcc GCC_UNIPHY2_PORT6_TX_CLK>, -+ <&gcc NSS_PORT5_RX_CLK_SRC>, -+ <&gcc NSS_PORT5_TX_CLK_SRC>; -+ clock-names = "cmn_ahb_clk", "cmn_sys_clk", -+ "uniphy0_ahb_clk", "uniphy0_sys_clk", -+ "uniphy1_ahb_clk", "uniphy1_sys_clk", -+ "uniphy2_ahb_clk", "uniphy2_sys_clk", -+ "port1_mac_clk", "port2_mac_clk", -+ "port3_mac_clk", "port4_mac_clk", -+ "port5_mac_clk", "port6_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", "nss_ppe_btq_clk", -+ "gcc_nss_noc_clk", -+ "gcc_nssnoc_snoc_clk", -+ "gcc_mem_noc_nss_axi_clk", -+ "gcc_nss_crypto_clk", -+ "gcc_nss_imem_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", -+ "nss_port6_rx_clk", "nss_port6_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", -+ "uniphy2_port6_rx_clk", -+ "uniphy2_port6_tx_clk", -+ "nss_port5_rx_clk_src", -+ "nss_port5_tx_clk_src"; -+ 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_UNIPHY2_SOFT_RESET>, -+ <&gcc GCC_UNIPHY2_XPCS_RESET>, -+ <&gcc GCC_NSSPORT1_RESET>, -+ <&gcc GCC_NSSPORT2_RESET>, -+ <&gcc GCC_NSSPORT3_RESET>, -+ <&gcc GCC_NSSPORT4_RESET>, -+ <&gcc GCC_NSSPORT5_RESET>, -+ <&gcc GCC_NSSPORT6_RESET>; -+ reset-names = "ppe_rst", "uniphy0_soft_rst", -+ "uniphy0_xpcs_rst", "uniphy1_soft_rst", -+ "uniphy1_xpcs_rst", "uniphy2_soft_rst", -+ "uniphy2_xpcs_rst", "nss_port1_rst", -+ "nss_port2_rst", "nss_port3_rst", -+ "nss_port4_rst", "nss_port5_rst", -+ "nss_port6_rst"; -+ }; -+ -+ ess-uniphy@7a00000 { -+ compatible = "qcom,ess-uniphy"; -+ reg = <0x7a00000 0x30000>; -+ uniphy_access_mode = "local bus"; -+ }; -+ -+ edma@3ab00000 { -+ compatible = "qcom,edma"; -+ reg = <0x3ab00000 0x76900>; -+ reg-names = "edma-reg-base"; -+ qcom,txdesc-ring-start = <23>; -+ qcom,txdesc-rings = <1>; -+ qcom,txcmpl-ring-start = <7>; -+ 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"; -+ }; - }; - }; diff --git a/target/linux/ipq807x/patches-5.10/125-ipq8074-gcc-Added-support-for-NSS-clocks.patch b/target/linux/ipq807x/patches-5.10/125-ipq8074-gcc-Added-support-for-NSS-clocks.patch deleted file mode 100644 index eae85eb55..000000000 --- a/target/linux/ipq807x/patches-5.10/125-ipq8074-gcc-Added-support-for-NSS-clocks.patch +++ /dev/null @@ -1,79 +0,0 @@ -From 4f579facd45c39f8f8b9993570944f4d83a95955 Mon Sep 17 00:00:00 2001 -From: Praveenkumar I -Date: Wed, 5 Feb 2020 10:13:01 +0530 -Subject: [PATCH 2/8] ipq8074: gcc: Added support for NSS clocks - -Change-Id: I446e84dbc3498618425677811a73124b99b5c0ad -Signed-off-by: Praveenkumar I -Signed-off-by: Rajkumar Ayyasamy ---- - arch/arm64/boot/dts/qcom/ipq8074.dtsi | 12 ++++ - drivers/clk/qcom/gcc-ipq8074.c | 68 +++++++++++++++++++- - include/dt-bindings/clock/qcom,gcc-ipq8074.h | 1 + - 3 files changed, 80 insertions(+), 1 deletion(-) - ---- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -1037,5 +1037,17 @@ - resets = <&gcc GCC_EDMA_HW_RESET>; - reset-names = "edma_rst"; - }; -+ -+ 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>; -+ }; - }; - }; ---- 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 = { -@@ -4602,6 +4620,7 @@ static struct clk_regmap *gcc_ipq8074_cl - [GCC_CMN_12GPLL_AHB_CLK] = &gcc_cmn_12gpll_ahb_clk.clkr, - [GCC_CMN_12GPLL_SYS_CLK] = &gcc_cmn_12gpll_sys_clk.clkr, - [GCC_MDIO_AHB_CLK] = &gcc_mdio_ahb_clk.clkr, -+ [GCC_CRYPTO_PPE_CLK] = &gcc_crypto_ppe_clk.clkr, - [GCC_UNIPHY0_AHB_CLK] = &gcc_uniphy0_ahb_clk.clkr, - [GCC_UNIPHY0_SYS_CLK] = &gcc_uniphy0_sys_clk.clkr, - [GCC_UNIPHY1_AHB_CLK] = &gcc_uniphy1_ahb_clk.clkr, ---- 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/ipq807x/patches-5.10/126-clk-ipq8074-Support-added-for-necessary-clocks-and-r.patch b/target/linux/ipq807x/patches-5.10/126-clk-ipq8074-Support-added-for-necessary-clocks-and-r.patch deleted file mode 100644 index 5f7238dae..000000000 --- a/target/linux/ipq807x/patches-5.10/126-clk-ipq8074-Support-added-for-necessary-clocks-and-r.patch +++ /dev/null @@ -1,352 +0,0 @@ -From 6504bc9edeb1a2a54d813f4bb5d0267e7bf827f9 Mon Sep 17 00:00:00 2001 -From: Praveenkumar I -Date: Thu, 6 Feb 2020 17:35:42 +0530 -Subject: [PATCH 4/8] clk: ipq8074: Support added for necessary clocks and - reset - -Change-Id: I21a76a44185f766e9b6dcba274392ea8e599718b -Signed-off-by: Praveenkumar I -Signed-off-by: Rajkumar Ayyasamy ---- - drivers/clk/qcom/gcc-ipq8074.c | 238 ++++++++++++++++++- - include/dt-bindings/clock/qcom,gcc-ipq8074.h | 35 ++- - 2 files changed, 258 insertions(+), 15 deletions(-) - ---- a/drivers/clk/qcom/gcc-ipq8074.c -+++ b/drivers/clk/qcom/gcc-ipq8074.c -@@ -391,6 +391,22 @@ static const struct parent_map gcc_xo_gp - { P_SLEEP_CLK, 6 }, - }; - -+static const char * const gcc_xo_gpll4_gpll0_gpll6_gpll0_div2[] = { -+ "xo", -+ "gpll4", -+ "gpll0", -+ "gpll6", -+ "gpll0_out_main_div2", -+}; -+ -+static const struct parent_map gcc_xo_gpll4_gpll0_gpll6_gpll0_div2_map[] = { -+ { P_XO, 0 }, -+ { P_GPLL4, 1 }, -+ { P_GPLL0, 2 }, -+ { P_GPLL6, 3 }, -+ { P_GPLL0_DIV2, 4 }, -+}; -+ - static struct clk_alpha_pll gpll0_main = { - .offset = 0x21000, - .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], -@@ -957,6 +973,12 @@ static const struct freq_tbl ftbl_pcie_a - { } - }; - -+struct freq_tbl ftbl_pcie_rchng_clk_src[] = { -+ F(19200000, P_XO, 1, 0, 0), -+ F(100000000, P_GPLL0, 8, 0, 0), -+ { } -+}; -+ - static struct clk_rcg2 pcie0_axi_clk_src = { - .cmd_rcgr = 0x75054, - .freq_tbl = ftbl_pcie_axi_clk_src, -@@ -2016,6 +2038,78 @@ static struct clk_rcg2 gp3_clk_src = { - }, - }; - -+struct freq_tbl ftbl_qdss_tsctr_clk_src[] = { -+ F(160000000, P_GPLL0_DIV2, 2.5, 0, 0), -+ F(320000000, P_GPLL0, 2.5, 0, 0), -+ F(600000000, P_GPLL6, 2, 0, 0), -+ { } -+}; -+ -+struct clk_rcg2 qdss_tsctr_clk_src = { -+ .cmd_rcgr = 0x29064, -+ .freq_tbl = ftbl_qdss_tsctr_clk_src, -+ .hid_width = 5, -+ .parent_map = gcc_xo_gpll4_gpll0_gpll6_gpll0_div2_map, -+ .clkr.hw.init = &(struct clk_init_data){ -+ .name = "qdss_tsctr_clk_src", -+ .parent_names = gcc_xo_gpll4_gpll0_gpll6_gpll0_div2, -+ .num_parents = 5, -+ .ops = &clk_rcg2_ops, -+ }, -+}; -+ -+static struct clk_fixed_factor qdss_dap_sync_clk_src = { -+ .mult = 1, -+ .div = 4, -+ .hw.init = &(struct clk_init_data){ -+ .name = "qdss_dap_sync_clk_src", -+ .parent_names = (const char *[]){ -+ "qdss_tsctr_clk_src" -+ }, -+ .num_parents = 1, -+ .ops = &clk_fixed_factor_ops, -+ }, -+}; -+ -+struct freq_tbl ftbl_qdss_at_clk_src[] = { -+ F(66670000, P_GPLL0_DIV2, 6, 0, 0), -+ F(240000000, P_GPLL6, 6, 0, 0), -+ { } -+}; -+ -+struct clk_rcg2 qdss_at_clk_src = { -+ .cmd_rcgr = 0x2900c, -+ .freq_tbl = ftbl_qdss_at_clk_src, -+ .hid_width = 5, -+ .parent_map = gcc_xo_gpll4_gpll0_gpll6_gpll0_div2_map, -+ .clkr.hw.init = &(struct clk_init_data){ -+ .name = "qdss_at_clk_src", -+ .parent_names = gcc_xo_gpll4_gpll0_gpll6_gpll0_div2, -+ .num_parents = 5, -+ .ops = &clk_rcg2_ops, -+ }, -+}; -+ -+ -+struct freq_tbl ftbl_adss_pwm_clk_src[] = { -+ F(19200000, P_XO, 1, 0, 0), -+ F(200000000, P_GPLL0, 4, 0, 0), -+ { } -+}; -+ -+struct clk_rcg2 adss_pwm_clk_src = { -+ .cmd_rcgr = 0x1c008, -+ .freq_tbl = ftbl_adss_pwm_clk_src, -+ .hid_width = 5, -+ .parent_map = gcc_xo_gpll0_map, -+ .clkr.hw.init = &(struct clk_init_data){ -+ .name = "adss_pwm_clk_src", -+ .parent_data = gcc_xo_gpll0, -+ .num_parents = 2, -+ .ops = &clk_rcg2_ops, -+ }, -+}; -+ - static struct clk_branch gcc_blsp1_ahb_clk = { - .halt_reg = 0x01008, - .clkr = { -@@ -4347,13 +4441,7 @@ static struct clk_branch gcc_gp3_clk = { - }, - }; - --static const struct freq_tbl ftbl_pcie_rchng_clk_src[] = { -- F(19200000, P_XO, 1, 0, 0), -- F(100000000, P_GPLL0, 8, 0, 0), -- { } --}; -- --static struct clk_rcg2 pcie0_rchng_clk_src = { -+struct clk_rcg2 pcie0_rchng_clk_src = { - .cmd_rcgr = 0x75070, - .freq_tbl = ftbl_pcie_rchng_clk_src, - .hid_width = 5, -@@ -4429,6 +4517,114 @@ static const struct alpha_pll_config nss - .alpha_en_mask = BIT(24), - }; - -+static struct clk_branch gcc_snoc_bus_timeout2_ahb_clk = { -+ .halt_reg = 0x4700c, -+ .halt_bit = 31, -+ .clkr = { -+ .enable_reg = 0x4700c, -+ .enable_mask = BIT(0), -+ .hw.init = &(struct clk_init_data){ -+ .name = "gcc_snoc_bus_timeout2_ahb_clk", -+ .parent_names = (const char *[]){ -+ "usb0_master_clk_src" -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch gcc_snoc_bus_timeout3_ahb_clk = { -+ .halt_reg = 0x47014, -+ .halt_bit = 31, -+ .clkr = { -+ .enable_reg = 0x47014, -+ .enable_mask = BIT(0), -+ .hw.init = &(struct clk_init_data){ -+ .name = "gcc_snoc_bus_timeout3_ahb_clk", -+ .parent_names = (const char *[]){ -+ "usb1_master_clk_src" -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch gcc_dcc_clk = { -+ .halt_reg = 0x77004, -+ .halt_bit = 31, -+ .clkr = { -+ .enable_reg = 0x77004, -+ .enable_mask = BIT(0), -+ .hw.init = &(struct clk_init_data){ -+ .name = "gcc_dcc_clk", -+ .parent_names = (const char *[]){ -+ "pcnoc_clk_src" -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch gcc_qdss_at_clk = { -+ .halt_reg = 0x29024, -+ .halt_bit = 31, -+ .clkr = { -+ .enable_reg = 0x29024, -+ .enable_mask = BIT(0), -+ .hw.init = &(struct clk_init_data){ -+ .name = "gcc_qdss_at_clk", -+ .parent_names = (const char *[]){ -+ "qdss_at_clk_src" -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch gcc_qdss_dap_clk = { -+ .halt_reg = 0x29084, -+ .halt_bit = 31, -+ .clkr = { -+ .enable_reg = 0x29084, -+ .enable_mask = BIT(0), -+ .hw.init = &(struct clk_init_data){ -+ .name = "gcc_qdss_dap_clk", -+ .parent_names = (const char *[]){ -+ "qdss_dap_sync_clk_src" -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch gcc_adss_pwm_clk = { -+ .halt_reg = 0x1c020, -+ .halt_bit = 31, -+ .clkr = { -+ .enable_reg = 0x1c020, -+ .enable_mask = BIT(0), -+ .hw.init = &(struct clk_init_data){ -+ .name = "gcc_adss_pwm_clk", -+ .parent_names = (const char *[]){ -+ "adss_pwm_clk_src" -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ - static struct clk_hw *gcc_ipq8074_hws[] = { - &gpll0_out_main_div2.hw, - &gpll6_out_main_div2.hw, -@@ -4437,6 +4633,7 @@ static struct clk_hw *gcc_ipq8074_hws[] - &gcc_xo_div4_clk_src.hw, - &nss_noc_clk_src.hw, - &nss_ppe_cdiv_clk_src.hw, -+ &qdss_dap_sync_clk_src.hw, - }; - - static struct clk_regmap *gcc_ipq8074_clks[] = { -@@ -4668,6 +4865,15 @@ 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_SNOC_BUS_TIMEOUT2_AHB_CLK] = &gcc_snoc_bus_timeout2_ahb_clk.clkr, -+ [GCC_SNOC_BUS_TIMEOUT3_AHB_CLK] = &gcc_snoc_bus_timeout3_ahb_clk.clkr, -+ [GCC_DCC_CLK] = &gcc_dcc_clk.clkr, -+ [QDSS_TSCTR_CLK_SRC] = &qdss_tsctr_clk_src.clkr, -+ [QDSS_AT_CLK_SRC] = &qdss_at_clk_src.clkr, -+ [GCC_QDSS_AT_CLK] = &gcc_qdss_at_clk.clkr, -+ [GCC_QDSS_DAP_CLK] = &gcc_qdss_dap_clk.clkr, -+ [ADSS_PWM_CLK_SRC] = &adss_pwm_clk_src.clkr, -+ [GCC_ADSS_PWM_CLK] = &gcc_adss_pwm_clk.clkr, - }; - - static const struct qcom_reset_map gcc_ipq8074_resets[] = { -@@ -4804,6 +5010,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, 0xf0000}, -+ [GCC_UNIPHY0_SOFT_RESET] = { 0x56004, 0, 0x3ff2}, -+ [GCC_UNIPHY0_XPCS_RESET] = { 0x56004, 2 }, -+ [GCC_UNIPHY1_SOFT_RESET] = { 0x56104, 0, 0x32}, -+ [GCC_UNIPHY1_XPCS_RESET] = { 0x56104, 2 }, -+ [GCC_UNIPHY2_SOFT_RESET] = { 0x56204, 0, 0x32}, -+ [GCC_UNIPHY2_XPCS_RESET] = { 0x56204, 2 }, -+ [GCC_EDMA_HW_RESET] = { 0x68014, 0, 0x300000}, -+ [GCC_NSSPORT1_RESET] = { 0x68014, 0, 0x1000003}, -+ [GCC_NSSPORT2_RESET] = { 0x68014, 0, 0x200000c}, -+ [GCC_NSSPORT3_RESET] = { 0x68014, 0, 0x4000030}, -+ [GCC_NSSPORT4_RESET] = { 0x68014, 0, 0x8000300}, -+ [GCC_NSSPORT5_RESET] = { 0x68014, 0, 0x10000c00}, -+ [GCC_NSSPORT6_RESET] = { 0x68014, 0, 0x20003000}, - }; - - static const struct of_device_id gcc_ipq8074_match_table[] = { ---- a/include/dt-bindings/clock/qcom,gcc-ipq8074.h -+++ b/include/dt-bindings/clock/qcom,gcc-ipq8074.h -@@ -230,10 +230,19 @@ - #define GCC_GP1_CLK 221 - #define GCC_GP2_CLK 222 - #define GCC_GP3_CLK 223 --#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_CRYPTO_PPE_CLK 224 -+#define GCC_PCIE0_RCHNG_CLK_SRC 225 -+#define GCC_PCIE0_RCHNG_CLK 226 -+#define GCC_PCIE0_AXI_S_BRIDGE_CLK 227 -+#define GCC_SNOC_BUS_TIMEOUT2_AHB_CLK 228 -+#define GCC_SNOC_BUS_TIMEOUT3_AHB_CLK 229 -+#define GCC_DCC_CLK 230 -+#define ADSS_PWM_CLK_SRC 231 -+#define GCC_ADSS_PWM_CLK 232 -+#define QDSS_TSCTR_CLK_SRC 233 -+#define QDSS_AT_CLK_SRC 234 -+#define GCC_QDSS_AT_CLK 235 -+#define GCC_QDSS_DAP_CLK 236 - - #define GCC_BLSP1_BCR 0 - #define GCC_BLSP1_QUP1_BCR 1 -@@ -368,5 +377,19 @@ - #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 - - #endif diff --git a/target/linux/ipq807x/patches-5.10/127-clk-qcom-ipq8074-Fix-gcc_snoc_bus_timeout_ahb_clk-of.patch b/target/linux/ipq807x/patches-5.10/127-clk-qcom-ipq8074-Fix-gcc_snoc_bus_timeout_ahb_clk-of.patch deleted file mode 100644 index 2bf82f5da..000000000 --- a/target/linux/ipq807x/patches-5.10/127-clk-qcom-ipq8074-Fix-gcc_snoc_bus_timeout_ahb_clk-of.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 462aa0c53397ec5bf78e3e7f68aa8a3ca300f4ba Mon Sep 17 00:00:00 2001 -From: Selvam Sathappan Periakaruppan -Date: Tue, 24 Mar 2020 19:09:38 +0530 -Subject: [PATCH 5/8] clk: qcom: ipq8074: Fix gcc_snoc_bus_timeout_ahb_clk - offset - -By default, the ipq8074 V2 clks are provided in the gcc driver. -Updating the gcc_snoc_bus_timeout_ahb_clk offsets also as needed -in ipq8074 V2. - -Change-Id: I5a6e98d002f5c3354a804e55dd9ebb1f83f7f974 -Signed-off-by: Selvam Sathappan Periakaruppan ---- - drivers/clk/qcom/gcc-ipq8074.c | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - ---- a/drivers/clk/qcom/gcc-ipq8074.c -+++ b/drivers/clk/qcom/gcc-ipq8074.c -@@ -4518,10 +4518,10 @@ static const struct alpha_pll_config nss - }; - - static struct clk_branch gcc_snoc_bus_timeout2_ahb_clk = { -- .halt_reg = 0x4700c, -+ .halt_reg = 0x47014, - .halt_bit = 31, - .clkr = { -- .enable_reg = 0x4700c, -+ .enable_reg = 0x47014, - .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data){ - .name = "gcc_snoc_bus_timeout2_ahb_clk", -@@ -4536,10 +4536,10 @@ static struct clk_branch gcc_snoc_bus_ti - }; - - static struct clk_branch gcc_snoc_bus_timeout3_ahb_clk = { -- .halt_reg = 0x47014, -+ .halt_reg = 0x4701C, - .halt_bit = 31, - .clkr = { -- .enable_reg = 0x47014, -+ .enable_reg = 0x4701C, - .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data){ - .name = "gcc_snoc_bus_timeout3_ahb_clk", diff --git a/target/linux/ipq807x/patches-5.10/131-arm64-dts-ipq8074-add-SPMI-bus.patch b/target/linux/ipq807x/patches-5.10/131-arm64-dts-ipq8074-add-SPMI-bus.patch deleted file mode 100644 index 3596d1fd2..000000000 --- a/target/linux/ipq807x/patches-5.10/131-arm64-dts-ipq8074-add-SPMI-bus.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 43d5a2b56802327a27a3acb30eb1e458959f5794 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Thu, 13 May 2021 11:14:02 +0200 -Subject: [PATCH] arm64: dts: ipq8074: add SPMI bus - -IPQ8074 has a SPMI v2 arbiter, so add the node -for it. - -Signed-off-by: Robert Marko ---- - 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 -@@ -385,6 +385,25 @@ - #reset-cells = <0x1>; - }; - -+ spmi_bus: qcom,spmi@200f000 { -+ compatible = "qcom,spmi-pmic-arb"; -+ reg = <0x200f000 0x1000>, -+ <0x2400000 0x800000>, -+ <0x2c00000 0x800000>, -+ <0x3800000 0x200000>, -+ <0x200a000 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/ipq807x/patches-5.10/132-regulator-qcom_spmi-Add-PMD9655-SPMI-regulator.patch b/target/linux/ipq807x/patches-5.10/132-regulator-qcom_spmi-Add-PMD9655-SPMI-regulator.patch deleted file mode 100644 index 6b3ca0e1b..000000000 --- a/target/linux/ipq807x/patches-5.10/132-regulator-qcom_spmi-Add-PMD9655-SPMI-regulator.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 43361c2201bc9b67ee42a6afab7a3a476eaf6156 Mon Sep 17 00:00:00 2001 -From: Praveenkumar I -Date: Tue, 31 Mar 2020 22:00:27 +0530 -Subject: [PATCH 1/6] regulator: qcom_spmi: Add PMD9655 SPMI regulator - -PMD9655 is used in IPQ8074 and provides S3 for cores, -S4 for UBI core and LDO11 for SDIO/eMMC. - -Signed-off-by: Praveenkumar I -Signed-off-by: Robert Marko ---- - drivers/regulator/qcom_spmi-regulator.c | 8 ++++++++ - 1 file changed, 8 insertions(+) - ---- a/drivers/regulator/qcom_spmi-regulator.c -+++ b/drivers/regulator/qcom_spmi-regulator.c -@@ -2082,6 +2082,13 @@ static const struct spmi_regulator_data - { } - }; - -+static const struct spmi_regulator_data pmd9655_regulators[] = { -+ { "s3", 0x1a00, "vdd_s3",}, -+ { "s4", 0x1d00, "vdd_s4",}, -+ { "ldo11", 0x4a00, "vdd_ldo11",}, -+ { } -+}; -+ - static const struct of_device_id qcom_spmi_regulator_match[] = { - { .compatible = "qcom,pm8004-regulators", .data = &pm8004_regulators }, - { .compatible = "qcom,pm8005-regulators", .data = &pm8005_regulators }, -@@ -2094,6 +2101,7 @@ static const struct of_device_id qcom_sp - { .compatible = "qcom,pm660-regulators", .data = &pm660_regulators }, - { .compatible = "qcom,pm660l-regulators", .data = &pm660l_regulators }, - { .compatible = "qcom,pms405-regulators", .data = &pms405_regulators }, -+ { .compatible = "qcom,pmd9655-regulators", .data = &pmd9655_regulators }, - { } - }; - MODULE_DEVICE_TABLE(of, qcom_spmi_regulator_match); diff --git a/target/linux/ipq807x/patches-5.10/133-regulator-qcom_spmi-SMPS-range-is-added-to-support-P.patch b/target/linux/ipq807x/patches-5.10/133-regulator-qcom_spmi-SMPS-range-is-added-to-support-P.patch deleted file mode 100644 index 06628ad2a..000000000 --- a/target/linux/ipq807x/patches-5.10/133-regulator-qcom_spmi-SMPS-range-is-added-to-support-P.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 095567c1736af28ef6b472e2ab728a2222a425da Mon Sep 17 00:00:00 2001 -From: Praveenkumar I -Date: Mon, 4 May 2020 19:31:00 +0530 -Subject: [PATCH 2/6] regulator: qcom_spmi: SMPS range is added to support - PMD9655 PMIC - -Signed-off-by: Praveenkumar I -Change-Id: I5571801debec25527fd763d95aff27cc42f53bde ---- - drivers/regulator/qcom_spmi-regulator.c | 1 + - 1 file changed, 1 insertion(+) - ---- a/drivers/regulator/qcom_spmi-regulator.c -+++ b/drivers/regulator/qcom_spmi-regulator.c -@@ -480,6 +480,7 @@ static struct spmi_voltage_range ln_ldo_ - }; - - static struct spmi_voltage_range smps_ranges[] = { -+ SPMI_VOLTAGE_RANGE(2, 670000, 670000, 990000, 990000, 8000), - SPMI_VOLTAGE_RANGE(0, 375000, 375000, 1562500, 1562500, 12500), - SPMI_VOLTAGE_RANGE(1, 1550000, 1575000, 3125000, 3125000, 25000), - }; diff --git a/target/linux/ipq807x/patches-5.10/134-regulator-qcom_spmi-Initialize-slew-rate-only-if-req.patch b/target/linux/ipq807x/patches-5.10/134-regulator-qcom_spmi-Initialize-slew-rate-only-if-req.patch deleted file mode 100644 index b7fd176fc..000000000 --- a/target/linux/ipq807x/patches-5.10/134-regulator-qcom_spmi-Initialize-slew-rate-only-if-req.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0890aba3f364ed0764fdfa79bd77db130396e594 Mon Sep 17 00:00:00 2001 -From: PRAVEENKUMAR I -Date: Tue, 5 May 2020 07:57:21 +0530 -Subject: [PATCH 3/6] regulator: qcom_spmi: Initialize slew rate only if - required - -Initialize slew rate only if set_voltage_time_sel in ops -is defined. - -Change-Id: I661c88d2f4a8f26cc85b1e2d4c8aa3170420ba6c -Signed-off-by: Rajith Cherian -(cherry picked from commit 608a6f171ef4017197fbe2069b5910b582923027) -Signed-off-by: Praveenkumar I - -Change-Id: Ida3cf3d754e1207e34a164d6d86c6e1aa109ef1e ---- - 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 -@@ -1610,6 +1610,13 @@ static int spmi_regulator_init_slew_rate - int step, delay, slew_rate, step_delay; - const struct spmi_voltage_range *range; - -+ /* -+ * Slew rate need not be initialized if -+ * set_voltage_time_sel in the ops is not defined. -+ */ -+ if (!vreg->desc.ops->set_voltage_time_sel) -+ return 0; -+ - ret = spmi_vreg_read(vreg, SPMI_COMMON_REG_STEP_CTRL, ®, 1); - if (ret) { - dev_err(vreg->dev, "spmi read failed, ret=%d\n", ret); diff --git a/target/linux/ipq807x/patches-5.10/135-regulator-qcom_spmi-Add-support-for-VMPWM_CTL-subtyp.patch b/target/linux/ipq807x/patches-5.10/135-regulator-qcom_spmi-Add-support-for-VMPWM_CTL-subtyp.patch deleted file mode 100644 index 0b36cee95..000000000 --- a/target/linux/ipq807x/patches-5.10/135-regulator-qcom_spmi-Add-support-for-VMPWM_CTL-subtyp.patch +++ /dev/null @@ -1,159 +0,0 @@ -From 50b5c040b8c1928990baad8e07126df63aa09cce Mon Sep 17 00:00:00 2001 -From: PRAVEENKUMAR I -Date: Tue, 5 May 2020 07:57:52 +0530 -Subject: [PATCH 4/6] regulator: qcom_spmi: Add support for VMPWM_CTL subtype - -Support for Voltage Mode PWM Controller (VMPWM_CTL). -Set/Get microvolts functions added. Function to find the -voltage range for this particular subtype added. - -Change-Id: Ib4bf35ee65de17a917f01e63208368c7770401d4 -Signed-off-by: Rajith Cherian -(cherry picked from commit 31e7e4183b5afaf18dbca3548f4988c420ebb58b) -Signed-off-by: Praveenkumar I - -Change-Id: Id7a3caef84499b9e2eefda9f57576923c84234f0 ---- - drivers/regulator/qcom_spmi-regulator.c | 82 +++++++++++++++++++++++++ - 1 file changed, 82 insertions(+) - ---- a/drivers/regulator/qcom_spmi-regulator.c -+++ b/drivers/regulator/qcom_spmi-regulator.c -@@ -163,6 +163,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_VMPWM_CTL = 0x0a, - }; - - enum spmi_common_regulator_registers { -@@ -288,6 +289,10 @@ enum spmi_common_control_register_index - #define SPMI_FTSMPS_STEP_CTRL_DELAY_MASK 0x07 - #define SPMI_FTSMPS_STEP_CTRL_DELAY_SHIFT 0 - -+#define SPMI_SMPS_VMPWM_VSET_UB_SHIFT 8 -+#define SPMI_SMPS_VMPWM_VSET_UB_MASK 0xf00 -+#define SPMI_SMPS_VMPWM_VSET_LB_MASK 0xff -+ - /* Clock rate in kHz of the FTSMPS regulator reference clock. */ - #define SPMI_FTSMPS_CLOCK_RATE 19200 - -@@ -485,6 +490,10 @@ static struct spmi_voltage_range smps_ra - SPMI_VOLTAGE_RANGE(1, 1550000, 1575000, 3125000, 3125000, 25000), - }; - -+static struct spmi_voltage_range smps_vmpwm_ranges[] = { -+ SPMI_VOLTAGE_RANGE(0, 664000, 664000, 1104000, 1104000, 8000), -+}; -+ - static struct spmi_voltage_range ftsmps_ranges[] = { - SPMI_VOLTAGE_RANGE(0, 0, 350000, 1275000, 1275000, 5000), - SPMI_VOLTAGE_RANGE(1, 0, 1280000, 2040000, 2040000, 10000), -@@ -550,6 +559,7 @@ static DEFINE_SPMI_SET_POINTS(nldo2); - static DEFINE_SPMI_SET_POINTS(nldo3); - static DEFINE_SPMI_SET_POINTS(ln_ldo); - static DEFINE_SPMI_SET_POINTS(smps); -+static DEFINE_SPMI_SET_POINTS(smps_vmpwm); - static DEFINE_SPMI_SET_POINTS(ftsmps); - static DEFINE_SPMI_SET_POINTS(ftsmps2p5); - static DEFINE_SPMI_SET_POINTS(ftsmps426); -@@ -740,6 +750,24 @@ spmi_regulator_find_range(struct spmi_re - return NULL; - } - -+static const struct spmi_voltage_range * -+spmi_regulator_find_uV_range(struct spmi_regulator *vreg, int min, int max) -+{ -+ const struct spmi_voltage_range *range, *end; -+ -+ if (!vreg->set_points || !vreg->set_points->count) -+ return 0; -+ -+ range = vreg->set_points->range; -+ end = range + vreg->set_points->count; -+ -+ for (; range < end; range++) -+ if ((range->min_uV <= min) && (range->max_uV >= max)) -+ return range; -+ -+ return 0; -+} -+ - static int spmi_regulator_select_voltage_same_range(struct spmi_regulator *vreg, - int min_uV, int max_uV) - { -@@ -961,6 +989,47 @@ static int spmi_regulator_ult_lo_smps_ge - return spmi_hw_selector_to_sw(vreg, voltage_sel, range); - } - -+static int spmi_regulator_smps_vmpwm_set_vol_uV(struct regulator_dev *rdev, -+ int min_uV, int max_uV, unsigned *selector) -+{ -+ struct spmi_regulator *vreg = rdev_get_drvdata(rdev); -+ const struct spmi_voltage_range *range; -+ int req_vol; -+ u8 reg[2]; -+ -+ range = spmi_regulator_find_uV_range(vreg, min_uV, max_uV); -+ if (!range) -+ return -EINVAL; -+ -+ *selector = spmi_regulator_select_voltage(vreg, min_uV, max_uV); -+ req_vol = range->set_point_min_uV + (range->step_uV * (*selector)); -+ -+ /* Convert uV to mV as the register supports mV */ -+ req_vol = req_vol/1000; -+ -+ /* -+ * Voltage set point bits<7:0>. 2-Byte Word (lower byte word) -+ */ -+ reg[0] = req_vol & SPMI_SMPS_VMPWM_VSET_LB_MASK; -+ /* -+ * Voltage set point bit <11:8>. 2-Byte Word (upper byte word) -+ */ -+ reg[1] = (req_vol & SPMI_SMPS_VMPWM_VSET_UB_MASK) -+ >> SPMI_SMPS_VMPWM_VSET_UB_SHIFT; -+ -+ return spmi_vreg_write(vreg, SPMI_COMMON_REG_VOLTAGE_RANGE, reg, 2); -+} -+ -+static int spmi_regulator_smps_vmpwm_get_vol_uV(struct regulator_dev *rdev) -+{ -+ struct spmi_regulator *vreg = rdev_get_drvdata(rdev); -+ u8 reg[2]; -+ -+ spmi_vreg_read(vreg, SPMI_COMMON_REG_VOLTAGE_RANGE, reg, 2); -+ -+ return ((reg[1] << SPMI_SMPS_VMPWM_VSET_UB_SHIFT) | reg[0]) * 1000; -+} -+ - static int spmi_regulator_common_list_voltage(struct regulator_dev *rdev, - unsigned selector) - { -@@ -1309,6 +1378,18 @@ static const struct regulator_ops spmi_s - .set_pull_down = spmi_regulator_common_set_pull_down, - }; - -+static const struct regulator_ops spmi_smps_vmpwm_ops = { -+ .enable = regulator_enable_regmap, -+ .disable = regulator_disable_regmap, -+ .is_enabled = regulator_is_enabled_regmap, -+ .set_voltage = spmi_regulator_smps_vmpwm_set_vol_uV, -+ .get_voltage = spmi_regulator_smps_vmpwm_get_vol_uV, -+ .map_voltage = spmi_regulator_common_map_voltage, -+ .list_voltage = spmi_regulator_common_list_voltage, -+ .set_mode = spmi_regulator_common_set_mode, -+ .get_mode = spmi_regulator_common_get_mode, -+}; -+ - static const struct regulator_ops spmi_ldo_ops = { - .enable = regulator_enable_regmap, - .disable = regulator_disable_regmap, -@@ -1454,6 +1535,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(BUCK, VMPWM_CTL, 0, INF, SMPS, smps_vmpwm, smps_vmpwm, 0), - 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/ipq807x/patches-5.10/136-ipq807x-sdhc-Fixed-SDR104-mode-card-detection.patch b/target/linux/ipq807x/patches-5.10/136-ipq807x-sdhc-Fixed-SDR104-mode-card-detection.patch deleted file mode 100644 index 81f73182e..000000000 --- a/target/linux/ipq807x/patches-5.10/136-ipq807x-sdhc-Fixed-SDR104-mode-card-detection.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 84d0ae645dc1c3d8726bf8cd482be052f915f00b Mon Sep 17 00:00:00 2001 -From: Vasudevan Murugesan -Date: Thu, 8 Jun 2017 19:13:48 +0530 -Subject: [PATCH 5/6] ipq807x: sdhc: Fixed SDR104 mode card detection - -Change-Id: I353356284d28d09d79bf7d318c4ebcdbc15e5b02 -Signed-off-by: Vasudevan Murugesan -Signed-off-by: Saravanan Jaganathan -(cherry picked from commit 080d3f390aa409ef2b5adf59a175b6bb2aa863fd) -Signed-off-by: Praveenkumar I - -Change-Id: Ie5edb7b3d972e06f3eb2525e10597b49e9bae14d ---- - arch/arm64/boot/dts/qcom/ipq8074.dtsi | 1 - - drivers/regulator/qcom_spmi-regulator.c | 3 +++ - 2 files changed, 3 insertions(+), 1 deletion(-) - ---- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -425,7 +425,6 @@ - - status = "disabled"; - }; -- - blsp_dma: dma@7884000 { - compatible = "qcom,bam-v1.7.0"; - reg = <0x07884000 0x2b000>; ---- 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_CTL4 = 0x10, - SPMI_REGULATOR_SUBTYPE_HFS430 = 0x0a, - SPMI_REGULATOR_SUBTYPE_VMPWM_CTL = 0x0a, -+ SPMI_REGULATOR_SUBTYPE_HT_P150 = 0x35, - }; - - enum spmi_common_regulator_registers { -@@ -492,6 +493,7 @@ static struct spmi_voltage_range smps_ra - - static struct spmi_voltage_range smps_vmpwm_ranges[] = { - SPMI_VOLTAGE_RANGE(0, 664000, 664000, 1104000, 1104000, 8000), -+ SPMI_VOLTAGE_RANGE(1, 1104000, 1104000, 3300000, 3300000, 8000), - }; - - static struct spmi_voltage_range ftsmps_ranges[] = { -@@ -1535,6 +1537,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, LDO, smps_vmpwm, smps_vmpwm, 0), - SPMI_VREG(BUCK, VMPWM_CTL, 0, INF, SMPS, smps_vmpwm, smps_vmpwm, 0), - 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/ipq807x/patches-5.10/137-ipq807x-spmi-regulator-Add-separate-voltage-range-fo.patch b/target/linux/ipq807x/patches-5.10/137-ipq807x-spmi-regulator-Add-separate-voltage-range-fo.patch deleted file mode 100644 index 4e4b3f1f0..000000000 --- a/target/linux/ipq807x/patches-5.10/137-ipq807x-spmi-regulator-Add-separate-voltage-range-fo.patch +++ /dev/null @@ -1,49 +0,0 @@ -From c603c7a1e2d5cc432d8e1250baff8130755a6f43 Mon Sep 17 00:00:00 2001 -From: Praveenkumar I -Date: Mon, 13 Jul 2020 18:13:48 +0530 -Subject: [PATCH 6/6] ipq807x: spmi regulator: Add separate voltage range for - LDO - -When LDO voltage range added in SMPS voltage range structure, -selector value used during set voltage is wrongly calculated. -Because the SMPS voltage range is also taken into account for LDO. - -So, a separate voltage range structure is introduced for LDO. - -Signed-off-by: Praveenkumar I -Change-Id: I883518ae0686762a3774750b1dd480c4fe7298f3 ---- - drivers/regulator/qcom_spmi-regulator.c | 8 ++++++-- - 1 file changed, 6 insertions(+), 2 deletions(-) - ---- a/drivers/regulator/qcom_spmi-regulator.c -+++ b/drivers/regulator/qcom_spmi-regulator.c -@@ -493,7 +493,10 @@ static struct spmi_voltage_range smps_ra - - static struct spmi_voltage_range smps_vmpwm_ranges[] = { - SPMI_VOLTAGE_RANGE(0, 664000, 664000, 1104000, 1104000, 8000), -- SPMI_VOLTAGE_RANGE(1, 1104000, 1104000, 3300000, 3300000, 8000), -+}; -+ -+static struct spmi_voltage_range ldo_vmpwm_ranges[] = { -+ SPMI_VOLTAGE_RANGE(0, 1104000, 1104000, 3300000, 3300000, 8000), - }; - - static struct spmi_voltage_range ftsmps_ranges[] = { -@@ -562,6 +565,7 @@ static DEFINE_SPMI_SET_POINTS(nldo3); - static DEFINE_SPMI_SET_POINTS(ln_ldo); - static DEFINE_SPMI_SET_POINTS(smps); - static DEFINE_SPMI_SET_POINTS(smps_vmpwm); -+static DEFINE_SPMI_SET_POINTS(ldo_vmpwm); - static DEFINE_SPMI_SET_POINTS(ftsmps); - static DEFINE_SPMI_SET_POINTS(ftsmps2p5); - static DEFINE_SPMI_SET_POINTS(ftsmps426); -@@ -1537,7 +1541,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, LDO, smps_vmpwm, smps_vmpwm, 0), -+ SPMI_VREG(LDO, HT_P150, 0, INF, LDO, smps_vmpwm, ldo_vmpwm, 0), - SPMI_VREG(BUCK, VMPWM_CTL, 0, INF, SMPS, smps_vmpwm, smps_vmpwm, 0), - 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/ipq807x/patches-5.10/138-arm64-dts-ipq8074-add-SPMI-PMIC-regulators.patch b/target/linux/ipq807x/patches-5.10/138-arm64-dts-ipq8074-add-SPMI-PMIC-regulators.patch deleted file mode 100644 index 7342824bc..000000000 --- a/target/linux/ipq807x/patches-5.10/138-arm64-dts-ipq8074-add-SPMI-PMIC-regulators.patch +++ /dev/null @@ -1,84 +0,0 @@ -From df848f06020c609950107f87c39f41e7eee92b5e Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Thu, 13 May 2021 11:54:35 +0200 -Subject: [PATCH] arm64: dts: ipq8074: add SPMI PMIC regulators - -PMD9655 is used in IPQ8074 and provides S3 for cores, -S4 for UBI core and LDO11 for SDIO/eMMC. - -So, lets add the nodes in preparation for DVFS later. - -Signed-off-by: Robert Marko ---- - arch/arm64/boot/dts/qcom/ipq8074.dtsi | 46 +++++++++++++++++++++++++++ - 1 file changed, 46 insertions(+) - ---- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -5,6 +5,7 @@ - - #include - #include -+#include - - / { - model = "Qualcomm Technologies, Inc. IPQ8074"; -@@ -136,6 +137,15 @@ - }; - }; - -+ e_smps1_reg: fixed-regulator@0 { -+ compatible = "regulator-fixed"; -+ regulator-name = "e-smps1-reg"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-always-on; -+ regulator-boot-on; -+ }; -+ - soc: soc { - #address-cells = <0x1>; - #size-cells = <0x1>; -@@ -402,6 +412,42 @@ - interrupt-controller; - #interrupt-cells = <4>; - cell-index = <0>; -+ -+ pmic@1 { -+ compatible ="qcom,spmi-pmic"; -+ reg = <0x1 SPMI_USID>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ regulators { -+ compatible = "qcom,pmd9655-regulators"; -+ vdd_s3-supply = <&e_smps1_reg>; -+ vdd_s4-supply = <&e_smps1_reg>; -+ vdd_ldo11-supply = <&e_smps1_reg>; -+ -+ s3: s3 { -+ regulator-name = "pmd9655_s3"; -+ regulator-min-microvolt = <592000>; -+ regulator-max-microvolt = <1064000>; -+ regulator-always-on; -+ regulator-boot-on; -+ }; -+ -+ s4: s4 { -+ regulator-name = "pmd9655_s4"; -+ regulator-min-microvolt = <712000>; -+ regulator-max-microvolt = <992000>; -+ regulator-always-on; -+ regulator-boot-on; -+ }; -+ -+ ldo11: ldo11 { -+ regulator-name = "pmd9655_ldo11"; -+ regulator-min-microvolt = <1104000>; -+ regulator-max-microvolt = <3300000>; -+ }; -+ }; -+ }; - }; - - sdhc_1: sdhci@7824900 { diff --git a/target/linux/ipq807x/patches-5.10/139-ipq8074-clk-apss-Added-APSS-clock-driver.patch b/target/linux/ipq807x/patches-5.10/139-ipq8074-clk-apss-Added-APSS-clock-driver.patch deleted file mode 100644 index 71c3124b9..000000000 --- a/target/linux/ipq807x/patches-5.10/139-ipq8074-clk-apss-Added-APSS-clock-driver.patch +++ /dev/null @@ -1,328 +0,0 @@ -From 6961b02dd2765b71b201f065172998a16ff9c2eb Mon Sep 17 00:00:00 2001 -From: Praveenkumar I -Date: Sun, 22 Mar 2020 20:22:29 +0530 -Subject: [PATCH 1/3] ipq8074: clk: apss: Added APSS clock driver - -apss-ipq8074 files are snapshot form eggplant branch, -https://source.codeaurora.org/quic/qsdk/oss/kernel/linux-ipq-5.4/commit/?h=keggplant/eggplant&id=f2fb70e8315ef1c450171e59d681c6a156b1a4e8 - -Signed-off-by: Praveenkumar I -Change-Id: I17ecad1f1731c88d8d91485d5d5f8a38b76f7104 ---- - drivers/clk/qcom/Kconfig | 7 + - drivers/clk/qcom/Makefile | 1 + - drivers/clk/qcom/apss-ipq8074.c | 210 +++++++++++++++++++ - drivers/clk/qcom/clk-alpha-pll.c | 12 ++ - drivers/clk/qcom/clk-alpha-pll.h | 3 + - include/dt-bindings/clock/qca,apss-ipq8074.h | 25 +++ - 6 files changed, 258 insertions(+) - create mode 100644 drivers/clk/qcom/apss-ipq8074.c - create mode 100644 include/dt-bindings/clock/qca,apss-ipq8074.h - ---- a/drivers/clk/qcom/Kconfig -+++ b/drivers/clk/qcom/Kconfig -@@ -156,6 +156,13 @@ config IPQ_GCC_8074 - i2c, USB, SD/eMMC, etc. Select this for the root clock - of ipq8074. - -+config IPQ_APSS_8074 -+ tristate "IPQ8074 APSS Clock Controller" -+ select IPQ_GCC_8074 -+ help -+ Support for APSS clock controller on ipq8074 devices. -+ Say Y if you want to use APSS clocks such as CPU. -+ - config MSM_GCC_8660 - tristate "MSM8660 Global Clock Controller" - help ---- a/drivers/clk/qcom/Makefile -+++ b/drivers/clk/qcom/Makefile -@@ -25,6 +25,7 @@ obj-$(CONFIG_IPQ_GCC_4019) += gcc-ipq401 - obj-$(CONFIG_IPQ_GCC_6018) += gcc-ipq6018.o - obj-$(CONFIG_IPQ_GCC_806X) += gcc-ipq806x.o - obj-$(CONFIG_IPQ_GCC_8074) += gcc-ipq8074.o -+obj-$(CONFIG_IPQ_APSS_8074) += apss-ipq8074.o - obj-$(CONFIG_IPQ_LCC_806X) += lcc-ipq806x.o - obj-$(CONFIG_MDM_GCC_9615) += gcc-mdm9615.o - obj-$(CONFIG_MDM_LCC_9615) += lcc-mdm9615.o ---- /dev/null -+++ b/drivers/clk/qcom/apss-ipq8074.c -@@ -0,0 +1,210 @@ -+/* -+ * Copyright (c) 2017,2020. 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 -+ -+#include -+#include -+ -+#include "common.h" -+#include "clk-regmap.h" -+#include "clk-pll.h" -+#include "clk-rcg.h" -+#include "clk-branch.h" -+#include "clk-alpha-pll.h" -+#include "clk-regmap-divider.h" -+#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_GPLL0, -+ P_GPLL2, -+ P_GPLL4, -+ P_APSS_PLL_EARLY, -+ P_APSS_PLL -+}; -+ -+static struct clk_alpha_pll apss_pll_early = { -+ .offset = 0x5000, -+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_APSS], -+ .clkr = { -+ .enable_reg = 0x5000, -+ .enable_mask = BIT(0), -+ .hw.init = &(struct clk_init_data){ -+ .name = "apss_pll_early", -+ .parent_names = (const char *[]){ -+ "xo" -+ }, -+ .num_parents = 1, -+ .ops = &clk_alpha_pll_huayra_ops, -+ }, -+ }, -+}; -+ -+static struct clk_alpha_pll_postdiv apss_pll = { -+ .offset = 0x5000, -+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_APSS], -+ .width = 2, -+ .clkr.hw.init = &(struct clk_init_data){ -+ .name = "apss_pll", -+ .parent_names = (const char *[]){ "apss_pll_early" }, -+ .num_parents = 1, -+ .ops = &clk_alpha_pll_postdiv_ro_ops, -+ }, -+}; -+ -+static const char * const parents_apcs_alias0_clk_src[] = { -+ "xo", -+ "gpll0", -+ "gpll2", -+ "gpll4", -+ "apss_pll", -+ "apss_pll_early", -+}; -+ -+static const struct parent_map parents_apcs_alias0_clk_src_map[] = { -+ { P_XO, 0 }, -+ { P_GPLL0, 4 }, -+ { P_GPLL2, 2 }, -+ { P_GPLL4, 1 }, -+ { P_APSS_PLL, 3 }, -+ { P_APSS_PLL_EARLY, 5 }, -+}; -+ -+struct freq_tbl ftbl_apcs_alias0_clk_src[] = { -+ F(19200000, P_XO, 1, 0, 0), -+ F(403200000, P_APSS_PLL_EARLY, 1, 0, 0), -+ F(806400000, P_APSS_PLL_EARLY, 1, 0, 0), -+ F(1017600000, P_APSS_PLL_EARLY, 1, 0, 0), -+ F(1382400000, P_APSS_PLL_EARLY, 1, 0, 0), -+ F(1651200000, P_APSS_PLL_EARLY, 1, 0, 0), -+ F(1843200000, P_APSS_PLL_EARLY, 1, 0, 0), -+ F(1920000000, P_APSS_PLL_EARLY, 1, 0, 0), -+ F(2208000000UL, P_APSS_PLL_EARLY, 1, 0, 0), -+ { } -+}; -+ -+struct clk_rcg2 apcs_alias0_clk_src = { -+ .cmd_rcgr = 0x0050, -+ .freq_tbl = ftbl_apcs_alias0_clk_src, -+ .hid_width = 5, -+ .parent_map = parents_apcs_alias0_clk_src_map, -+ .clkr.hw.init = &(struct clk_init_data){ -+ .name = "apcs_alias0_clk_src", -+ .parent_names = parents_apcs_alias0_clk_src, -+ .num_parents = 6, -+ .ops = &clk_rcg2_ops, -+ .flags = CLK_SET_RATE_PARENT, -+ }, -+}; -+ -+static struct clk_branch apcs_alias0_core_clk = { -+ .halt_reg = 0x0058, -+ .halt_bit = 31, -+ .clkr = { -+ .enable_reg = 0x0058, -+ .enable_mask = BIT(0), -+ .hw.init = &(struct clk_init_data){ -+ .name = "apcs_alias0_core_clk", -+ .parent_names = (const char *[]){ -+ "apcs_alias0_clk_src" -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT | -+ CLK_IS_CRITICAL, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_regmap *apss_ipq807x_clks[] = { -+ [APSS_PLL_EARLY] = &apss_pll_early.clkr, -+ [APSS_PLL] = &apss_pll.clkr, -+ [APCS_ALIAS0_CLK_SRC] = &apcs_alias0_clk_src.clkr, -+ [APCS_ALIAS0_CORE_CLK] = &apcs_alias0_core_clk.clkr, -+}; -+ -+static const struct of_device_id apss_ipq807x_match_table[] = { -+ { .compatible = "qcom,apss-ipq807x" }, -+ { } -+}; -+MODULE_DEVICE_TABLE(of, apss_ipq807x_match_table); -+ -+static const struct regmap_config apss_ipq807x_regmap_config = { -+ .reg_bits = 32, -+ .reg_stride = 4, -+ .val_bits = 32, -+ .max_register = 0x5ffc, -+ .fast_io = true, -+}; -+ -+static const struct qcom_cc_desc apss_ipq807x_desc = { -+ .config = &apss_ipq807x_regmap_config, -+ .clks = apss_ipq807x_clks, -+ .num_clks = ARRAY_SIZE(apss_ipq807x_clks), -+}; -+ -+static int apss_ipq807x_probe(struct platform_device *pdev) -+{ -+ int ret; -+ -+ ret = qcom_cc_probe(pdev, &apss_ipq807x_desc); -+ -+ dev_dbg(&pdev->dev, "Registered ipq807x apss clock provider\n"); -+ -+ return ret; -+} -+ -+static int apss_ipq807x_remove(struct platform_device *pdev) -+{ -+ return 0; -+} -+ -+static struct platform_driver apss_ipq807x_driver = { -+ .probe = apss_ipq807x_probe, -+ .remove = apss_ipq807x_remove, -+ .driver = { -+ .name = "qcom,apss-ipq807x", -+ .owner = THIS_MODULE, -+ .of_match_table = apss_ipq807x_match_table, -+ }, -+}; -+ -+static int __init apss_ipq807x_init(void) -+{ -+ return platform_driver_register(&apss_ipq807x_driver); -+} -+core_initcall(apss_ipq807x_init); -+ -+static void __exit apss_ipq807x_exit(void) -+{ -+ platform_driver_unregister(&apss_ipq807x_driver); -+} -+module_exit(apss_ipq807x_exit); -+ -+MODULE_DESCRIPTION("QCA APSS IPQ807x Driver"); -+MODULE_LICENSE("Dual BSD/GPLv2"); -+MODULE_ALIAS("platform:apss-ipq807x"); ---- a/drivers/clk/qcom/clk-alpha-pll.c -+++ b/drivers/clk/qcom/clk-alpha-pll.c -@@ -116,6 +116,18 @@ const u8 clk_alpha_pll_regs[][PLL_OFF_MA - [PLL_OFF_OPMODE] = 0x38, - [PLL_OFF_ALPHA_VAL] = 0x40, - }, -+ [CLK_ALPHA_PLL_TYPE_APSS] = { -+ [PLL_OFF_L_VAL] = 0x08, -+ [PLL_OFF_ALPHA_VAL] = 0x10, -+ [PLL_OFF_ALPHA_VAL_U] = 0xff, -+ [PLL_OFF_USER_CTL] = 0x18, -+ [PLL_OFF_USER_CTL_U] = 0xff, -+ [PLL_OFF_CONFIG_CTL] = 0x20, -+ [PLL_OFF_CONFIG_CTL_U] = 0x24, -+ [PLL_OFF_TEST_CTL] = 0x30, -+ [PLL_OFF_TEST_CTL_U] = 0x34, -+ [PLL_OFF_STATUS] = 0x28, -+ } - }; - EXPORT_SYMBOL_GPL(clk_alpha_pll_regs); - ---- a/drivers/clk/qcom/clk-alpha-pll.h -+++ b/drivers/clk/qcom/clk-alpha-pll.h -@@ -15,6 +15,7 @@ enum { - CLK_ALPHA_PLL_TYPE_FABIA, - CLK_ALPHA_PLL_TYPE_TRION, - CLK_ALPHA_PLL_TYPE_LUCID = CLK_ALPHA_PLL_TYPE_TRION, -+ CLK_ALPHA_PLL_TYPE_APSS, - CLK_ALPHA_PLL_TYPE_MAX, - }; - -@@ -69,6 +70,8 @@ struct clk_alpha_pll { - #define SUPPORTS_OFFLINE_REQ BIT(0) - #define SUPPORTS_FSM_MODE BIT(2) - #define SUPPORTS_DYNAMIC_UPDATE BIT(3) -+ -+ - u8 flags; - - struct clk_regmap clkr; ---- /dev/null -+++ b/include/dt-bindings/clock/qca,apss-ipq8074.h -@@ -0,0 +1,25 @@ -+/* -+ * Copyright (c) 2017,2020. 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. -+ */ -+ -+#ifndef _DT_BINDINGS_CLOCK_QCA_APSS_IPQ8074_H -+#define _DT_BINDINGS_CLOCK_QCA_APSS_IPQ8074_H -+ -+#define APSS_PLL_EARLY 0 -+#define APSS_PLL 1 -+#define APCS_ALIAS0_CLK_SRC 2 -+#define APCS_ALIAS0_CORE_CLK 3 -+ -+#endif diff --git a/target/linux/ipq807x/patches-5.10/140-clk-qcom-ipq8074-make-apss-clock-as-child-of-mailbox.patch b/target/linux/ipq807x/patches-5.10/140-clk-qcom-ipq8074-make-apss-clock-as-child-of-mailbox.patch deleted file mode 100644 index 995e65676..000000000 --- a/target/linux/ipq807x/patches-5.10/140-clk-qcom-ipq8074-make-apss-clock-as-child-of-mailbox.patch +++ /dev/null @@ -1,105 +0,0 @@ -From b5c28ea3b9a963d425ae88ef53d266ff8ae95bc2 Mon Sep 17 00:00:00 2001 -From: Sivaprakash Murugesan -Date: Fri, 24 Apr 2020 23:05:50 +0530 -Subject: [PATCH 2/3] clk: qcom: ipq8074: make apss clock as child of mailbox - -both apcs mailbox and apss clock controller access the same register -space, resource request will fail for one of the two drivers. - -to resolve this make apss clock controller as child of mailbox, the apss -clock controller will use mailbox regmap for resource request and probe. - -Signed-off-by: Sivaprakash Murugesan -Change-Id: Ic26ee78b6f680fa0655a73d3176bae271725ab05 ---- - drivers/clk/qcom/apss-ipq8074.c | 14 ++++++-------- - drivers/mailbox/qcom-apcs-ipc-mailbox.c | 18 +++++++++++++++--- - 2 files changed, 21 insertions(+), 11 deletions(-) - ---- a/drivers/clk/qcom/apss-ipq8074.c -+++ b/drivers/clk/qcom/apss-ipq8074.c -@@ -147,12 +147,6 @@ static struct clk_regmap *apss_ipq807x_c - [APCS_ALIAS0_CORE_CLK] = &apcs_alias0_core_clk.clkr, - }; - --static const struct of_device_id apss_ipq807x_match_table[] = { -- { .compatible = "qcom,apss-ipq807x" }, -- { } --}; --MODULE_DEVICE_TABLE(of, apss_ipq807x_match_table); -- - static const struct regmap_config apss_ipq807x_regmap_config = { - .reg_bits = 32, - .reg_stride = 4, -@@ -170,8 +164,13 @@ static const struct qcom_cc_desc apss_ip - static int apss_ipq807x_probe(struct platform_device *pdev) - { - int ret; -+ struct regmap *regmap; -+ -+ regmap = dev_get_regmap(pdev->dev.parent, NULL); -+ if (IS_ERR(regmap)) -+ return PTR_ERR(regmap); - -- ret = qcom_cc_probe(pdev, &apss_ipq807x_desc); -+ ret = qcom_cc_really_probe(pdev, &apss_ipq807x_desc, regmap); - - dev_dbg(&pdev->dev, "Registered ipq807x apss clock provider\n"); - -@@ -189,7 +188,6 @@ static struct platform_driver apss_ipq80 - .driver = { - .name = "qcom,apss-ipq807x", - .owner = THIS_MODULE, -- .of_match_table = apss_ipq807x_match_table, - }, - }; - ---- a/drivers/mailbox/qcom-apcs-ipc-mailbox.c -+++ b/drivers/mailbox/qcom-apcs-ipc-mailbox.c -@@ -65,7 +65,7 @@ static const struct regmap_config apcs_r - .reg_bits = 32, - .reg_stride = 4, - .val_bits = 32, -- .max_register = 0xFFC, -+ .max_register = 0x5FFC, - .fast_io = true, - }; - -@@ -82,6 +82,16 @@ static const struct mbox_chan_ops qcom_a - .send_data = qcom_apcs_ipc_send_data, - }; - -+static const struct of_device_id apcs_clk_match_table[] = { -+ { .compatible = "qcom,msm8916-apcs-kpss-global", -+ . data = "qcom-apcs-msm8916-clk", }, -+ { .compatible = "qcom,qcs404-apcs-apps-global", -+ .data = "qcom-apcs-msm8916-clk", }, -+ { .compatible = "qcom,ipq8074-apcs-apps-global", -+ .data = "qcom,apss-ipq807x", }, -+ {} -+}; -+ - static int qcom_apcs_ipc_probe(struct platform_device *pdev) - { - struct qcom_apcs_ipc *apcs; -@@ -91,6 +101,7 @@ static int qcom_apcs_ipc_probe(struct pl - void __iomem *base; - unsigned long i; - int ret; -+ const struct of_device_id *device_id; - - apcs = devm_kzalloc(&pdev->dev, sizeof(*apcs), GFP_KERNEL); - if (!apcs) -@@ -125,9 +136,10 @@ static int qcom_apcs_ipc_probe(struct pl - return ret; - } - -- if (apcs_data->clk_name) { -+ device_id = of_match_device(apcs_clk_match_table, &pdev->dev); -+ if (device_id) { - apcs->clk = platform_device_register_data(&pdev->dev, -- apcs_data->clk_name, -+ device_id->data, - PLATFORM_DEVID_AUTO, - NULL, 0); - if (IS_ERR(apcs->clk)) diff --git a/target/linux/ipq807x/patches-5.10/141-arm64-dts-ipq8074-add-APPS-CPU-clock.patch b/target/linux/ipq807x/patches-5.10/141-arm64-dts-ipq8074-add-APPS-CPU-clock.patch deleted file mode 100644 index b2722a1be..000000000 --- a/target/linux/ipq807x/patches-5.10/141-arm64-dts-ipq8074-add-APPS-CPU-clock.patch +++ /dev/null @@ -1,70 +0,0 @@ -From 99841b41e13b4a0512de1e06191cdcaf7ee0e1d1 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Thu, 13 May 2021 12:42:05 +0200 -Subject: [PATCH 3/3] arm64: dts: ipq8074: add APPS CPU clock - -In preparation for frequency scaling add the APPS -clock support. - -Signed-off-by: Robert Marko ---- - arch/arm64/boot/dts/qcom/ipq8074.dtsi | 12 +++++++++++- - 1 file changed, 11 insertions(+), 1 deletion(-) - ---- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -5,6 +5,7 @@ - - #include - #include -+#include - #include - - / { -@@ -33,6 +34,8 @@ - device_type = "cpu"; - compatible = "arm,cortex-a53"; - reg = <0x0>; -+ clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>; -+ clock-names = "cpu"; - next-level-cache = <&L2_0>; - enable-method = "psci"; - }; -@@ -42,6 +45,8 @@ - compatible = "arm,cortex-a53"; - enable-method = "psci"; - reg = <0x1>; -+ clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>; -+ clock-names = "cpu"; - next-level-cache = <&L2_0>; - }; - -@@ -50,6 +55,8 @@ - compatible = "arm,cortex-a53"; - enable-method = "psci"; - reg = <0x2>; -+ clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>; -+ clock-names = "cpu"; - next-level-cache = <&L2_0>; - }; - -@@ -58,6 +65,8 @@ - compatible = "arm,cortex-a53"; - enable-method = "psci"; - reg = <0x3>; -+ clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>; -+ clock-names = "cpu"; - next-level-cache = <&L2_0>; - }; - -@@ -897,8 +906,9 @@ - - apcs_glb: mailbox@b111000 { - compatible = "qcom,ipq8074-apcs-apps-global"; -- reg = <0x0b111000 0x1000>; -+ reg = <0x0b111000 0x6000>; - -+ #clock-cells = <1>; - #mbox-cells = <1>; - }; - diff --git a/target/linux/ipq807x/patches-5.10/142-arm64-dts-ipq8074-add-label-to-cpus.patch b/target/linux/ipq807x/patches-5.10/142-arm64-dts-ipq8074-add-label-to-cpus.patch deleted file mode 100644 index 687cb55c4..000000000 --- a/target/linux/ipq807x/patches-5.10/142-arm64-dts-ipq8074-add-label-to-cpus.patch +++ /dev/null @@ -1,26 +0,0 @@ -From fb5a1fff750f99dbf7cabda0de9fbf7463a07586 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Thu, 13 May 2021 13:13:46 +0200 -Subject: [PATCH] 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 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 -@@ -26,7 +26,7 @@ - }; - }; - -- cpus { -+ cpus: cpus { - #address-cells = <0x1>; - #size-cells = <0x0>; - diff --git a/target/linux/ipq807x/patches-5.10/143-arm64-dts-ipq8074-Add-WLAN-node.patch b/target/linux/ipq807x/patches-5.10/143-arm64-dts-ipq8074-Add-WLAN-node.patch deleted file mode 100644 index 42c123d03..000000000 --- a/target/linux/ipq807x/patches-5.10/143-arm64-dts-ipq8074-Add-WLAN-node.patch +++ /dev/null @@ -1,133 +0,0 @@ -From 0fb054684bdf40f17ab59226dae21ddfe0d79466 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Thu, 13 May 2021 15:15:46 +0200 -Subject: [PATCH] arm64: dts: ipq8074: Add WLAN node - -IPQ8074 is supported by ath11k, so add the required -DT node. - -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 -@@ -962,6 +962,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"; -+ }; -+ - ess_switch: ess-switch@3a000000 { - compatible = "qcom,ess-switch-ipq807x"; - reg = <0x3a000000 0x1000000>; diff --git a/target/linux/ipq807x/patches-5.10/144-arm64-dts-ipq8074-add-NSS-reserved-memory-node.patch b/target/linux/ipq807x/patches-5.10/144-arm64-dts-ipq8074-add-NSS-reserved-memory-node.patch deleted file mode 100644 index ce2af3edf..000000000 --- a/target/linux/ipq807x/patches-5.10/144-arm64-dts-ipq8074-add-NSS-reserved-memory-node.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 22865119dada2a40a5e5e8c5f22b5bec08651021 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Fri, 14 May 2021 19:43:41 +0200 -Subject: [PATCH] arm64: dts: ipq8074: add NSS reserved memory node - -NSS FW has its own dedicated memory it needs to get loaded to. -Since it simply uses ioremap() that memory must be reserved -so the kernel will allow using ioremap() on it. - -Signed-off-by: Robert Marko ---- - 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 -@@ -91,6 +91,11 @@ - #size-cells = <2>; - ranges; - -+ nss@40000000 { -+ no-map; -+ reg = <0x0 0x40000000 0x0 0x01000000>; -+ }; -+ - smem_region: memory@4ab00000 { - no-map; - reg = <0x0 0x4ab00000 0x0 0x00100000>; diff --git a/target/linux/ipq807x/patches-5.10/145-clk-qcom-ipq8074-disable-SW_COLLAPSE-for-USB-GDSCR-s.patch b/target/linux/ipq807x/patches-5.10/145-clk-qcom-ipq8074-disable-SW_COLLAPSE-for-USB-GDSCR-s.patch deleted file mode 100644 index 7d0f82293..000000000 --- a/target/linux/ipq807x/patches-5.10/145-clk-qcom-ipq8074-disable-SW_COLLAPSE-for-USB-GDSCR-s.patch +++ /dev/null @@ -1,29 +0,0 @@ -From a801cc475f0d1fdf29d7b6b56d64df090bf83f8d Mon Sep 17 00:00:00 2001 -From: Praveenkumar I -Date: Fri, 3 Apr 2020 12:57:37 +0530 -Subject: [PATCH] clk: qcom: ipq8074: disable SW_COLLAPSE for USB GDSCR's - -Change-Id: Id347be781e2bb449bd7cdf05e3535e8ca3c3ffd6 -Signed-off-by: Abhishek Sahu -(cherry picked from commit 5e100df9c29ed7e5ad12583aa39053f4a9761efe) -Signed-off-by: Praveenkumar I - -Change-Id: I17beca334be79d738a35587860847aa0b1f96fa9 ---- - drivers/clk/qcom/gcc-ipq8074.c | 5 +++++ - 1 file changed, 5 insertions(+) - ---- a/drivers/clk/qcom/gcc-ipq8074.c -+++ b/drivers/clk/qcom/gcc-ipq8074.c -@@ -5061,6 +5061,11 @@ static int gcc_ipq8074_probe(struct plat - /* SW Workaround for UBI32 Huayra PLL */ - regmap_update_bits(regmap, 0x2501c, BIT(26), BIT(26)); - -+ /* Disable SW_COLLAPSE for USB0 GDSCR */ -+ regmap_update_bits(regmap, 0x3e078, BIT(0), 0x0); -+ /* Disable SW_COLLAPSE for USB1 GDSCR */ -+ regmap_update_bits(regmap, 0x3f078, BIT(0), 0x0); -+ - clk_alpha_pll_configure(&ubi32_pll_main, regmap, &ubi32_pll_config); - clk_alpha_pll_configure(&nss_crypto_pll_main, regmap, - &nss_crypto_pll_config); diff --git a/target/linux/ipq807x/patches-5.10/146-clk-qcom-ipq8074-SW-workaround-for-UBI-PLL-lock.patch b/target/linux/ipq807x/patches-5.10/146-clk-qcom-ipq8074-SW-workaround-for-UBI-PLL-lock.patch deleted file mode 100644 index 1a929925e..000000000 --- a/target/linux/ipq807x/patches-5.10/146-clk-qcom-ipq8074-SW-workaround-for-UBI-PLL-lock.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 5f707d3ff1b22c089253e39906b5edeeb5f10fdc Mon Sep 17 00:00:00 2001 -From: Praveenkumar I -Date: Fri, 3 Apr 2020 15:31:59 +0530 -Subject: [PATCH] clk: qcom: ipq8074: SW workaround for UBI PLL lock -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Some chip’s Huyara PLL is unable to lock in 5 us and -generating UBI PLL lock error. - - WARNING: CPU: 1 PID: 625 at drivers/clk/qcom/clk-alpha-pll.c:114 - wait_for_pll+0xbc/0xe0() - ubi32_pll_main failed to enable! - CPU: 1 PID: 625 Comm: kmodloader Not tainted 4.4.60 #1 - Hardware name: Generic DT based system - (unwind_backtrace) from [<8021b550>] (show_stack+0x10/0x14) - (show_stack) from [<803f6b24>] (dump_stack+0x80/0xa0) - (dump_stack) from [<80228ff0>] (warn_slowpath_common+0x84/0xb0) - (warn_slowpath_common) from [<80229048>] (warn_slowpath_fmt+0x2c/0x3c) - (warn_slowpath_fmt) from [<8054d53c>] (wait_for_pll+0xbc/0xe0) - (wait_for_pll) from [<8054d6cc>] (clk_alpha_pll_enable+0xe0/0x128) - (clk_alpha_pll_enable) from [<80547b68>] (clk_core_enable+0x68/0x98) - (clk_core_enable) from [<80547b48>] (clk_core_enable+0x48/0x98) - -This is BUG in Huayra PLL HW for which SW workaround -is to set bit 26 of TEST_CTL register. - -Change-Id: Ib5473f4011e3410515f382b2445bee2d66dd654a -Signed-off-by: Abhishek Sahu ---- - drivers/clk/qcom/gcc-ipq8074.c | 3 +++ - 1 file changed, 3 insertions(+) - ---- a/drivers/clk/qcom/gcc-ipq8074.c -+++ b/drivers/clk/qcom/gcc-ipq8074.c -@@ -5066,6 +5066,9 @@ static int gcc_ipq8074_probe(struct plat - /* Disable SW_COLLAPSE for USB1 GDSCR */ - regmap_update_bits(regmap, 0x3f078, BIT(0), 0x0); - -+ /* SW Workaround for UBI Huayra PLL */ -+ regmap_update_bits(regmap, 0x2501c, BIT(26), BIT(26)); -+ - clk_alpha_pll_configure(&ubi32_pll_main, regmap, &ubi32_pll_config); - clk_alpha_pll_configure(&nss_crypto_pll_main, regmap, - &nss_crypto_pll_config); diff --git a/target/linux/ipq807x/patches-5.10/148-clk-ipq8074-fix-gcc_blsp1_ahb_clk-properties.patch b/target/linux/ipq807x/patches-5.10/148-clk-ipq8074-fix-gcc_blsp1_ahb_clk-properties.patch deleted file mode 100644 index 54999753f..000000000 --- a/target/linux/ipq807x/patches-5.10/148-clk-ipq8074-fix-gcc_blsp1_ahb_clk-properties.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 52315bec6ed633b6a71f28b746029602f8bd70b9 Mon Sep 17 00:00:00 2001 -From: Balaji Prakash J -Date: Wed, 22 Apr 2020 20:35:30 +0530 -Subject: [PATCH] clk: ipq8074: fix gcc_blsp1_ahb_clk properties - -All the voting enabled clocks does not support the enable -from CBCR register. So, updated gcc_blsp1_ahb_clk enable -register and mask to enable bit in APCS_CLOCK_BRANCH_ENA_VOTE. - -Also, the voting controlled clocks are shared among multiple -components like APSS, RPM, NSS, TZ, etc. So, turning the -voting off from APSS does not make the clock off if it has -been voted from another component. Added the flag -BRANCH_HALT_VOTED in order to skip checking the clock -disable status. - -This change is referred from the below commits, -1. 246b4fb3af9bd65d8af794aac2f0e7b1ed9cc2dd -2. c8374157d5ae91d3b3e0d513d62808a798b32d3a - -Signed-off-by: Balaji Prakash J -Change-Id: I505cb560b31ad27a02c165fbe13bb33a2fc7d230 ---- - drivers/clk/qcom/gcc-ipq8074.c | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - ---- a/drivers/clk/qcom/gcc-ipq8074.c -+++ b/drivers/clk/qcom/gcc-ipq8074.c -@@ -2112,9 +2112,10 @@ struct clk_rcg2 adss_pwm_clk_src = { - - static struct clk_branch gcc_blsp1_ahb_clk = { - .halt_reg = 0x01008, -+ .halt_check = BRANCH_HALT_VOTED, - .clkr = { -- .enable_reg = 0x01008, -- .enable_mask = BIT(0), -+ .enable_reg = 0x0b004, -+ .enable_mask = BIT(10), - .hw.init = &(struct clk_init_data){ - .name = "gcc_blsp1_ahb_clk", - .parent_names = (const char *[]){ diff --git a/target/linux/ipq807x/patches-5.10/149-remoteproc-wcss-disable-auto-boot-for-IPQ8074.patch b/target/linux/ipq807x/patches-5.10/149-remoteproc-wcss-disable-auto-boot-for-IPQ8074.patch deleted file mode 100644 index f484b97a7..000000000 --- a/target/linux/ipq807x/patches-5.10/149-remoteproc-wcss-disable-auto-boot-for-IPQ8074.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 256eda666b4687c5242b9f075caf4e09ad642daa Mon Sep 17 00:00:00 2001 -From: Sivaprakash Murugesan -Date: Fri, 17 Apr 2020 16:37:10 +0530 -Subject: [PATCH] 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) -@@ -1147,6 +1148,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; -@@ -1183,6 +1185,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 = { -@@ -1199,6 +1202,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/ipq807x/patches-5.10/150-arm64-dts-ipq8074-add-missing-reserved-memory-nodes.patch b/target/linux/ipq807x/patches-5.10/150-arm64-dts-ipq8074-add-missing-reserved-memory-nodes.patch deleted file mode 100644 index bc0535998..000000000 --- a/target/linux/ipq807x/patches-5.10/150-arm64-dts-ipq8074-add-missing-reserved-memory-nodes.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 158bd87b3db04bdd1effe4a92424f9572224a6c3 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Sat, 15 May 2021 00:09:21 +0200 -Subject: [PATCH] arm64: dts: ipq8074: add missing reserved memory nodes - -Downstream kernel has more reserved memory nodes. -Without these ath11k will cause a board reset. - -Signed-off-by: Robert Marko ---- - arch/arm64/boot/dts/qcom/ipq8074.dtsi | 36 +++++++++++++++++++++++++-- - 1 file changed, 34 insertions(+), 2 deletions(-) - ---- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -96,15 +96,47 @@ - reg = <0x0 0x40000000 0x0 0x01000000>; - }; - -- smem_region: memory@4ab00000 { -+ tzapp: 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_region: smem@4ab00000 { - no-map; - reg = <0x0 0x4ab00000 0x0 0x00100000>; - }; - -- q6_region: memory@4b000000 { -+ tz@4ac00000 { -+ 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@51000000 { -+ no-map; -+ reg = <0x0 0x51000000 0x0 0x100000>; -+ }; -+ - }; - - firmware { diff --git a/target/linux/ipq807x/patches-5.10/151-arm64-dts-ipq8074-add-q6_etr-memory-region-to-remote.patch b/target/linux/ipq807x/patches-5.10/151-arm64-dts-ipq8074-add-q6_etr-memory-region-to-remote.patch deleted file mode 100644 index d13e26e09..000000000 --- a/target/linux/ipq807x/patches-5.10/151-arm64-dts-ipq8074-add-q6_etr-memory-region-to-remote.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 86aa6afcf280a61150a3e6c796f629d09db88d55 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Sat, 15 May 2021 00:18:32 +0200 -Subject: [PATCH] arm64: dts: ipq8074: add q6_etr memory region to remoteproc - -Q6v5 remoteprocessor also has a q6_etr memor region -reserved for it, so add it to the 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 -@@ -986,7 +986,7 @@ - qcom,smem-state-names = "shutdown", - "stop"; - -- memory-region = <&q6_region>; -+ memory-region = <&q6_region>, <&q6_etr_region>; - - glink-edge { - interrupts = ; diff --git a/target/linux/ipq807x/patches-5.10/152-thermal-qcom-tsens-Add-IPQ8074-support.patch b/target/linux/ipq807x/patches-5.10/152-thermal-qcom-tsens-Add-IPQ8074-support.patch deleted file mode 100644 index 075c321e6..000000000 --- a/target/linux/ipq807x/patches-5.10/152-thermal-qcom-tsens-Add-IPQ8074-support.patch +++ /dev/null @@ -1,99 +0,0 @@ -From 98130cb1cb992593b050baa9c4d8484d6fd6e8f6 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Fri, 20 Nov 2020 13:52:43 +0100 -Subject: [PATCH] thermal: qcom: tsens: Add IPQ8074 support - -Qualcomm IPQ807x SoC-s use tsens v2.3.0 IP, but they -only have one interrupt and not a dedicated critical interrupt. - -Signed-off-by: Robert Marko ---- - drivers/thermal/qcom/tsens-v2.c | 14 ++++++++++++++ - drivers/thermal/qcom/tsens.c | 27 ++++++++++++++++++--------- - drivers/thermal/qcom/tsens.h | 2 +- - 3 files changed, 33 insertions(+), 10 deletions(-) - ---- a/drivers/thermal/qcom/tsens-v2.c -+++ b/drivers/thermal/qcom/tsens-v2.c -@@ -36,6 +36,14 @@ static struct tsens_features tsens_v2_fe - .max_sensors = 16, - }; - -+static struct tsens_features tsens_ipq8074_feat = { -+ .ver_major = VER_2_X, -+ .crit_int = 0, -+ .adc = 0, -+ .srot_split = 1, -+ .max_sensors = 16, -+}; -+ - static const struct reg_field tsens_v2_regfields[MAX_REGFIELDS] = { - /* ----- SROT ------ */ - /* VERSION */ -@@ -101,6 +109,12 @@ struct tsens_plat_data data_tsens_v2 = { - .fields = tsens_v2_regfields, - }; - -+struct tsens_plat_data data_tsens_ipq8074 = { -+ .ops = &ops_generic_v2, -+ .feat = &tsens_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 -@@ -323,16 +323,22 @@ static int tsens_read_irq_state(struct t - ret = regmap_field_read(priv->rf[LOW_INT_MASK_0 + hw_id], &d->low_irq_mask); - if (ret) - return ret; -- ret = regmap_field_read(priv->rf[CRIT_INT_CLEAR_0 + hw_id], -- &d->crit_irq_clear); -- if (ret) -- return ret; -- ret = regmap_field_read(priv->rf[CRIT_INT_MASK_0 + hw_id], -- &d->crit_irq_mask); -- if (ret) -- return ret; -+ if (priv->feat->crit_int) { -+ ret = regmap_field_read(priv->rf[CRIT_INT_CLEAR_0 + hw_id], -+ &d->crit_irq_clear); -+ if (ret) -+ return ret; -+ ret = regmap_field_read(priv->rf[CRIT_INT_MASK_0 + hw_id], -+ &d->crit_irq_mask); -+ if (ret) -+ return ret; - -- d->crit_thresh = tsens_hw_to_mC(s, CRIT_THRESH_0 + hw_id); -+ d->crit_thresh = tsens_hw_to_mC(s, CRIT_THRESH_0 + hw_id); -+ } else { -+ d->crit_irq_clear = 0; -+ d->crit_irq_mask = 0; -+ d->crit_thresh = 0; -+ } - } else { - /* No mask register on older TSENS */ - d->up_irq_mask = 0; -@@ -923,6 +929,9 @@ static const struct of_device_id tsens_t - }, { - .compatible = "qcom,tsens-v2", - .data = &data_tsens_v2, -+ }, { -+ .compatible = "qcom,ipq8074-tsens", -+ .data = &data_tsens_ipq8074, - }, - {} - }; ---- a/drivers/thermal/qcom/tsens.h -+++ b/drivers/thermal/qcom/tsens.h -@@ -591,6 +591,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_tsens_v2, data_tsens_ipq8074; - - #endif /* __QCOM_TSENS_H__ */ diff --git a/target/linux/ipq807x/patches-5.10/154-drivers-thermal-tsens-add-timeout-to-get_tem_tsens_v.patch b/target/linux/ipq807x/patches-5.10/154-drivers-thermal-tsens-add-timeout-to-get_tem_tsens_v.patch deleted file mode 100644 index 73eaef837..000000000 --- a/target/linux/ipq807x/patches-5.10/154-drivers-thermal-tsens-add-timeout-to-get_tem_tsens_v.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 47b165aa6ed3b85b793c5bfb27050c93a194c0cc Mon Sep 17 00:00:00 2001 -From: Ansuel Smith -Date: Wed, 19 May 2021 00:52:21 +0200 -Subject: [PATCH 2/2] drivers: thermal: tsens: add timeout to - get_tem_tsens_valid - -The function can loop and lock the system if for whatever reason the bit -for the target sensor is NEVER valid. This is the case if a sensor is -disabled by the factory and the valid bit is never reported as actually -valid. Add a timeout check and exit if a timeout occurs. As this is -a very rare condition, handle the timeout only if the first read fails. - -Signed-off-by: Ansuel Smith ---- - drivers/thermal/qcom/tsens.c | 23 ++++++++++++++++------- - 1 file changed, 16 insertions(+), 7 deletions(-) - ---- a/drivers/thermal/qcom/tsens.c -+++ b/drivers/thermal/qcom/tsens.c -@@ -587,19 +587,28 @@ int get_temp_tsens_valid(const struct ts - int hw_id = s->hw_id; - u32 temp_idx = LAST_TEMP_0 + hw_id; - u32 valid_idx = VALID_0 + hw_id; -+ unsigned long timeout; - u32 valid; - int ret; - - ret = regmap_field_read(priv->rf[valid_idx], &valid); - if (ret) - return ret; -- while (!valid) { -- /* Valid bit is 0 for 6 AHB clock cycles. -- * At 19.2MHz, 1 AHB clock is ~60ns. -- * We should enter this loop very, very rarely. -- */ -- ndelay(400); -- ret = regmap_field_read(priv->rf[valid_idx], &valid); -+ -+ if (!valid) { -+ timeout = jiffies + msecs_to_jiffies(20); -+ -+ do { -+ /* Valid bit is 0 for 6 AHB clock cycles. -+ * At 19.2MHz, 1 AHB clock is ~60ns. -+ * We should enter this loop very, very rarely. -+ */ -+ ndelay(400); -+ ret = regmap_field_read(priv->rf[valid_idx], &valid); -+ if (valid || ret) -+ break; -+ } while (!(ret = time_after_eq(jiffies, timeout))); -+ - if (ret) - return ret; - } diff --git a/target/linux/ipq807x/patches-5.10/155-arm64-dts-ipq8074-add-thermal-nodes.patch b/target/linux/ipq807x/patches-5.10/155-arm64-dts-ipq8074-add-thermal-nodes.patch deleted file mode 100644 index fb6699b9e..000000000 --- a/target/linux/ipq807x/patches-5.10/155-arm64-dts-ipq8074-add-thermal-nodes.patch +++ /dev/null @@ -1,167 +0,0 @@ -From de1ca571d14bab031cc57bab5311db05f33ceec3 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Wed, 19 May 2021 00:14:50 +0200 -Subject: [PATCH] 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 required nodes for tsens and thermal -zones to enable passive cooling of the device. - -Signed-off-by: Robert Marko ---- - arch/arm64/boot/dts/qcom/ipq8074.dtsi | 101 ++++++++++++++++++++++++++ - 1 file changed, 101 insertions(+) - ---- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -6,6 +6,7 @@ - #include - #include - #include -+#include - #include - - / { -@@ -38,6 +39,7 @@ - clock-names = "cpu"; - next-level-cache = <&L2_0>; - enable-method = "psci"; -+ #cooling-cells = <2>; - }; - - CPU1: cpu@1 { -@@ -48,6 +50,7 @@ - clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>; - clock-names = "cpu"; - next-level-cache = <&L2_0>; -+ #cooling-cells = <2>; - }; - - CPU2: cpu@2 { -@@ -58,6 +61,7 @@ - clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>; - clock-names = "cpu"; - next-level-cache = <&L2_0>; -+ #cooling-cells = <2>; - }; - - CPU3: cpu@3 { -@@ -68,6 +72,7 @@ - clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>; - clock-names = "cpu"; - next-level-cache = <&L2_0>; -+ #cooling-cells = <2>; - }; - - L2_0: l2-cache { -@@ -360,6 +365,16 @@ - status = "disabled"; - }; - -+ tsens: thermal-sensor@4a9000 { -+ compatible = "qcom,ipq8074-tsens"; -+ reg = <0x4a9000 0x1000>, /* TM */ -+ <0x4a8000 0x1000>; /* SROT */ -+ interrupts = ; -+ interrupt-names = "uplow"; -+ #qcom,sensors = <16>; -+ #thermal-sensor-cells = <1>; -+ }; -+ - cryptobam: dma@704000 { - compatible = "qcom,bam-v1.7.0"; - reg = <0x00704000 0x20000>; -@@ -1272,4 +1287,90 @@ - #clock-cells = <0>; - }; - }; -+ -+ 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/ipq807x/patches-5.10/156-arm64-dts-ipq8074-disable-USB-phy-by-default.patch b/target/linux/ipq807x/patches-5.10/156-arm64-dts-ipq8074-disable-USB-phy-by-default.patch deleted file mode 100644 index e0ea16bf3..000000000 --- a/target/linux/ipq807x/patches-5.10/156-arm64-dts-ipq8074-disable-USB-phy-by-default.patch +++ /dev/null @@ -1,27 +0,0 @@ -From c58dea2220d978756a0f7e815bc13dbfa8c33ebc Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Wed, 26 May 2021 16:49:02 +0200 -Subject: [PATCH] arm64: dts: ipq8074: disable USB phy by default - -One of the QUSB USB PHY-s has been left enabled by -default, this is probably just a mistake as other -USB PHY-s are disabled by default. - -It makes no sense to have it enabled by default as -not all board implement USB ports, so disable it. - -Signed-off-by: Robert Marko ---- - 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 -@@ -286,6 +286,7 @@ - clock-names = "cfg_ahb", "ref"; - - resets = <&gcc GCC_QUSB2_0_PHY_BCR>; -+ status = "disabled"; - }; - - pcie_qmp0: phy@84000 { diff --git a/target/linux/ipq807x/patches-5.10/157-arm64-dts-ipq8074-Add-QUP6-I2C-node.patch b/target/linux/ipq807x/patches-5.10/157-arm64-dts-ipq8074-Add-QUP6-I2C-node.patch deleted file mode 100644 index 0393a441f..000000000 --- a/target/linux/ipq807x/patches-5.10/157-arm64-dts-ipq8074-Add-QUP6-I2C-node.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 9b2aee0e0fd786c6836d1472cd935186b746bc5e Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Sun, 13 Jun 2021 12:10:42 +0200 -Subject: [PATCH] arm64: dts: ipq8074: Add QUP6 I2C node - -Add node to support the QUP6 I2C controller inside -of IPQ8074. -It is exactly the same as QUP2 and QUP3 controllers. - -Some routers like Xiaomi AX9000 and Netgear RBK850 -use this bus. - -Signed-off-by: Robert Marko ---- - 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 -@@ -629,6 +629,21 @@ - status = "disabled"; - }; - -+ blsp1_i2c6: i2c@78ba000 { -+ compatible = "qcom,i2c-qup-v2.2.1"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ reg = <0x078ba000 0x600>; -+ interrupts = ; -+ clocks = <&gcc GCC_BLSP1_AHB_CLK>, -+ <&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"; -+ status = "disabled"; -+ }; -+ - qpic_bam: dma@7984000 { - compatible = "qcom,bam-v1.7.0"; - reg = <0x07984000 0x1a000>; diff --git a/target/linux/ipq807x/patches-5.10/158-hwmon-Add-SMSC-EMC2301-2-3-5-fan-controller-driver.patch b/target/linux/ipq807x/patches-5.10/158-hwmon-Add-SMSC-EMC2301-2-3-5-fan-controller-driver.patch deleted file mode 100644 index 18df86543..000000000 --- a/target/linux/ipq807x/patches-5.10/158-hwmon-Add-SMSC-EMC2301-2-3-5-fan-controller-driver.patch +++ /dev/null @@ -1,51 +0,0 @@ -From a58b73b20db06f91025c5c847fcf2b53e341a6ff Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Mon, 14 Jun 2021 19:01:14 +0200 -Subject: [PATCH] hwmon: Add SMSC EMC2301/2/3/5 fan controller driver - -Add support for SMSC EMC2305, EMC2303, EMC2302, EMC2301 fan controller -chips. -The driver primary supports the EMC2305 chip which provides RPM-based -PWM control and monitoring for up to 5 fans. - -According to the SMSC data sheets the EMC2303, EMC2302 and EMC2301 chips -have basically the same functionality and register layout, but support -less fans and (in case of EMC2302 and EMC2301) less possible I2C addresses. -The driver supports them, too. - -Signed-off-by: Robert Marko ---- - drivers/hwmon/Kconfig | 11 +++++++++++ - drivers/hwmon/Makefile | 1 + - 2 files changed, 12 insertions(+) - ---- a/drivers/hwmon/Kconfig -+++ b/drivers/hwmon/Kconfig -@@ -1602,6 +1602,17 @@ config SENSORS_EMC2103 - This driver can also be built as a module. If so, the module - will be called emc2103. - -+config SENSORS_EMC2305 -+ tristate "SMSC EMC2305" -+ depends on I2C -+ select REGMAP_I2C -+ help -+ If you say yes here you get support for the fan monitoring -+ and control features of the SMSC EMC2301/2/3/5 chips. -+ -+ This driver can also be built as a module. If so, the module -+ will be called emc2305. -+ - config SENSORS_EMC6W201 - tristate "SMSC EMC6W201" - depends on I2C ---- a/drivers/hwmon/Makefile -+++ b/drivers/hwmon/Makefile -@@ -66,6 +66,7 @@ obj-$(CONFIG_SENSORS_DS620) += ds620.o - obj-$(CONFIG_SENSORS_DS1621) += ds1621.o - obj-$(CONFIG_SENSORS_EMC1403) += emc1403.o - obj-$(CONFIG_SENSORS_EMC2103) += emc2103.o -+obj-$(CONFIG_SENSORS_EMC2305) += emc2305.o - obj-$(CONFIG_SENSORS_EMC6W201) += emc6w201.o - obj-$(CONFIG_SENSORS_F71805F) += f71805f.o - obj-$(CONFIG_SENSORS_F71882FG) += f71882fg.o diff --git a/target/linux/ipq807x/patches-5.10/600-qca-nss-ecm-support-CORE.patch b/target/linux/ipq807x/patches-5.10/600-qca-nss-ecm-support-CORE.patch deleted file mode 100644 index c0e7f973d..000000000 --- a/target/linux/ipq807x/patches-5.10/600-qca-nss-ecm-support-CORE.patch +++ /dev/null @@ -1,741 +0,0 @@ ---- a/net/netfilter/nf_conntrack_proto_tcp.c -+++ b/net/netfilter/nf_conntrack_proto_tcp.c -@@ -32,20 +32,14 @@ - #include - - /* Do not check the TCP window for incoming packets */ --static int nf_ct_tcp_no_window_check __read_mostly = 1; -- --#ifdef CONFIG_SHORTCUT_FE -+int nf_ct_tcp_no_window_check __read_mostly = 1; - EXPORT_SYMBOL_GPL(nf_ct_tcp_no_window_check); --#endif - - /* "Be conservative in what you do, - be liberal in what you accept from others." - If it's non-zero, we mark only out of window RST segments as INVALID. */ --static int nf_ct_tcp_be_liberal __read_mostly = 0; -- --#ifdef CONFIG_SHORTCUT_FE -+int nf_ct_tcp_be_liberal __read_mostly = 0; - EXPORT_SYMBOL_GPL(nf_ct_tcp_be_liberal); --#endif - - /* If it is set to zero, we disable picking up already established - connections. */ ---- a/include/linux/if_bridge.h -+++ b/include/linux/if_bridge.h -@@ -63,6 +63,7 @@ extern void brioctl_set(int (*ioctl_hook - - 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); - - #if IS_ENABLED(CONFIG_BRIDGE) && IS_ENABLED(CONFIG_BRIDGE_IGMP_SNOOPING) - int br_multicast_list_adjacent(struct net_device *dev, -@@ -158,4 +159,42 @@ br_port_flag_is_set(const struct net_dev - } - #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 -@@ -2786,6 +2786,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 -@@ -210,6 +210,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/8021q/vlan_core.c -+++ b/net/8021q/vlan_core.c -@@ -557,4 +557,52 @@ static int __init vlan_offload_init(void - return 0; - } - -+/* QCA NSS ECM support - Start */ -+/* Update the VLAN device with statistics from network offload engines */ -+void __vlan_dev_update_accel_stats(struct net_device *dev, -+ struct rtnl_link_stats64 *nlstats) -+{ -+ struct vlan_pcpu_stats *stats; -+ -+ if (!is_vlan_dev(dev)) -+ return; -+ -+ stats = per_cpu_ptr(vlan_dev_priv(dev)->vlan_pcpu_stats, 0); -+ -+ u64_stats_update_begin(&stats->syncp); -+ stats->rx_packets += nlstats->rx_packets; -+ stats->rx_bytes += nlstats->rx_bytes; -+ stats->tx_packets += nlstats->tx_packets; -+ stats->tx_bytes += nlstats->tx_bytes; -+ u64_stats_update_end(&stats->syncp); -+} -+EXPORT_SYMBOL(__vlan_dev_update_accel_stats); -+ -+/* Lookup the 802.1p egress_map table and return the 802.1p value */ -+u16 vlan_dev_get_egress_prio(struct net_device *dev, u32 skb_prio) -+{ -+ struct vlan_priority_tci_mapping *mp; -+ -+ mp = vlan_dev_priv(dev)->egress_priority_map[(skb_prio & 0xf)]; -+ while (mp) { -+ if (mp->priority == skb_prio) { -+ /* This should already be shifted -+ * to mask correctly with the -+ * VLAN's TCI -+ */ -+ return mp->vlan_qos; -+ } -+ mp = mp->next; -+ } -+ return 0; -+} -+EXPORT_SYMBOL(vlan_dev_get_egress_prio); -+ -+struct net_device *vlan_dev_next_dev(const struct net_device *dev) -+{ -+ return vlan_dev_priv(dev)->real_dev; -+} -+EXPORT_SYMBOL(vlan_dev_next_dev); -+/* QCA NSS ECM support - End */ -+ - fs_initcall(vlan_offload_init); ---- a/net/bridge/br_fdb.c -+++ b/net/bridge/br_fdb.c -@@ -37,6 +37,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", -@@ -342,6 +371,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 -@@ -368,8 +398,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); - } - } -@@ -610,6 +647,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))) -@@ -734,6 +777,25 @@ static void fdb_notify(struct net_bridge - struct sk_buff *skb; - int err = -ENOBUFS; - -+ /* 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); - -@@ -1317,3 +1379,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 -@@ -26,6 +26,12 @@ - - #include "br_private.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 -@@ -712,6 +718,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; - - err7: -@@ -748,6 +756,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. -@@ -813,3 +823,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 -@@ -1591,4 +1591,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 -@@ -1216,7 +1216,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. -@@ -1247,6 +1261,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); - -@@ -1261,6 +1276,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; -@@ -1298,6 +1315,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; -@@ -1420,8 +1442,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 -@@ -1164,6 +1164,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) -@@ -1354,6 +1357,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: -@@ -1725,6 +1731,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; -@@ -2365,6 +2374,20 @@ void __init fib_trie_init(void) - 0, SLAB_PANIC, 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 -@@ -514,4 +514,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/addrconf.c -+++ b/net/ipv6/addrconf.c -@@ -7283,3 +7283,35 @@ void addrconf_cleanup(void) - - destroy_workqueue(addrconf_wq); - } -+ -+/* QCA NSS ECM support - Start */ -+/* ipv6_dev_find_and_hold() -+ * Find (and hold) net device that has the given address. -+ * Or NULL on failure. -+ */ -+struct net_device *ipv6_dev_find_and_hold(struct net *net, struct in6_addr *addr, -+ int strict) -+{ -+ struct inet6_ifaddr *ifp; -+ struct net_device *dev; -+ -+ ifp = ipv6_get_ifaddr(net, addr, NULL, strict); -+ if (!ifp) -+ return NULL; -+ -+ if (!ifp->idev) { -+ in6_ifa_put(ifp); -+ return NULL; -+ } -+ -+ dev = ifp->idev->dev; -+ if (dev) -+ dev_hold(dev); -+ -+ in6_ifa_put(ifp); -+ -+ return dev; -+} -+EXPORT_SYMBOL(ipv6_dev_find_and_hold); -+/* QCA NSS ECM support - End */ -+ ---- a/net/ipv6/ndisc.c -+++ b/net/ipv6/ndisc.c -@@ -650,6 +650,7 @@ void ndisc_send_ns(struct net_device *de - - ndisc_send_skb(skb, daddr, saddr); - } -+EXPORT_SYMBOL(ndisc_send_ns); - - void ndisc_send_rs(struct net_device *dev, const struct in6_addr *saddr, - const struct in6_addr *daddr) ---- a/net/ipv6/route.c -+++ b/net/ipv6/route.c -@@ -3765,6 +3765,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) - { -@@ -3776,6 +3779,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; -@@ -3797,6 +3804,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; -@@ -6185,6 +6195,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/ipq807x/patches-5.10/602-qca-add-pppoe-offload-support.patch b/target/linux/ipq807x/patches-5.10/602-qca-add-pppoe-offload-support.patch deleted file mode 100644 index 7582d2c7c..000000000 --- a/target/linux/ipq807x/patches-5.10/602-qca-add-pppoe-offload-support.patch +++ /dev/null @@ -1,588 +0,0 @@ ---- a/drivers/net/ppp/ppp_generic.c -+++ b/drivers/net/ppp/ppp_generic.c -@@ -48,6 +48,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -252,6 +253,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); -@@ -3301,7 +3321,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); -@@ -3332,13 +3355,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; - } - -@@ -3356,6 +3406,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); -@@ -3435,6 +3492,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); -@@ -3451,6 +3724,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) { -@@ -994,9 +995,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 -@@ -1654,6 +1654,24 @@ enum netdev_priv_flags { - IFF_NO_IP_ALIGN = 1<<31, - }; - -+ -+/** -+ * 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 -@@ -2033,6 +2051,7 @@ struct net_device { - - unsigned int flags; - unsigned int priv_flags; -+ unsigned int priv_flags_ext; - - unsigned short gflags; - unsigned short padded; ---- 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/ipq807x/patches-5.10/603-net-core-Flag-to-identify-ingress-shaping-done-for-e.patch b/target/linux/ipq807x/patches-5.10/603-net-core-Flag-to-identify-ingress-shaping-done-for-e.patch deleted file mode 100644 index 2b3bdd1a2..000000000 --- a/target/linux/ipq807x/patches-5.10/603-net-core-Flag-to-identify-ingress-shaping-done-for-e.patch +++ /dev/null @@ -1,74 +0,0 @@ -From a0c69a23c66ec6f527c439714eb2cc5857a71492 Mon Sep 17 00:00:00 2001 -From: Himanshu Joshi -Date: Tue, 3 Nov 2020 16:41:26 +0530 -Subject: [PATCH] net: core: Flag to identify ingress shaping done for - exceptioned packets. - -Signed-off-by: Himanshu Joshi -Change-Id: Ib3cd341e5b2d4dcf552e02e38d3f34a4f00351cd ---- - 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 -@@ -648,6 +648,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_nss: do not classify packet. set by NSS 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 -@@ -855,6 +856,7 @@ struct sk_buff { - #ifdef CONFIG_NET_CLS_ACT - __u8 tc_skip_classify:1; - __u8 tc_at_ingress:1; -+ __u8 tc_skip_classify_nss:1; - #endif - #ifdef CONFIG_NET_REDIRECT - __u8 redirected:1; ---- a/include/net/sch_generic.h -+++ b/include/net/sch_generic.h -@@ -740,6 +740,40 @@ static inline bool skb_skip_tc_classify( - return false; - } - -+/* -+ * Set skb classify bit field. -+ */ -+static inline void skb_set_tc_classify_nss(struct sk_buff *skb) -+{ -+#ifdef CONFIG_NET_CLS_ACT -+ skb->tc_skip_classify_nss = 1; -+#endif -+} -+ -+/* -+ * Clear skb classify bit field. -+ */ -+static inline void skb_clear_tc_classify_nss(struct sk_buff *skb) -+{ -+#ifdef CONFIG_NET_CLS_ACT -+ skb->tc_skip_classify_nss = 0; -+#endif -+} -+ -+/* -+ * Skip skb processing if sent from ifb dev. -+ */ -+static inline bool skb_skip_tc_classify_nss(struct sk_buff *skb) -+{ -+#ifdef CONFIG_NET_CLS_ACT -+ if (skb->tc_skip_classify_nss) { -+ skb_clear_tc_classify_nss(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/ipq807x/patches-5.10/604-net-core-Replace-nss-keyword-with-offload.patch b/target/linux/ipq807x/patches-5.10/604-net-core-Replace-nss-keyword-with-offload.patch deleted file mode 100644 index de103120f..000000000 --- a/target/linux/ipq807x/patches-5.10/604-net-core-Replace-nss-keyword-with-offload.patch +++ /dev/null @@ -1,76 +0,0 @@ -From 7c55539fa1e4ea6be400a35127ddc52d6dcd86d4 Mon Sep 17 00:00:00 2001 -From: Himanshu Joshi -Date: Thu, 26 Nov 2020 16:21:06 +0530 -Subject: [PATCH] net: core: Replace nss keyword with offload. - -Kernel code should not checked in with NSS keyword. -This change fixes the naming issue for ifb module. - -Signed-off-by: Himanshu Joshi -Change-Id: Iddb97d6ba0a443b830d1ac23728434a417bc8a92 ---- - include/linux/skbuff.h | 4 ++-- - include/net/sch_generic.h | 14 +++++++------- - 2 files changed, 9 insertions(+), 9 deletions(-) - ---- a/include/linux/skbuff.h -+++ b/include/linux/skbuff.h -@@ -648,7 +648,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_nss: do not classify packet. set by NSS 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 -@@ -856,7 +856,7 @@ struct sk_buff { - #ifdef CONFIG_NET_CLS_ACT - __u8 tc_skip_classify:1; - __u8 tc_at_ingress:1; -- __u8 tc_skip_classify_nss:1; -+ __u8 tc_skip_classify_offload:1; - #endif - #ifdef CONFIG_NET_REDIRECT - __u8 redirected:1; ---- a/include/net/sch_generic.h -+++ b/include/net/sch_generic.h -@@ -743,31 +743,31 @@ static inline bool skb_skip_tc_classify( - /* - * Set skb classify bit field. - */ --static inline void skb_set_tc_classify_nss(struct sk_buff *skb) -+static inline void skb_set_tc_classify_offload(struct sk_buff *skb) - { - #ifdef CONFIG_NET_CLS_ACT -- skb->tc_skip_classify_nss = 1; -+ skb->tc_skip_classify_offload = 1; - #endif - } - - /* - * Clear skb classify bit field. - */ --static inline void skb_clear_tc_classify_nss(struct sk_buff *skb) -+static inline void skb_clear_tc_classify_offload(struct sk_buff *skb) - { - #ifdef CONFIG_NET_CLS_ACT -- skb->tc_skip_classify_nss = 0; -+ skb->tc_skip_classify_offload = 0; - #endif - } - - /* - * Skip skb processing if sent from ifb dev. - */ --static inline bool skb_skip_tc_classify_nss(struct sk_buff *skb) -+static inline bool skb_skip_tc_classify_offload(struct sk_buff *skb) - { - #ifdef CONFIG_NET_CLS_ACT -- if (skb->tc_skip_classify_nss) { -- skb_clear_tc_classify_nss(skb); -+ if (skb->tc_skip_classify_offload) { -+ skb_clear_tc_classify_offload(skb); - return true; - } - #endif diff --git a/target/linux/ipq807x/patches-5.10/605-qca-add-add-nss-bridge-mgr-support.patch b/target/linux/ipq807x/patches-5.10/605-qca-add-add-nss-bridge-mgr-support.patch deleted file mode 100644 index 4d6afb93f..000000000 --- a/target/linux/ipq807x/patches-5.10/605-qca-add-add-nss-bridge-mgr-support.patch +++ /dev/null @@ -1,97 +0,0 @@ -From bcb4b67add833322a1361eea26f185deecd15ff1 Mon Sep 17 00:00:00 2001 -From: Simon Casey -Date: Fri, 22 Oct 2021 14:43:11 +0200 -Subject: [PATCH] bridge: Add NSS bridge-mgr support for ipq807x - -Add necessary functionality for enabling the NSS bridge-mgr module. - -Signed-off-by: Simon Casey ---- - 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 -@@ -197,4 +197,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 -@@ -66,6 +66,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", -@@ -371,7 +380,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 -@@ -399,12 +408,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); -@@ -615,6 +625,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) -@@ -640,6 +651,12 @@ void br_fdb_update(struct net_bridge *br - if (unlikely(source != 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 = fdb->dst->dev; -+ fdb_event.dev = source->dev; -+ /* QCA NSS bridge-mgr support - End */ - fdb->dst = source; - fdb_modified = true; - /* Take over HW learned entry */ -@@ -651,7 +668,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/ipq807x/patches-5.10/606-qca-nss-ecm-bonding-add-bond_get_id.patch b/target/linux/ipq807x/patches-5.10/606-qca-nss-ecm-bonding-add-bond_get_id.patch deleted file mode 100644 index 7c9ab09ec..000000000 --- a/target/linux/ipq807x/patches-5.10/606-qca-nss-ecm-bonding-add-bond_get_id.patch +++ /dev/null @@ -1,74 +0,0 @@ ---- a/drivers/net/bonding/bond_main.c -+++ b/drivers/net/bonding/bond_main.c -@@ -247,6 +247,7 @@ static const struct flow_dissector_key f - }; - - static struct flow_dissector flow_keys_bonding __read_mostly; -+static unsigned long bond_id_mask = 0xFFFFFFF0; - - /*-------------------------- Forward declarations ---------------------------*/ - -@@ -301,6 +302,20 @@ netdev_tx_t bond_dev_queue_xmit(struct b - return dev_queue_xmit(skb); - } - -+int bond_get_id(struct net_device *bond_dev) -+{ -+ struct bonding *bond; -+ -+ if (!((bond_dev->priv_flags & IFF_BONDING) && -+ (bond_dev->flags & IFF_MASTER))) -+ return -EINVAL; -+ -+ bond = netdev_priv(bond_dev); -+ -+ return bond->id; -+} -+EXPORT_SYMBOL(bond_get_id); -+ - /*---------------------------------- VLAN -----------------------------------*/ - - /* In the following 2 functions, bond_vlan_rx_add_vid and bond_vlan_rx_kill_vid, -@@ -4876,6 +4891,9 @@ static void bond_destructor(struct net_d - struct bonding *bond = netdev_priv(bond_dev); - if (bond->wq) - destroy_workqueue(bond->wq); -+ -+ if (bond->id != (~0U)) -+ clear_bit(bond->id, &bond_id_mask); - } - - void bond_setup(struct net_device *bond_dev) -@@ -5448,6 +5466,14 @@ int bond_create(struct net *net, const c - bond_work_init_all(bond); - - rtnl_unlock(); -+ -+ bond = netdev_priv(bond_dev); -+ bond->id = ~0U; -+ if (bond_id_mask != (~0UL)) { -+ bond->id = (u32)ffz(bond_id_mask); -+ set_bit(bond->id, &bond_id_mask); -+ } -+ - return 0; - } - ---- a/include/net/bonding.h -+++ b/include/net/bonding.h -@@ -257,6 +257,7 @@ struct bonding { - /* protecting ipsec_list */ - spinlock_t ipsec_lock; - #endif /* CONFIG_XFRM_OFFLOAD */ -+ u32 id; - }; - - #define bond_slave_get_rcu(dev) \ -@@ -629,6 +630,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); - 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/ipq807x/patches-5.10/607-qca-nss-ecm-Add-bridge-join-and-leave-netdev-cmds.patch b/target/linux/ipq807x/patches-5.10/607-qca-nss-ecm-Add-bridge-join-and-leave-netdev-cmds.patch deleted file mode 100644 index 69e553528..000000000 --- a/target/linux/ipq807x/patches-5.10/607-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 -@@ -1802,7 +1802,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/ipq807x/patches-5.10/720-net-phy-add-aqr-phys.patch b/target/linux/ipq807x/patches-5.10/720-net-phy-add-aqr-phys.patch deleted file mode 100644 index e90447e0c..000000000 --- a/target/linux/ipq807x/patches-5.10/720-net-phy-add-aqr-phys.patch +++ /dev/null @@ -1,142 +0,0 @@ -From: Birger Koblitz -Date: Sun, 5 Sep 2021 15:13:10 +0200 -Subject: [PATCH] kernel: Add AQR113C and AQR813 support - -This hack adds support for the Aquantia 4th generation, 10GBit -PHYs AQR113C and AQR813. - -Signed-off-by: Birger Koblitz - ---- a/drivers/net/phy/aquantia_main.c -+++ b/drivers/net/phy/aquantia_main.c -@@ -20,8 +20,10 @@ - #define PHY_ID_AQR105 0x03a1b4a2 - #define PHY_ID_AQR106 0x03a1b4d0 - #define PHY_ID_AQR107 0x03a1b4e0 -+#define PHY_ID_AQR113C 0x31c31c12 - #define PHY_ID_AQCS109 0x03a1b5c2 - #define PHY_ID_AQR405 0x03a1b4b0 -+#define PHY_ID_AQR813 0x31c31cb2 - - #define MDIO_PHYXS_VEND_IF_STATUS 0xe812 - #define MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK GENMASK(7, 3) -@@ -352,6 +354,49 @@ static int aqr107_read_rate(struct phy_d - return 0; - } - -+static int aqr113c_read_status(struct phy_device *phydev) -+{ -+ int val, ret; -+ -+ ret = aqr_read_status(phydev); -+ if (ret) -+ return ret; -+ -+ if (!phydev->link || phydev->autoneg == AUTONEG_DISABLE) -+ return 0; -+ -+ // On AQR113C, the speed returned by aqr_read_status is wrong -+ aqr107_read_rate(phydev); -+ -+ val = phy_read_mmd(phydev, MDIO_MMD_PHYXS, MDIO_PHYXS_VEND_IF_STATUS); -+ if (val < 0) -+ return val; -+ -+ switch (FIELD_GET(MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK, val)) { -+ case MDIO_PHYXS_VEND_IF_STATUS_TYPE_KR: -+ phydev->interface = PHY_INTERFACE_MODE_10GKR; -+ break; -+ case MDIO_PHYXS_VEND_IF_STATUS_TYPE_XFI: -+ phydev->interface = PHY_INTERFACE_MODE_10GBASER; -+ break; -+ case MDIO_PHYXS_VEND_IF_STATUS_TYPE_USXGMII: -+ phydev->interface = PHY_INTERFACE_MODE_USXGMII; -+ break; -+ case MDIO_PHYXS_VEND_IF_STATUS_TYPE_SGMII: -+ phydev->interface = PHY_INTERFACE_MODE_SGMII; -+ break; -+ case MDIO_PHYXS_VEND_IF_STATUS_TYPE_OCSGMII: -+ phydev->interface = PHY_INTERFACE_MODE_2500BASEX; -+ break; -+ default: -+ phydev->interface = PHY_INTERFACE_MODE_NA; -+ break; -+ } -+ -+ /* Read downshifted rate from vendor register */ -+ return aqr107_read_rate(phydev); -+} -+ - static int aqr107_read_status(struct phy_device *phydev) - { - int val, ret; -@@ -482,7 +527,7 @@ static void aqr107_chip_info(struct phy_ - build_id = FIELD_GET(VEND1_GLOBAL_RSVD_STAT1_FW_BUILD_ID, val); - prov_id = FIELD_GET(VEND1_GLOBAL_RSVD_STAT1_PROV_ID, val); - -- phydev_dbg(phydev, "FW %u.%u, Build %u, Provisioning %u\n", -+ phydev_info(phydev, "FW %u.%u, Build %u, Provisioning %u\n", - fw_major, fw_minor, build_id, prov_id); - } - -@@ -690,6 +735,24 @@ static struct phy_driver aqr_driver[] = - .link_change_notify = aqr107_link_change_notify, - }, - { -+ PHY_ID_MATCH_MODEL(PHY_ID_AQR113C), -+ .name = "Aquantia AQR113C", -+ .probe = aqr107_probe, -+ .config_init = aqr107_config_init, -+ .config_aneg = aqr_config_aneg, -+ .config_intr = aqr_config_intr, -+ .ack_interrupt = aqr_ack_interrupt, -+ .read_status = aqr113c_read_status, -+ .get_tunable = aqr107_get_tunable, -+ .set_tunable = aqr107_set_tunable, -+ .suspend = aqr107_suspend, -+ .resume = aqr107_resume, -+ .get_sset_count = aqr107_get_sset_count, -+ .get_strings = aqr107_get_strings, -+ .get_stats = aqr107_get_stats, -+ .link_change_notify = aqr107_link_change_notify, -+}, -+{ - PHY_ID_MATCH_MODEL(PHY_ID_AQCS109), - .name = "Aquantia AQCS109", - .probe = aqr107_probe, -@@ -715,6 +778,24 @@ static struct phy_driver aqr_driver[] = - .ack_interrupt = aqr_ack_interrupt, - .read_status = aqr_read_status, - }, -+{ -+ PHY_ID_MATCH_MODEL(PHY_ID_AQR813), -+ .name = "Aquantia AQR813", -+ .probe = aqr107_probe, -+ .config_init = aqr107_config_init, -+ .config_aneg = aqr_config_aneg, -+ .config_intr = aqr_config_intr, -+ .ack_interrupt = aqr_ack_interrupt, -+ .read_status = aqr113c_read_status, -+ .get_tunable = aqr107_get_tunable, -+ .set_tunable = aqr107_set_tunable, -+ .suspend = aqr107_suspend, -+ .resume = aqr107_resume, -+ .get_sset_count = aqr107_get_sset_count, -+ .get_strings = aqr107_get_strings, -+ .get_stats = aqr107_get_stats, -+ .link_change_notify = aqr107_link_change_notify, -+}, - }; - - module_phy_driver(aqr_driver); -@@ -725,8 +806,10 @@ static struct mdio_device_id __maybe_unu - { PHY_ID_MATCH_MODEL(PHY_ID_AQR105) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQR106) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQR107) }, -+ { PHY_ID_MATCH_MODEL(PHY_ID_AQR113C) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQCS109) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQR405) }, -+ { PHY_ID_MATCH_MODEL(PHY_ID_AQR813) }, - { } - }; - diff --git a/target/linux/ipq807x/patches-5.10/722-net-phy-aquantia-enable-AQR112-and-AQR412.patch b/target/linux/ipq807x/patches-5.10/722-net-phy-aquantia-enable-AQR112-and-AQR412.patch deleted file mode 100644 index 42bf8951d..000000000 --- a/target/linux/ipq807x/patches-5.10/722-net-phy-aquantia-enable-AQR112-and-AQR412.patch +++ /dev/null @@ -1,154 +0,0 @@ -From 5f62951fba63a9f9cfff564209426bdea5fcc371 Mon Sep 17 00:00:00 2001 -From: Alex Marginean -Date: Tue, 27 Aug 2019 15:16:56 +0300 -Subject: [PATCH] drivers: net: phy: aquantia: enable AQR112 and AQR412 - -Adds support for AQR112 and AQR412 which is mostly based on existing code -with the addition of code configuring the protocol on system side. -This allows changing the system side protocol without having to deploy a -different firmware on the PHY. - -Signed-off-by: Alex Marginean ---- - drivers/net/phy/aquantia_main.c | 88 +++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 88 insertions(+) - ---- a/drivers/net/phy/aquantia_main.c -+++ b/drivers/net/phy/aquantia_main.c -@@ -20,9 +20,11 @@ - #define PHY_ID_AQR105 0x03a1b4a2 - #define PHY_ID_AQR106 0x03a1b4d0 - #define PHY_ID_AQR107 0x03a1b4e0 -+#define PHY_ID_AQR112 0x03a1b662 - #define PHY_ID_AQR113C 0x31c31c12 - #define PHY_ID_AQCS109 0x03a1b5c2 - #define PHY_ID_AQR405 0x03a1b4b0 -+#define PHY_ID_AQR412 0x03a1b712 - #define PHY_ID_AQR813 0x31c31cb2 - - #define MDIO_PHYXS_VEND_IF_STATUS 0xe812 -@@ -134,6 +136,29 @@ - #define AQR107_OP_IN_PROG_SLEEP 1000 - #define AQR107_OP_IN_PROG_TIMEOUT 100000 - -+/* registers in MDIO_MMD_VEND1 region */ -+#define AQUANTIA_VND1_GLOBAL_SC 0x000 -+#define AQUANTIA_VND1_GLOBAL_SC_LP BIT(0xb) -+ -+/* global start rate, the protocol associated with this speed is used by default -+ * on SI. -+ */ -+#define AQUANTIA_VND1_GSTART_RATE 0x31a -+#define AQUANTIA_VND1_GSTART_RATE_OFF 0 -+#define AQUANTIA_VND1_GSTART_RATE_100M 1 -+#define AQUANTIA_VND1_GSTART_RATE_1G 2 -+#define AQUANTIA_VND1_GSTART_RATE_10G 3 -+#define AQUANTIA_VND1_GSTART_RATE_2_5G 4 -+#define AQUANTIA_VND1_GSTART_RATE_5G 5 -+ -+/* SYSCFG registers for 100M, 1G, 2.5G, 5G, 10G */ -+#define AQUANTIA_VND1_GSYSCFG_BASE 0x31b -+#define AQUANTIA_VND1_GSYSCFG_100M 0 -+#define AQUANTIA_VND1_GSYSCFG_1G 1 -+#define AQUANTIA_VND1_GSYSCFG_2_5G 2 -+#define AQUANTIA_VND1_GSYSCFG_5G 3 -+#define AQUANTIA_VND1_GSYSCFG_10G 4 -+ - struct aqr107_hw_stat { - const char *name; - int reg; -@@ -265,6 +290,51 @@ static int aqr_config_aneg(struct phy_de - return genphy_c45_check_and_restart_aneg(phydev, changed); - } - -+static struct { -+ u16 syscfg; -+ int cnt; -+ u16 start_rate; -+} aquantia_syscfg[PHY_INTERFACE_MODE_MAX] = { -+ [PHY_INTERFACE_MODE_SGMII] = {0x04b, AQUANTIA_VND1_GSYSCFG_1G, -+ AQUANTIA_VND1_GSTART_RATE_1G}, -+ [PHY_INTERFACE_MODE_2500BASEX] = {0x144, AQUANTIA_VND1_GSYSCFG_2_5G, -+ AQUANTIA_VND1_GSTART_RATE_2_5G}, -+ [PHY_INTERFACE_MODE_XGMII] = {0x100, AQUANTIA_VND1_GSYSCFG_10G, -+ AQUANTIA_VND1_GSTART_RATE_10G}, -+ [PHY_INTERFACE_MODE_USXGMII] = {0x080, AQUANTIA_VND1_GSYSCFG_10G, -+ AQUANTIA_VND1_GSTART_RATE_10G}, -+}; -+ -+/* Sets up protocol on system side before calling aqr_config_aneg */ -+static int aqr_config_aneg_set_prot(struct phy_device *phydev) -+{ -+ int if_type = phydev->interface; -+ int i; -+ -+ if (!aquantia_syscfg[if_type].cnt) -+ return 0; -+ -+ /* set PHY in low power mode so we can configure protocols */ -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, AQUANTIA_VND1_GLOBAL_SC, -+ AQUANTIA_VND1_GLOBAL_SC_LP); -+ mdelay(10); -+ -+ /* set the default rate to enable the SI link */ -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, AQUANTIA_VND1_GSTART_RATE, -+ aquantia_syscfg[if_type].start_rate); -+ -+ for (i = 0; i <= aquantia_syscfg[if_type].cnt; i++) -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, -+ AQUANTIA_VND1_GSYSCFG_BASE + i, -+ aquantia_syscfg[if_type].syscfg); -+ -+ /* wake PHY back up */ -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, AQUANTIA_VND1_GLOBAL_SC, 0); -+ mdelay(10); -+ -+ return aqr_config_aneg(phydev); -+} -+ - static int aqr_config_intr(struct phy_device *phydev) - { - bool en = phydev->interrupts == PHY_INTERRUPT_ENABLED; -@@ -796,6 +866,30 @@ static struct phy_driver aqr_driver[] = - .get_stats = aqr107_get_stats, - .link_change_notify = aqr107_link_change_notify, - }, -+{ -+ PHY_ID_MATCH_MODEL(PHY_ID_AQR112), -+ .name = "Aquantia AQR112", -+ .probe = aqr107_probe, -+ .config_aneg = aqr_config_aneg_set_prot, -+ .config_intr = aqr_config_intr, -+ .ack_interrupt = aqr_ack_interrupt, -+ .read_status = aqr107_read_status, -+ .get_sset_count = aqr107_get_sset_count, -+ .get_strings = aqr107_get_strings, -+ .get_stats = aqr107_get_stats, -+}, -+{ -+ PHY_ID_MATCH_MODEL(PHY_ID_AQR412), -+ .name = "Aquantia AQR412", -+ .probe = aqr107_probe, -+ .config_aneg = aqr_config_aneg_set_prot, -+ .config_intr = aqr_config_intr, -+ .ack_interrupt = aqr_ack_interrupt, -+ .read_status = aqr107_read_status, -+ .get_sset_count = aqr107_get_sset_count, -+ .get_strings = aqr107_get_strings, -+ .get_stats = aqr107_get_stats, -+}, - }; - - module_phy_driver(aqr_driver); -@@ -806,9 +900,11 @@ static struct mdio_device_id __maybe_unu - { PHY_ID_MATCH_MODEL(PHY_ID_AQR105) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQR106) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQR107) }, -+ { PHY_ID_MATCH_MODEL(PHY_ID_AQR112) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQR113C) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQCS109) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQR405) }, -+ { PHY_ID_MATCH_MODEL(PHY_ID_AQR412) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQR813) }, - { } - }; diff --git a/target/linux/ipq807x/patches-5.10/723-net-phy-aquantia-fix-system-side-protocol-mi.patch b/target/linux/ipq807x/patches-5.10/723-net-phy-aquantia-fix-system-side-protocol-mi.patch deleted file mode 100644 index c65f273a8..000000000 --- a/target/linux/ipq807x/patches-5.10/723-net-phy-aquantia-fix-system-side-protocol-mi.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 5f008cb22f60da4e10375f22266c1a4e20b1252e Mon Sep 17 00:00:00 2001 -From: Alex Marginean -Date: Fri, 20 Sep 2019 18:22:52 +0300 -Subject: [PATCH] drivers: net: phy: aquantia: fix system side protocol - misconfiguration - -Do not set up protocols for speeds that are not supported by FW. Enabling -these protocols leads to link issues on system side. - -Signed-off-by: Alex Marginean ---- - drivers/net/phy/aquantia_main.c | 8 +++++++- - 1 file changed, 7 insertions(+), 1 deletion(-) - ---- a/drivers/net/phy/aquantia_main.c -+++ b/drivers/net/phy/aquantia_main.c -@@ -323,10 +323,16 @@ static int aqr_config_aneg_set_prot(stru - phy_write_mmd(phydev, MDIO_MMD_VEND1, AQUANTIA_VND1_GSTART_RATE, - aquantia_syscfg[if_type].start_rate); - -- for (i = 0; i <= aquantia_syscfg[if_type].cnt; i++) -+ for (i = 0; i <= aquantia_syscfg[if_type].cnt; i++) { -+ u16 reg = phy_read_mmd(phydev, MDIO_MMD_VEND1, -+ AQUANTIA_VND1_GSYSCFG_BASE + i); -+ if (!reg) -+ continue; -+ - phy_write_mmd(phydev, MDIO_MMD_VEND1, - AQUANTIA_VND1_GSYSCFG_BASE + i, - aquantia_syscfg[if_type].syscfg); -+ } - - /* wake PHY back up */ - phy_write_mmd(phydev, MDIO_MMD_VEND1, AQUANTIA_VND1_GLOBAL_SC, 0); diff --git a/target/linux/ipq807x/patches-5.10/724-net-phy-aquantia-Add-AQR113-driver-support.patch b/target/linux/ipq807x/patches-5.10/724-net-phy-aquantia-Add-AQR113-driver-support.patch deleted file mode 100644 index 8fd3b018b..000000000 --- a/target/linux/ipq807x/patches-5.10/724-net-phy-aquantia-Add-AQR113-driver-support.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 2e677e4ae8f8330f68013163b060d0fda3a43095 Mon Sep 17 00:00:00 2001 -From: "Langer, Thomas" -Date: Fri, 9 Jul 2021 17:36:46 +0200 -Subject: [PATCH] PONRTSYS-8842: aquantia: Add AQR113 driver support - -Add a new entry for AQR113 PHY_ID ---- - drivers/net/phy/aquantia_main.c | 10 ++++++++++ - 1 file changed, 10 insertions(+) - ---- a/drivers/net/phy/aquantia_main.c -+++ b/drivers/net/phy/aquantia_main.c -@@ -21,6 +21,7 @@ - #define PHY_ID_AQR106 0x03a1b4d0 - #define PHY_ID_AQR107 0x03a1b4e0 - #define PHY_ID_AQR112 0x03a1b662 -+#define PHY_ID_AQR113 0x31c31c40 - #define PHY_ID_AQR113C 0x31c31c12 - #define PHY_ID_AQCS109 0x03a1b5c2 - #define PHY_ID_AQR405 0x03a1b4b0 -@@ -885,6 +886,14 @@ static struct phy_driver aqr_driver[] = - .get_stats = aqr107_get_stats, - }, - { -+ PHY_ID_MATCH_MODEL(PHY_ID_AQR113), -+ .name = "Aquantia AQR113", -+ .config_aneg = aqr_config_aneg, -+ .config_intr = aqr_config_intr, -+ .ack_interrupt = aqr_ack_interrupt, -+ .read_status = aqr107_read_status, -+}, -+{ - PHY_ID_MATCH_MODEL(PHY_ID_AQR412), - .name = "Aquantia AQR412", - .probe = aqr107_probe, -@@ -907,6 +916,7 @@ static struct mdio_device_id __maybe_unu - { PHY_ID_MATCH_MODEL(PHY_ID_AQR106) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQR107) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQR112) }, -+ { PHY_ID_MATCH_MODEL(PHY_ID_AQR113) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQR113C) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQCS109) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQR405) }, diff --git a/target/linux/ipq807x/patches-5.10/725-net-phy-aquantia-add-PHY_IDs-for-AQR112-variants.patch b/target/linux/ipq807x/patches-5.10/725-net-phy-aquantia-add-PHY_IDs-for-AQR112-variants.patch deleted file mode 100644 index f2db552a1..000000000 --- a/target/linux/ipq807x/patches-5.10/725-net-phy-aquantia-add-PHY_IDs-for-AQR112-variants.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 3b92ee7b7899b6beffb2b484c58326e36612a873 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Thu, 23 Dec 2021 14:52:56 +0000 -Subject: [PATCH] net: phy: aquantia: add PHY_ID for AQR112R - -As advised by Ian Chang this PHY is used in Puzzle devices. - -Signed-off-by: Daniel Golle ---- - drivers/net/phy/aquantia_main.c | 10 ++++++++++ - 1 file changed, 10 insertions(+) - ---- a/drivers/net/phy/aquantia_main.c -+++ b/drivers/net/phy/aquantia_main.c -@@ -21,6 +21,8 @@ - #define PHY_ID_AQR106 0x03a1b4d0 - #define PHY_ID_AQR107 0x03a1b4e0 - #define PHY_ID_AQR112 0x03a1b662 -+#define PHY_ID_AQR112C 0x03a1b790 -+#define PHY_ID_AQR112R 0x31c31d12 - #define PHY_ID_AQR113 0x31c31c40 - #define PHY_ID_AQR113C 0x31c31c12 - #define PHY_ID_AQCS109 0x03a1b5c2 -@@ -886,6 +888,30 @@ static struct phy_driver aqr_driver[] = - .get_stats = aqr107_get_stats, - }, - { -+ PHY_ID_MATCH_MODEL(PHY_ID_AQR112C), -+ .name = "Aquantia AQR112C", -+ .probe = aqr107_probe, -+ .config_aneg = aqr_config_aneg_set_prot, -+ .config_intr = aqr_config_intr, -+ .ack_interrupt = aqr_ack_interrupt, -+ .read_status = aqr107_read_status, -+ .get_sset_count = aqr107_get_sset_count, -+ .get_strings = aqr107_get_strings, -+ .get_stats = aqr107_get_stats, -+}, -+{ -+ PHY_ID_MATCH_MODEL(PHY_ID_AQR112R), -+ .name = "Aquantia AQR112R", -+ .probe = aqr107_probe, -+ .config_aneg = aqr_config_aneg_set_prot, -+ .config_intr = aqr_config_intr, -+ .ack_interrupt = aqr_ack_interrupt, -+ .read_status = aqr107_read_status, -+ .get_sset_count = aqr107_get_sset_count, -+ .get_strings = aqr107_get_strings, -+ .get_stats = aqr107_get_stats, -+}, -+{ - PHY_ID_MATCH_MODEL(PHY_ID_AQR113), - .name = "Aquantia AQR113", - .config_aneg = aqr_config_aneg, -@@ -916,6 +942,8 @@ static struct mdio_device_id __maybe_unu - { PHY_ID_MATCH_MODEL(PHY_ID_AQR106) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQR107) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQR112) }, -+ { PHY_ID_MATCH_MODEL(PHY_ID_AQR112C) }, -+ { PHY_ID_MATCH_MODEL(PHY_ID_AQR112R) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQR113) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQR113C) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQCS109) }, diff --git a/target/linux/ipq807x/patches-5.10/900-arm64-dts-add-OpenWrt-DTS-files.patch b/target/linux/ipq807x/patches-5.10/900-arm64-dts-add-OpenWrt-DTS-files.patch deleted file mode 100644 index 47139bc71..000000000 --- a/target/linux/ipq807x/patches-5.10/900-arm64-dts-add-OpenWrt-DTS-files.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 8aec79b6d4d59616eb6ce4fbfb94658b3e79d9ce Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Tue, 11 May 2021 13:29:33 +0200 -Subject: [PATCH] arm64: dts: add OpenWrt DTS files - -Lets add custom OpenWrt DTS files to Makefile. - -Signed-off-by: Robert Marko ---- - 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 -@@ -3,6 +3,13 @@ dtb-$(CONFIG_ARCH_QCOM) += apq8016-sbc.d - 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) += ipq8072-301w.dtb -+dtb-$(CONFIG_ARCH_QCOM) += ipq8071-ax6.dtb -+dtb-$(CONFIG_ARCH_QCOM) += ipq8071-ax3600.dtb -+dtb-$(CONFIG_ARCH_QCOM) += ipq8071-mf269.dtb -+dtb-$(CONFIG_ARCH_QCOM) += ipq8078-xtr10890.dtb -+dtb-$(CONFIG_ARCH_QCOM) += ipq8070-tl-er2260t.dtb -+dtb-$(CONFIG_ARCH_QCOM) += ipq8074-nbg7815.dtb - dtb-$(CONFIG_ARCH_QCOM) += ipq8074-hk01.dtb - dtb-$(CONFIG_ARCH_QCOM) += msm8916-longcheer-l8150.dtb - dtb-$(CONFIG_ARCH_QCOM) += msm8916-mtp.dtb diff --git a/target/linux/ipq807x/patches-5.10/901-soc-qcom-Make-QMI-Helpers-user-selectable.patch b/target/linux/ipq807x/patches-5.10/901-soc-qcom-Make-QMI-Helpers-user-selectable.patch deleted file mode 100644 index 9d70edd15..000000000 --- a/target/linux/ipq807x/patches-5.10/901-soc-qcom-Make-QMI-Helpers-user-selectable.patch +++ /dev/null @@ -1,28 +0,0 @@ -From b9b94712847f8fa6ca8dc03422ba9e0332b6997d Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Thu, 13 May 2021 14:54:43 +0200 -Subject: [PATCH] soc: qcom: Make QMI Helpers user selectable - -Wireless backports for ath11k have a different logic -then upstream as they depend on QMI helpers instead -of selecting them. - -So, to make it possible to select QMI helpers -through KConfig add text to tristate. - -Signed-off-by: Robert Marko ---- - drivers/soc/qcom/Kconfig | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/soc/qcom/Kconfig -+++ b/drivers/soc/qcom/Kconfig -@@ -93,7 +93,7 @@ config QCOM_PDR_HELPERS - select QCOM_QMI_HELPERS - - config QCOM_QMI_HELPERS -- tristate -+ tristate "Qualcomm QMI helpers" - depends on NET - - config QCOM_RMTFS_MEM diff --git a/target/linux/ipq807x/patches-5.10/902-arm64-provide-dma-cache-routines-with-same-API-as-32.patch b/target/linux/ipq807x/patches-5.10/902-arm64-provide-dma-cache-routines-with-same-API-as-32.patch deleted file mode 100644 index a682bb259..000000000 --- a/target/linux/ipq807x/patches-5.10/902-arm64-provide-dma-cache-routines-with-same-API-as-32.patch +++ /dev/null @@ -1,56 +0,0 @@ -From 181e506248fd24a0febbfbd794bba43a7b346115 Mon Sep 17 00:00:00 2001 -From: Kathiravan T -Date: Fri, 17 Jan 2014 10:33:08 -0800 -Subject: [PATCH] arm64: provide dma cache routines with same API as 32 bit - -The APIs __dma_inv_range() and __dma_clean_range() were -not exported by the third party patch. Since the functions -starting with underscores are not to be directly used by drivers, -related functions without the underscores are provided -which have the same name and functionality as the 32 bit APIs. - -CRs-Fixed: 1053067 -Change-Id: Ie0e681614307d9d9a19e58cacfb9b5dff4528977 - -arm64: add defines for dmac_*_range for compatibility with arm32 - -An earlier patch created defines for dma_*_range APIs to be -compatible with arm 32 bit, however it appears -these API names have not (at least yet) appeared there, so -revise the names to dmac_*_range, which is defined -for arm 32 bit so that there is one name defined -for both architectures. - -CRs-Fixed: 1053067 -Signed-off-by: Larry Bassel -(cherry picked from commit 0930bab0db67cc0d91e52e385e3e061871c6be05) -[psodagud: fixed up trivial merge conflicts and warnings] -Signed-off-by: Prasad Sodagudi - -(cherry picked from commit a313e54567627a1fd96cd267e2c6c358d14e468c) -[kathirav: fixed the trivial conflicts] - -Change-Id: I6456c02bad73fb54a874dc9925d3d43d9b8be2f2 -Signed-off-by: Kathiravan T ---- - 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 -@@ -102,6 +102,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, size_t size); -+extern void __dma_clean_area(const void *start, size_t size); -+ -+#define dmac_flush_range(start, end) \ -+ __dma_flush_area(start, (void *)(end) - (void *)(start)) -+#define dmac_inv_range(start, end) \ -+ __dma_inv_area(start, (void *)(end) - (void *)(start)) -+#define dmac_clean_range(start, end) \ -+ __dma_clean_area(start, (void *)(end) - (void *)(start)) - - /* - * Copy user data from/to a page which is mapped into a different diff --git a/target/linux/ipq807x/patches-5.10/903-arm64-mm-export-__dma_inv_area-and-__dma_clean_area.patch b/target/linux/ipq807x/patches-5.10/903-arm64-mm-export-__dma_inv_area-and-__dma_clean_area.patch deleted file mode 100644 index 865a7a9d5..000000000 --- a/target/linux/ipq807x/patches-5.10/903-arm64-mm-export-__dma_inv_area-and-__dma_clean_area.patch +++ /dev/null @@ -1,58 +0,0 @@ -From da0c8f67d9aca417a441af4fb90acf65eef94585 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Thu, 13 May 2021 23:44:07 +0200 -Subject: [PATCH] arm64: mm: export __dma_inv_area and __dma_clean_area - -Qualcomm NSS drivers use these extensively. - -Signed-off-by: Robert Marko ---- - 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 -@@ -102,8 +102,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, size_t size); --extern void __dma_clean_area(const void *start, size_t size); -+extern void __dma_inv_area(const void *, size_t); -+extern void __dma_clean_area(const void *, size_t); - - #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 -@@ -138,7 +138,7 @@ SYM_FUNC_END(__clean_dcache_area_pou) - * - kaddr - kernel address - * - size - size in question - */ --SYM_FUNC_START_LOCAL(__dma_inv_area) -+SYM_FUNC_START(__dma_inv_area) - SYM_FUNC_START_PI(__inval_dcache_area) - /* FALLTHROUGH */ - -@@ -177,7 +177,7 @@ SYM_FUNC_END(__dma_inv_area) - * - kaddr - kernel address - * - size - size in question - */ --SYM_FUNC_START_LOCAL(__dma_clean_area) -+SYM_FUNC_START(__dma_clean_area) - SYM_FUNC_START_PI(__clean_dcache_area_poc) - /* FALLTHROUGH */ - ---- a/arch/arm64/mm/flush.c -+++ b/arch/arm64/mm/flush.c -@@ -78,6 +78,8 @@ EXPORT_SYMBOL(flush_dcache_page); - * Additional functions defined in assembly. - */ - EXPORT_SYMBOL(__flush_icache_range); -+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/ipq807x/patches-5.10/991-clk-qcom-add-support-for-hw-controlled-RCG.patch b/target/linux/ipq807x/patches-5.10/991-clk-qcom-add-support-for-hw-controlled-RCG.patch deleted file mode 100644 index 6512b6f46..000000000 --- a/target/linux/ipq807x/patches-5.10/991-clk-qcom-add-support-for-hw-controlled-RCG.patch +++ /dev/null @@ -1,136 +0,0 @@ -From 0245360f8e118b67f4015533cfc79314f2d848d5 Mon Sep 17 00:00:00 2001 -From: Praveenkumar I -Date: Tue, 13 Jun 2017 15:30:39 +0530 -Subject: [PATCH 2/3] 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 in this case. The check for update bit can be -skipped in this case. - -Signed-off-by: Abhishek Sahu -(cherry picked from commit 84dd0e12f10eebff44a464eb8455205abc4b4178) -Signed-off-by: Praveenkumar I - -Change-Id: Ifb4175b02d89542baa1b758107c2ce86f7bf8599 ---- - drivers/clk/qcom/clk-rcg.h | 4 ++++ - drivers/clk/qcom/clk-rcg2.c | 27 +++++++++++++++++++++------ - 2 files changed, 25 insertions(+), 6 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 -@@ -97,7 +97,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; -@@ -109,6 +109,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); -@@ -127,14 +130,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); - } - - /* -@@ -305,12 +313,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, -@@ -790,7 +805,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, -@@ -902,7 +917,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; - -@@ -933,7 +948,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/ipq807x/patches-5.10/992-clk-qcom-ipq8074-add-hw-controlled-flag.patch b/target/linux/ipq807x/patches-5.10/992-clk-qcom-ipq8074-add-hw-controlled-flag.patch deleted file mode 100644 index 2b11b7c01..000000000 --- a/target/linux/ipq807x/patches-5.10/992-clk-qcom-ipq8074-add-hw-controlled-flag.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 18d04f5cae30725ffa0c1c025f6beb1821c46857 Mon Sep 17 00:00:00 2001 -From: Praveenkumar I -Date: Tue, 13 Jun 2017 15:31:34 +0530 -Subject: [PATCH 3/3] clk: qcom: ipq8074: add hw controlled flag -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -These RCG’s are hw controlled so add the -CLK_RCG2_HW_CONTROLLED flag. - -Signed-off-by: Abhishek Sahu -(cherry picked from commit 9a025b8271a95a80e9e769b89154b98b263be860) -Signed-off-by: Praveenkumar I - -Change-Id: Ic5da1551bf46921890955312026b9175a42fe14e ---- - drivers/clk/qcom/gcc-ipq8074.c | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/drivers/clk/qcom/gcc-ipq8074.c -+++ b/drivers/clk/qcom/gcc-ipq8074.c -@@ -637,6 +637,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_names = gcc_xo_gpll0_gpll0_out_main_div2, -@@ -1311,6 +1312,7 @@ 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_names = gcc_xo_gpll0_gpll6_gpll0_out_main_div2, diff --git a/target/linux/ipq807x/patches-5.10/998-regulator-add-Qualcomm-CPR-regulators.patch b/target/linux/ipq807x/patches-5.10/998-regulator-add-Qualcomm-CPR-regulators.patch deleted file mode 100644 index 7b5669bf2..000000000 --- a/target/linux/ipq807x/patches-5.10/998-regulator-add-Qualcomm-CPR-regulators.patch +++ /dev/null @@ -1,466 +0,0 @@ ---- /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/ipq807x/patches-5.10/999-5.10-qca-nss-ssdk-delete-fdb-entry-using-netdev.patch b/target/linux/ipq807x/patches-5.10/999-5.10-qca-nss-ssdk-delete-fdb-entry-using-netdev.patch deleted file mode 100644 index 15ce2ce4a..000000000 --- a/target/linux/ipq807x/patches-5.10/999-5.10-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 -@@ -201,4 +201,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 -@@ -1181,6 +1181,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/ipq807x/patches-5.15/0001-v5.16-arm64-dts-qcom-ipq8074-add-SPMI-bus.patch b/target/linux/ipq807x/patches-5.15/0001-v5.16-arm64-dts-qcom-ipq8074-add-SPMI-bus.patch deleted file mode 100644 index 1679c25ba..000000000 --- a/target/linux/ipq807x/patches-5.15/0001-v5.16-arm64-dts-qcom-ipq8074-add-SPMI-bus.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 63750607afad67e57841689b01a9425822503e0c Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Sun, 5 Sep 2021 18:58:16 +0200 -Subject: [PATCH] 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/ipq807x/patches-5.15/0002-v5.16-arm64-dts-qcom-ipq8074-Add-QUP5-I2C-node.patch b/target/linux/ipq807x/patches-5.15/0002-v5.16-arm64-dts-qcom-ipq8074-Add-QUP5-I2C-node.patch deleted file mode 100644 index 329dcf3aa..000000000 --- a/target/linux/ipq807x/patches-5.15/0002-v5.16-arm64-dts-qcom-ipq8074-Add-QUP5-I2C-node.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 9c0bd8e53774c38bd7859ad4af300a5062430925 Mon Sep 17 00:00:00 2001 -From: Chukun Pan -Date: Fri, 1 Oct 2021 22:54:21 +0800 -Subject: [PATCH] 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/ipq807x/patches-5.15/0003-v5.16-arm64-dts-qcom-msm8996-Move-clock-cells-to-QMP-PHY-c.patch b/target/linux/ipq807x/patches-5.15/0003-v5.16-arm64-dts-qcom-msm8996-Move-clock-cells-to-QMP-PHY-c.patch deleted file mode 100644 index 5fec26c43..000000000 --- a/target/linux/ipq807x/patches-5.15/0003-v5.16-arm64-dts-qcom-msm8996-Move-clock-cells-to-QMP-PHY-c.patch +++ /dev/null @@ -1,134 +0,0 @@ -From 82d61e19fccbf2fe7c018765b3799791916e7f31 Mon Sep 17 00:00:00 2001 -From: Shawn Guo -Date: Wed, 29 Sep 2021 11:42:46 +0800 -Subject: [PATCH] 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 ++-- - arch/arm64/boot/dts/qcom/msm8996.dtsi | 4 ++-- - arch/arm64/boot/dts/qcom/msm8998.dtsi | 2 +- - arch/arm64/boot/dts/qcom/sm8350.dtsi | 3 --- - 4 files changed, 5 insertions(+), 8 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"; ---- a/arch/arm64/boot/dts/qcom/msm8996.dtsi -+++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi -@@ -602,7 +602,6 @@ - pcie_phy: phy@34000 { - compatible = "qcom,msm8996-qmp-pcie-phy"; - reg = <0x00034000 0x488>; -- #clock-cells = <1>; - #address-cells = <1>; - #size-cells = <1>; - ranges; -@@ -624,6 +623,7 @@ - <0x00035400 0x1dc>; - #phy-cells = <0>; - -+ #clock-cells = <1>; - clock-output-names = "pcie_0_pipe_clk_src"; - clocks = <&gcc GCC_PCIE_0_PIPE_CLK>; - clock-names = "pipe0"; -@@ -2620,7 +2620,6 @@ - usb3phy: phy@7410000 { - compatible = "qcom,msm8996-qmp-usb3-phy"; - reg = <0x07410000 0x1c4>; -- #clock-cells = <1>; - #address-cells = <1>; - #size-cells = <1>; - ranges; -@@ -2641,6 +2640,7 @@ - <0x07410600 0x1a8>; - #phy-cells = <0>; - -+ #clock-cells = <1>; - clock-output-names = "usb3_phy_pipe_clk_src"; - clocks = <&gcc GCC_USB3_PHY_PIPE_CLK>; - clock-names = "pipe0"; ---- a/arch/arm64/boot/dts/qcom/msm8998.dtsi -+++ b/arch/arm64/boot/dts/qcom/msm8998.dtsi -@@ -1985,7 +1985,6 @@ - compatible = "qcom,msm8998-qmp-usb3-phy"; - reg = <0x0c010000 0x18c>; - status = "disabled"; -- #clock-cells = <1>; - #address-cells = <1>; - #size-cells = <1>; - ranges; -@@ -2006,6 +2005,7 @@ - <0xc010600 0x128>, - <0xc010800 0x200>; - #phy-cells = <0>; -+ #clock-cells = <1>; - clocks = <&gcc GCC_USB3_PHY_PIPE_CLK>; - clock-names = "pipe0"; - clock-output-names = "usb3_phy_pipe_clk_src"; ---- a/arch/arm64/boot/dts/qcom/sm8350.dtsi -+++ b/arch/arm64/boot/dts/qcom/sm8350.dtsi -@@ -1119,7 +1119,6 @@ - reg = <0 0x01d87000 0 0x1c4>; - #address-cells = <2>; - #size-cells = <2>; -- #clock-cells = <1>; - ranges; - clock-names = "ref", - "ref_aux"; -@@ -1254,7 +1253,6 @@ - <0 0x088e8000 0 0x20>; - reg-names = "reg-base", "dp_com"; - status = "disabled"; -- #clock-cells = <1>; - #address-cells = <2>; - #size-cells = <2>; - ranges; -@@ -1287,7 +1285,6 @@ - compatible = "qcom,sm8350-qmp-usb3-uni-phy"; - reg = <0 0x088eb000 0 0x200>; - status = "disabled"; -- #clock-cells = <1>; - #address-cells = <2>; - #size-cells = <2>; - ranges; diff --git a/target/linux/ipq807x/patches-5.15/0006-v5.17-arm64-dts-qcom-ipq8074-add-MDIO-bus.patch b/target/linux/ipq807x/patches-5.15/0006-v5.17-arm64-dts-qcom-ipq8074-add-MDIO-bus.patch deleted file mode 100644 index 40be96bb5..000000000 --- a/target/linux/ipq807x/patches-5.15/0006-v5.17-arm64-dts-qcom-ipq8074-add-MDIO-bus.patch +++ /dev/null @@ -1,36 +0,0 @@ -From d201f67714a302b12ad3d78b982963342939629c Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Thu, 7 Oct 2021 13:58:46 +0200 -Subject: [PATCH] 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/ipq807x/patches-5.15/0007-v5.16-soc-qcom-socinfo-Add-IPQ8074-family-ID-s.patch b/target/linux/ipq807x/patches-5.15/0007-v5.16-soc-qcom-socinfo-Add-IPQ8074-family-ID-s.patch deleted file mode 100644 index a344a4b27..000000000 --- a/target/linux/ipq807x/patches-5.15/0007-v5.16-soc-qcom-socinfo-Add-IPQ8074-family-ID-s.patch +++ /dev/null @@ -1,50 +0,0 @@ -From adfde5bbb4afd5e47371b74a0a4c9ec02fcc8d58 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Sun, 5 Sep 2021 19:11:31 +0200 -Subject: [PATCH] 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/ipq807x/patches-5.15/0011-v5.18-arm64-dts-ipq8074-add-SMEM-support.patch b/target/linux/ipq807x/patches-5.15/0011-v5.18-arm64-dts-ipq8074-add-SMEM-support.patch deleted file mode 100644 index 43e4a36b5..000000000 --- a/target/linux/ipq807x/patches-5.15/0011-v5.18-arm64-dts-ipq8074-add-SMEM-support.patch +++ /dev/null @@ -1,49 +0,0 @@ -From f63c96c02671c00871d180fb5b436e53f4847d3c Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Thu, 6 Jan 2022 22:25:12 +0100 -Subject: [PATCH] arm64: dts: 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 ---- - 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/ipq807x/patches-5.15/0103-phy-qcom-qmp-Add-IPQ8074-PCIe-Gen3-QMP-PHY-support.patch b/target/linux/ipq807x/patches-5.15/0103-phy-qcom-qmp-Add-IPQ8074-PCIe-Gen3-QMP-PHY-support.patch deleted file mode 100644 index 3c8306c62..000000000 --- a/target/linux/ipq807x/patches-5.15/0103-phy-qcom-qmp-Add-IPQ8074-PCIe-Gen3-QMP-PHY-support.patch +++ /dev/null @@ -1,369 +0,0 @@ -From 6fe752e3927ee9d9cad6ad197d5fe58c23a61935 Mon Sep 17 00:00:00 2001 -From: Sivaprakash Murugesan -Date: Wed, 29 Jul 2020 21:00:04 +0530 -Subject: [PATCH] phy: qcom-qmp: Add IPQ8074 PCIe Gen3 QMP PHY support - -IPQ8074 has two PCIe ports, One Gen2 and one Gen3 port. -Since support for Gen2 PHY is already available, add support for -PCIe Gen3 PHY. - -Co-developed-by: Selvam Sathappan Periakaruppan -Signed-off-by: Selvam Sathappan Periakaruppan -Signed-off-by: Sivaprakash Murugesan -Signed-off-by: Robert Marko ---- - drivers/phy/qualcomm/phy-qcom-pcie3-qmp.h | 139 ++++++++++++++++++ - drivers/phy/qualcomm/phy-qcom-qmp.c | 171 +++++++++++++++++++++- - 2 files changed, 308 insertions(+), 2 deletions(-) - create mode 100644 drivers/phy/qualcomm/phy-qcom-pcie3-qmp.h - ---- /dev/null -+++ b/drivers/phy/qualcomm/phy-qcom-pcie3-qmp.h -@@ -0,0 +1,139 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+ -+/* -+ * Copyright (c) 2020, The Linux Foundation. All rights reserved. -+ */ -+ -+#ifndef PHY_QCOM_PCIE_H -+#define PHY_QCOM_PCIE_H -+ -+/* QMP V2 PCIE PHY - Found in IPQ8074 gen3 port - QSERDES PLL registers */ -+#define QSERDES_PLL_BG_TIMER 0x00c -+#define QSERDES_PLL_SSC_PER1 0x01c -+#define QSERDES_PLL_SSC_PER2 0x020 -+#define QSERDES_PLL_SSC_STEP_SIZE1_MODE0 0x024 -+#define QSERDES_PLL_SSC_STEP_SIZE2_MODE0 0x028 -+#define QSERDES_PLL_SSC_STEP_SIZE1_MODE1 0x02c -+#define QSERDES_PLL_SSC_STEP_SIZE2_MODE1 0x030 -+#define QSERDES_PLL_BIAS_EN_CLKBUFLR_EN 0x03c -+#define QSERDES_PLL_CLK_ENABLE1 0x040 -+#define QSERDES_PLL_SYS_CLK_CTRL 0x044 -+#define QSERDES_PLL_SYSCLK_BUF_ENABLE 0x048 -+#define QSERDES_PLL_PLL_IVCO 0x050 -+#define QSERDES_PLL_LOCK_CMP1_MODE0 0x054 -+#define QSERDES_PLL_LOCK_CMP2_MODE0 0x058 -+#define QSERDES_PLL_LOCK_CMP1_MODE1 0x060 -+#define QSERDES_PLL_LOCK_CMP2_MODE1 0x064 -+#define QSERDES_PLL_BG_TRIM 0x074 -+#define QSERDES_PLL_CLK_EP_DIV_MODE0 0x078 -+#define QSERDES_PLL_CLK_EP_DIV_MODE1 0x07c -+#define QSERDES_PLL_CP_CTRL_MODE0 0x080 -+#define QSERDES_PLL_CP_CTRL_MODE1 0x084 -+#define QSERDES_PLL_PLL_RCTRL_MODE0 0x088 -+#define QSERDES_PLL_PLL_RCTRL_MODE1 0x08C -+#define QSERDES_PLL_PLL_CCTRL_MODE0 0x090 -+#define QSERDES_PLL_PLL_CCTRL_MODE1 0x094 -+#define QSERDES_PLL_BIAS_EN_CTRL_BY_PSM 0x0a4 -+#define QSERDES_PLL_SYSCLK_EN_SEL 0x0a8 -+#define QSERDES_PLL_RESETSM_CNTRL 0x0b0 -+#define QSERDES_PLL_LOCK_CMP_EN 0x0c4 -+#define QSERDES_PLL_DEC_START_MODE0 0x0cc -+#define QSERDES_PLL_DEC_START_MODE1 0x0d0 -+#define QSERDES_PLL_DIV_FRAC_START1_MODE0 0x0d8 -+#define QSERDES_PLL_DIV_FRAC_START2_MODE0 0x0dc -+#define QSERDES_PLL_DIV_FRAC_START3_MODE0 0x0e0 -+#define QSERDES_PLL_DIV_FRAC_START1_MODE1 0x0e4 -+#define QSERDES_PLL_DIV_FRAC_START2_MODE1 0x0e8 -+#define QSERDES_PLL_DIV_FRAC_START3_MODE1 0x0eC -+#define QSERDES_PLL_INTEGLOOP_GAIN0_MODE0 0x100 -+#define QSERDES_PLL_INTEGLOOP_GAIN1_MODE0 0x104 -+#define QSERDES_PLL_INTEGLOOP_GAIN0_MODE1 0x108 -+#define QSERDES_PLL_INTEGLOOP_GAIN1_MODE1 0x10c -+#define QSERDES_PLL_VCO_TUNE_MAP 0x120 -+#define QSERDES_PLL_VCO_TUNE1_MODE0 0x124 -+#define QSERDES_PLL_VCO_TUNE2_MODE0 0x128 -+#define QSERDES_PLL_VCO_TUNE1_MODE1 0x12c -+#define QSERDES_PLL_VCO_TUNE2_MODE1 0x130 -+#define QSERDES_PLL_VCO_TUNE_TIMER1 0x13c -+#define QSERDES_PLL_VCO_TUNE_TIMER2 0x140 -+#define QSERDES_PLL_CLK_SELECT 0x16c -+#define QSERDES_PLL_HSCLK_SEL 0x170 -+#define QSERDES_PLL_CORECLK_DIV 0x17c -+#define QSERDES_PLL_CORE_CLK_EN 0x184 -+#define QSERDES_PLL_CMN_CONFIG 0x18c -+#define QSERDES_PLL_SVS_MODE_CLK_SEL 0x194 -+#define QSERDES_PLL_CORECLK_DIV_MODE1 0x1b4 -+ -+/* QMP V2 PCIE PHY - Found in IPQ8074 gen3 port - - QSERDES TX registers */ -+#define QSERDES_TX0_RES_CODE_LANE_OFFSET_TX 0x03c -+#define QSERDES_TX0_HIGHZ_DRVR_EN 0x058 -+#define QSERDES_TX0_LANE_MODE_1 0x084 -+#define QSERDES_TX0_RCV_DETECT_LVL_2 0x09c -+ -+/* QMP V2 PCIE PHY - Found in IPQ8074 gen3 port - QSERDES RX registers */ -+#define QSERDES_RX0_UCDR_FO_GAIN 0x008 -+#define QSERDES_RX0_UCDR_SO_GAIN 0x014 -+#define QSERDES_RX0_UCDR_SO_SATURATION_AND_ENABLE 0x034 -+#define QSERDES_RX0_UCDR_PI_CONTROLS 0x044 -+#define QSERDES_RX0_RX_EQU_ADAPTOR_CNTRL2 0x0ec -+#define QSERDES_RX0_RX_EQU_ADAPTOR_CNTRL3 0x0f0 -+#define QSERDES_RX0_RX_EQU_ADAPTOR_CNTRL4 0x0f4 -+#define QSERDES_RX0_RX_IDAC_TSETTLE_LOW 0x0f8 -+#define QSERDES_RX0_RX_IDAC_TSETTLE_HIGH 0x0fc -+#define QSERDES_RX0_RX_EQ_OFFSET_ADAPTOR_CNTRL1 0x110 -+#define QSERDES_RX0_RX_OFFSET_ADAPTOR_CNTRL2 0x114 -+#define QSERDES_RX0_SIGDET_ENABLES 0x118 -+#define QSERDES_RX0_SIGDET_CNTRL 0x11c -+#define QSERDES_RX0_SIGDET_DEGLITCH_CNTRL 0x124 -+#define QSERDES_RX0_RX_MODE_00_LOW 0x170 -+#define QSERDES_RX0_RX_MODE_00_HIGH 0x174 -+#define QSERDES_RX0_RX_MODE_00_HIGH2 0x178 -+#define QSERDES_RX0_RX_MODE_00_HIGH3 0x17c -+#define QSERDES_RX0_RX_MODE_00_HIGH4 0x180 -+#define QSERDES_RX0_RX_MODE_01_LOW 0x184 -+#define QSERDES_RX0_RX_MODE_01_HIGH 0x188 -+#define QSERDES_RX0_RX_MODE_01_HIGH2 0x18c -+#define QSERDES_RX0_RX_MODE_01_HIGH3 0x190 -+#define QSERDES_RX0_RX_MODE_01_HIGH4 0x194 -+#define QSERDES_RX0_RX_MODE_10_LOW 0x198 -+#define QSERDES_RX0_RX_MODE_10_HIGH 0x19c -+#define QSERDES_RX0_RX_MODE_10_HIGH2 0x1a0 -+#define QSERDES_RX0_RX_MODE_10_HIGH3 0x1a4 -+#define QSERDES_RX0_RX_MODE_10_HIGH4 0x1a8 -+#define QSERDES_RX0_DFE_EN_TIMER 0x1b4 -+ -+/* QMP V2 PCIE PHY - Found in IPQ8074 gen3 port - PCS registers */ -+ -+#define PCS_COM_FLL_CNTRL1 0x098 -+#define PCS_COM_FLL_CNTRL2 0x09c -+#define PCS_COM_FLL_CNT_VAL_L 0x0a0 -+#define PCS_COM_FLL_CNT_VAL_H_TOL 0x0a4 -+#define PCS_COM_FLL_MAN_CODE 0x0a8 -+#define PCS_COM_REFGEN_REQ_CONFIG1 0x0dc -+#define PCS_COM_G12S1_TXDEEMPH_M3P5DB 0x16c -+#define PCS_COM_RX_SIGDET_LVL 0x188 -+#define PCS_COM_P2U3_WAKEUP_DLY_TIME_AUXCLK_L 0x1a4 -+#define PCS_COM_P2U3_WAKEUP_DLY_TIME_AUXCLK_H 0x1a8 -+#define PCS_COM_RX_DCC_CAL_CONFIG 0x1d8 -+#define PCS_COM_EQ_CONFIG5 0x1ec -+ -+/* QMP V2 PCIE PHY - Found in IPQ8074 gen3 port - PCS Misc registers */ -+ -+#define PCS_PCIE_POWER_STATE_CONFIG2 0x40c -+#define PCS_PCIE_POWER_STATE_CONFIG4 0x414 -+#define PCS_PCIE_ENDPOINT_REFCLK_DRIVE 0x41c -+#define PCS_PCIE_L1P1_WAKEUP_DLY_TIME_AUXCLK_L 0x440 -+#define PCS_PCIE_L1P1_WAKEUP_DLY_TIME_AUXCLK_H 0x444 -+#define PCS_PCIE_L1P2_WAKEUP_DLY_TIME_AUXCLK_L 0x448 -+#define PCS_PCIE_L1P2_WAKEUP_DLY_TIME_AUXCLK_H 0x44c -+#define PCS_PCIE_OSC_DTCT_CONFIG2 0x45c -+#define PCS_PCIE_OSC_DTCT_MODE2_CONFIG2 0x478 -+#define PCS_PCIE_OSC_DTCT_MODE2_CONFIG4 0x480 -+#define PCS_PCIE_OSC_DTCT_MODE2_CONFIG5 0x484 -+#define PCS_PCIE_OSC_DTCT_ACTIONS 0x490 -+#define PCS_PCIE_EQ_CONFIG1 0x4a0 -+#define PCS_PCIE_EQ_CONFIG2 0x4a4 -+#define PCS_PCIE_PRESET_P10_PRE 0x4bc -+#define PCS_PCIE_PRESET_P10_POST 0x4e0 -+ -+#endif ---- a/drivers/phy/qualcomm/phy-qcom-qmp.c -+++ b/drivers/phy/qualcomm/phy-qcom-qmp.c -@@ -23,6 +23,7 @@ - #include - - #include "phy-qcom-qmp.h" -+#include "phy-qcom-pcie3-qmp.h" - - /* QPHY_SW_RESET bit */ - #define SW_RESET BIT(0) -@@ -812,6 +813,132 @@ 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), -@@ -3195,6 +3322,36 @@ static const struct qmp_phy_cfg ipq6018_ - .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 = qmp_v4_usb3phy_regs_layout, -+ -+ .start_ctrl = SERDES_START | PCS_START, -+ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, -+ -+ .has_phy_com_ctrl = false, -+ .has_lane_rst = false, -+ .has_pwrdn_delay = true, -+ .pwrdn_delay_min = 995, /* us */ -+ .pwrdn_delay_max = 1005, /* us */ -+}; -+ - static const struct qmp_phy_cfg sdm845_qmp_pciephy_cfg = { - .type = PHY_TYPE_PCIE, - .nlanes = 1, -@@ -5139,8 +5296,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 phys use 125MHz pipe clock interface unless -+ * other frequency is specified in dts -+ */ -+ ret = of_property_read_u32(np, "clock-output-rate", -+ (u32 *)&fixed->fixed_rate); -+ if (ret) -+ fixed->fixed_rate = 125000000; -+ - fixed->hw.init = &init; - - ret = devm_clk_hw_register(qmp->dev, &fixed->hw); -@@ -5567,6 +5731,9 @@ static const struct of_device_id qcom_qm - .compatible = "qcom,ipq6018-qmp-usb3-phy", - .data = &ipq8074_usb3phy_cfg, - }, { -+ .compatible = "qcom,ipq8074-qmp-pcie-gen3-phy", -+ .data = &ipq8074_pciephy_gen3_cfg, -+ }, { - .compatible = "qcom,sc7180-qmp-usb3-phy", - .data = &sc7180_usb3phy_cfg, - }, { diff --git a/target/linux/ipq807x/patches-5.15/0104-arm64-dts-qcom-ipq8074-enable-the-GICv2m-support.patch b/target/linux/ipq807x/patches-5.15/0104-arm64-dts-qcom-ipq8074-enable-the-GICv2m-support.patch deleted file mode 100644 index 5bbba4fa0..000000000 --- a/target/linux/ipq807x/patches-5.15/0104-arm64-dts-qcom-ipq8074-enable-the-GICv2m-support.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 110bec39320cbfd23ac869af4aa231cda9c5f74a Mon Sep 17 00:00:00 2001 -From: Kathiravan T -Date: Tue, 8 Feb 2022 21:05:24 +0530 -Subject: [PATCH] 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 ---- - 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 -@@ -670,9 +670,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/ipq807x/patches-5.15/0105-PCI-dwc-tegra-move-GEN3_RELATED-DBI-register-to-comm.patch b/target/linux/ipq807x/patches-5.15/0105-PCI-dwc-tegra-move-GEN3_RELATED-DBI-register-to-comm.patch deleted file mode 100644 index f81de791e..000000000 --- a/target/linux/ipq807x/patches-5.15/0105-PCI-dwc-tegra-move-GEN3_RELATED-DBI-register-to-comm.patch +++ /dev/null @@ -1,45 +0,0 @@ -From dae5693368998da74d3a460da739677c02c9c6af Mon Sep 17 00:00:00 2001 -From: Baruch Siach -Date: Mon, 7 Feb 2022 16:51:24 +0200 -Subject: [PATCH] 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/ipq807x/patches-5.15/0106-PCI-qcom-Define-slot-capabilities-using-PCI_EXP_SLTC.patch b/target/linux/ipq807x/patches-5.15/0106-PCI-qcom-Define-slot-capabilities-using-PCI_EXP_SLTC.patch deleted file mode 100644 index 5de9c87b6..000000000 --- a/target/linux/ipq807x/patches-5.15/0106-PCI-qcom-Define-slot-capabilities-using-PCI_EXP_SLTC.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 70261569da66997eb4c6057b136af417ed06716e Mon Sep 17 00:00:00 2001 -From: Baruch Siach -Date: Mon, 7 Feb 2022 16:51:25 +0200 -Subject: [PATCH] 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/ipq807x/patches-5.15/0107-PCI-qcom-Add-IPQ60xx-support.patch b/target/linux/ipq807x/patches-5.15/0107-PCI-qcom-Add-IPQ60xx-support.patch deleted file mode 100644 index d49d89e3d..000000000 --- a/target/linux/ipq807x/patches-5.15/0107-PCI-qcom-Add-IPQ60xx-support.patch +++ /dev/null @@ -1,212 +0,0 @@ -From 5d15adca10588019810505a07ed3f6758e4413be Mon Sep 17 00:00:00 2001 -From: Selvam Sathappan Periakaruppan -Date: Thu, 10 Feb 2022 18:02:47 +0100 -Subject: [PATCH] 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/ipq807x/patches-5.15/0108-PCI-qcom-add-IPQ8074-Gen3-support.patch b/target/linux/ipq807x/patches-5.15/0108-PCI-qcom-add-IPQ8074-Gen3-support.patch deleted file mode 100644 index 12b9b843e..000000000 --- a/target/linux/ipq807x/patches-5.15/0108-PCI-qcom-add-IPQ8074-Gen3-support.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 4e93203281f4b0c82bf36afd5f316e37991d6456 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Mon, 20 Dec 2021 15:01:36 +0100 -Subject: [PATCH] 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/ipq807x/patches-5.15/0121-thermal-qcom-tsens-Add-IPQ8074-support.patch b/target/linux/ipq807x/patches-5.15/0121-thermal-qcom-tsens-Add-IPQ8074-support.patch deleted file mode 100644 index 2f8f1d72c..000000000 --- a/target/linux/ipq807x/patches-5.15/0121-thermal-qcom-tsens-Add-IPQ8074-support.patch +++ /dev/null @@ -1,99 +0,0 @@ -From b7bf74840dcffd209d4fc26a6d16d669bcda8f1d Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Fri, 20 Nov 2020 13:52:43 +0100 -Subject: [PATCH] thermal: qcom: tsens: Add IPQ8074 support - -Qualcomm IPQ807x SoC-s use tsens v2.3.0 IP, but they -only have one interrupt and not a dedicated critical interrupt. - -Signed-off-by: Robert Marko ---- - drivers/thermal/qcom/tsens-v2.c | 14 ++++++++++++++ - drivers/thermal/qcom/tsens.c | 27 ++++++++++++++++++--------- - drivers/thermal/qcom/tsens.h | 2 +- - 3 files changed, 33 insertions(+), 10 deletions(-) - ---- a/drivers/thermal/qcom/tsens-v2.c -+++ b/drivers/thermal/qcom/tsens-v2.c -@@ -36,6 +36,14 @@ static struct tsens_features tsens_v2_fe - .max_sensors = 16, - }; - -+static struct tsens_features tsens_ipq8074_feat = { -+ .ver_major = VER_2_X, -+ .crit_int = 0, -+ .adc = 0, -+ .srot_split = 1, -+ .max_sensors = 16, -+}; -+ - static const struct reg_field tsens_v2_regfields[MAX_REGFIELDS] = { - /* ----- SROT ------ */ - /* VERSION */ -@@ -101,6 +109,12 @@ struct tsens_plat_data data_tsens_v2 = { - .fields = tsens_v2_regfields, - }; - -+struct tsens_plat_data data_tsens_ipq8074 = { -+ .ops = &ops_generic_v2, -+ .feat = &tsens_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 -@@ -325,16 +325,22 @@ static int tsens_read_irq_state(struct t - ret = regmap_field_read(priv->rf[LOW_INT_MASK_0 + hw_id], &d->low_irq_mask); - if (ret) - return ret; -- ret = regmap_field_read(priv->rf[CRIT_INT_CLEAR_0 + hw_id], -- &d->crit_irq_clear); -- if (ret) -- return ret; -- ret = regmap_field_read(priv->rf[CRIT_INT_MASK_0 + hw_id], -- &d->crit_irq_mask); -- if (ret) -- return ret; -+ if (priv->feat->crit_int) { -+ ret = regmap_field_read(priv->rf[CRIT_INT_CLEAR_0 + hw_id], -+ &d->crit_irq_clear); -+ if (ret) -+ return ret; -+ ret = regmap_field_read(priv->rf[CRIT_INT_MASK_0 + hw_id], -+ &d->crit_irq_mask); -+ if (ret) -+ return ret; - -- d->crit_thresh = tsens_hw_to_mC(s, CRIT_THRESH_0 + hw_id); -+ d->crit_thresh = tsens_hw_to_mC(s, CRIT_THRESH_0 + hw_id); -+ } else { -+ d->crit_irq_clear = 0; -+ d->crit_irq_mask = 0; -+ d->crit_thresh = 0; -+ } - } else { - /* No mask register on older TSENS */ - d->up_irq_mask = 0; -@@ -999,6 +1005,9 @@ static const struct of_device_id tsens_t - }, { - .compatible = "qcom,tsens-v2", - .data = &data_tsens_v2, -+ }, { -+ .compatible = "qcom,ipq8074-tsens", -+ .data = &data_tsens_ipq8074, - }, - {} - }; ---- a/drivers/thermal/qcom/tsens.h -+++ b/drivers/thermal/qcom/tsens.h -@@ -593,6 +593,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_tsens_v2, data_tsens_ipq8074; - - #endif /* __QCOM_TSENS_H__ */ diff --git a/target/linux/ipq807x/patches-5.15/0123-regulator-qcom_spmi-Add-PMD9655-SPMI-regulator.patch b/target/linux/ipq807x/patches-5.15/0123-regulator-qcom_spmi-Add-PMD9655-SPMI-regulator.patch deleted file mode 100644 index 5093054c2..000000000 --- a/target/linux/ipq807x/patches-5.15/0123-regulator-qcom_spmi-Add-PMD9655-SPMI-regulator.patch +++ /dev/null @@ -1,38 +0,0 @@ -From cb5dc874a8f0740eb988c2851a97d214e463eeb1 Mon Sep 17 00:00:00 2001 -From: Praveenkumar I -Date: Tue, 31 Mar 2020 22:00:27 +0530 -Subject: [PATCH] regulator: qcom_spmi: Add PMD9655 SPMI regulator - -PMD9655 is used in IPQ8074 and provides S3 for cores, -S4 for UBI core and LDO11 for SDIO/eMMC. - -Signed-off-by: Praveenkumar I -Signed-off-by: Robert Marko ---- - drivers/regulator/qcom_spmi-regulator.c | 8 ++++++++ - 1 file changed, 8 insertions(+) - ---- a/drivers/regulator/qcom_spmi-regulator.c -+++ b/drivers/regulator/qcom_spmi-regulator.c -@@ -2092,6 +2092,13 @@ static const struct spmi_regulator_data - { } - }; - -+static const struct spmi_regulator_data pmd9655_regulators[] = { -+ { "s3", 0x1a00, "vdd_s3",}, -+ { "s4", 0x1d00, "vdd_s4",}, -+ { "ldo11", 0x4a00, "vdd_ldo11",}, -+ { } -+}; -+ - static const struct of_device_id qcom_spmi_regulator_match[] = { - { .compatible = "qcom,pm8004-regulators", .data = &pm8004_regulators }, - { .compatible = "qcom,pm8005-regulators", .data = &pm8005_regulators }, -@@ -2104,6 +2111,7 @@ static const struct of_device_id qcom_sp - { .compatible = "qcom,pm660-regulators", .data = &pm660_regulators }, - { .compatible = "qcom,pm660l-regulators", .data = &pm660l_regulators }, - { .compatible = "qcom,pms405-regulators", .data = &pms405_regulators }, -+ { .compatible = "qcom,pmd9655-regulators", .data = &pmd9655_regulators }, - { } - }; - MODULE_DEVICE_TABLE(of, qcom_spmi_regulator_match); diff --git a/target/linux/ipq807x/patches-5.15/0124-regulator-qcom_spmi-SMPS-range-is-added-to-support-P.patch b/target/linux/ipq807x/patches-5.15/0124-regulator-qcom_spmi-SMPS-range-is-added-to-support-P.patch deleted file mode 100644 index 1b8a5c429..000000000 --- a/target/linux/ipq807x/patches-5.15/0124-regulator-qcom_spmi-SMPS-range-is-added-to-support-P.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 3c5e2d0c4149c287b9992e156a15ff881895bf00 Mon Sep 17 00:00:00 2001 -From: Praveenkumar I -Date: Mon, 4 May 2020 19:31:00 +0530 -Subject: [PATCH] regulator: qcom_spmi: SMPS range is added to support PMD9655 - PMIC - -Signed-off-by: Praveenkumar I -Change-Id: I5571801debec25527fd763d95aff27cc42f53bde ---- - drivers/regulator/qcom_spmi-regulator.c | 1 + - 1 file changed, 1 insertion(+) - ---- a/drivers/regulator/qcom_spmi-regulator.c -+++ b/drivers/regulator/qcom_spmi-regulator.c -@@ -481,6 +481,7 @@ static struct spmi_voltage_range ln_ldo_ - }; - - static struct spmi_voltage_range smps_ranges[] = { -+ SPMI_VOLTAGE_RANGE(2, 670000, 670000, 990000, 990000, 8000), - SPMI_VOLTAGE_RANGE(0, 375000, 375000, 1562500, 1562500, 12500), - SPMI_VOLTAGE_RANGE(1, 1550000, 1575000, 3125000, 3125000, 25000), - }; diff --git a/target/linux/ipq807x/patches-5.15/0125-regulator-qcom_spmi-Initialize-slew-rate-only-if-req.patch b/target/linux/ipq807x/patches-5.15/0125-regulator-qcom_spmi-Initialize-slew-rate-only-if-req.patch deleted file mode 100644 index 9fd7dc432..000000000 --- a/target/linux/ipq807x/patches-5.15/0125-regulator-qcom_spmi-Initialize-slew-rate-only-if-req.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 7475c4cd8898ba5bdf3021a23d3087d7a9747ec4 Mon Sep 17 00:00:00 2001 -From: PRAVEENKUMAR I -Date: Tue, 5 May 2020 07:57:21 +0530 -Subject: [PATCH] regulator: qcom_spmi: Initialize slew rate only if required - -Initialize slew rate only if set_voltage_time_sel in ops -is defined. - -Change-Id: I661c88d2f4a8f26cc85b1e2d4c8aa3170420ba6c -Signed-off-by: Rajith Cherian -(cherry picked from commit 608a6f171ef4017197fbe2069b5910b582923027) -Signed-off-by: Praveenkumar I - -Change-Id: Ida3cf3d754e1207e34a164d6d86c6e1aa109ef1e ---- - 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 -@@ -1617,6 +1617,13 @@ static int spmi_regulator_init_slew_rate - int step, delay, slew_rate, step_delay; - const struct spmi_voltage_range *range; - -+ /* -+ * Slew rate need not be initialized if -+ * set_voltage_time_sel in the ops is not defined. -+ */ -+ if (!vreg->desc.ops->set_voltage_time_sel) -+ return 0; -+ - ret = spmi_vreg_read(vreg, SPMI_COMMON_REG_STEP_CTRL, ®, 1); - if (ret) { - dev_err(vreg->dev, "spmi read failed, ret=%d\n", ret); diff --git a/target/linux/ipq807x/patches-5.15/0126-regulator-qcom_spmi-Add-support-for-VMPWM_CTL-subtyp.patch b/target/linux/ipq807x/patches-5.15/0126-regulator-qcom_spmi-Add-support-for-VMPWM_CTL-subtyp.patch deleted file mode 100644 index 9a15cb7ba..000000000 --- a/target/linux/ipq807x/patches-5.15/0126-regulator-qcom_spmi-Add-support-for-VMPWM_CTL-subtyp.patch +++ /dev/null @@ -1,159 +0,0 @@ -From 29d356f93a44cd96a2618ffcc08968a1a0dff828 Mon Sep 17 00:00:00 2001 -From: PRAVEENKUMAR I -Date: Tue, 5 May 2020 07:57:52 +0530 -Subject: [PATCH] regulator: qcom_spmi: Add support for VMPWM_CTL subtype - -Support for Voltage Mode PWM Controller (VMPWM_CTL). -Set/Get microvolts functions added. Function to find the -voltage range for this particular subtype added. - -Change-Id: Ib4bf35ee65de17a917f01e63208368c7770401d4 -Signed-off-by: Rajith Cherian -(cherry picked from commit 31e7e4183b5afaf18dbca3548f4988c420ebb58b) -Signed-off-by: Praveenkumar I - -Change-Id: Id7a3caef84499b9e2eefda9f57576923c84234f0 ---- - drivers/regulator/qcom_spmi-regulator.c | 82 +++++++++++++++++++++++++ - 1 file changed, 82 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_VMPWM_CTL = 0x0a, - }; - - enum spmi_common_regulator_registers { -@@ -289,6 +290,10 @@ enum spmi_common_control_register_index - #define SPMI_FTSMPS_STEP_CTRL_DELAY_MASK 0x07 - #define SPMI_FTSMPS_STEP_CTRL_DELAY_SHIFT 0 - -+#define SPMI_SMPS_VMPWM_VSET_UB_SHIFT 8 -+#define SPMI_SMPS_VMPWM_VSET_UB_MASK 0xf00 -+#define SPMI_SMPS_VMPWM_VSET_LB_MASK 0xff -+ - /* Clock rate in kHz of the FTSMPS regulator reference clock. */ - #define SPMI_FTSMPS_CLOCK_RATE 19200 - -@@ -486,6 +491,10 @@ static struct spmi_voltage_range smps_ra - SPMI_VOLTAGE_RANGE(1, 1550000, 1575000, 3125000, 3125000, 25000), - }; - -+static struct spmi_voltage_range smps_vmpwm_ranges[] = { -+ SPMI_VOLTAGE_RANGE(0, 664000, 664000, 1104000, 1104000, 8000), -+}; -+ - static struct spmi_voltage_range ftsmps_ranges[] = { - SPMI_VOLTAGE_RANGE(0, 0, 350000, 1275000, 1275000, 5000), - SPMI_VOLTAGE_RANGE(1, 0, 1280000, 2040000, 2040000, 10000), -@@ -551,6 +560,7 @@ static DEFINE_SPMI_SET_POINTS(nldo2); - static DEFINE_SPMI_SET_POINTS(nldo3); - static DEFINE_SPMI_SET_POINTS(ln_ldo); - static DEFINE_SPMI_SET_POINTS(smps); -+static DEFINE_SPMI_SET_POINTS(smps_vmpwm); - static DEFINE_SPMI_SET_POINTS(ftsmps); - static DEFINE_SPMI_SET_POINTS(ftsmps2p5); - static DEFINE_SPMI_SET_POINTS(ftsmps426); -@@ -745,6 +755,24 @@ spmi_regulator_find_range(struct spmi_re - return NULL; - } - -+static const struct spmi_voltage_range * -+spmi_regulator_find_uV_range(struct spmi_regulator *vreg, int min, int max) -+{ -+ const struct spmi_voltage_range *range, *end; -+ -+ if (!vreg->set_points || !vreg->set_points->count) -+ return 0; -+ -+ range = vreg->set_points->range; -+ end = range + vreg->set_points->count; -+ -+ for (; range < end; range++) -+ if ((range->min_uV <= min) && (range->max_uV >= max)) -+ return range; -+ -+ return 0; -+} -+ - static int spmi_regulator_select_voltage_same_range(struct spmi_regulator *vreg, - int min_uV, int max_uV) - { -@@ -966,6 +994,47 @@ static int spmi_regulator_ult_lo_smps_ge - return spmi_hw_selector_to_sw(vreg, voltage_sel, range); - } - -+static int spmi_regulator_smps_vmpwm_set_vol_uV(struct regulator_dev *rdev, -+ int min_uV, int max_uV, unsigned *selector) -+{ -+ struct spmi_regulator *vreg = rdev_get_drvdata(rdev); -+ const struct spmi_voltage_range *range; -+ int req_vol; -+ u8 reg[2]; -+ -+ range = spmi_regulator_find_uV_range(vreg, min_uV, max_uV); -+ if (!range) -+ return -EINVAL; -+ -+ *selector = spmi_regulator_select_voltage(vreg, min_uV, max_uV); -+ req_vol = range->set_point_min_uV + (range->step_uV * (*selector)); -+ -+ /* Convert uV to mV as the register supports mV */ -+ req_vol = req_vol/1000; -+ -+ /* -+ * Voltage set point bits<7:0>. 2-Byte Word (lower byte word) -+ */ -+ reg[0] = req_vol & SPMI_SMPS_VMPWM_VSET_LB_MASK; -+ /* -+ * Voltage set point bit <11:8>. 2-Byte Word (upper byte word) -+ */ -+ reg[1] = (req_vol & SPMI_SMPS_VMPWM_VSET_UB_MASK) -+ >> SPMI_SMPS_VMPWM_VSET_UB_SHIFT; -+ -+ return spmi_vreg_write(vreg, SPMI_COMMON_REG_VOLTAGE_RANGE, reg, 2); -+} -+ -+static int spmi_regulator_smps_vmpwm_get_vol_uV(struct regulator_dev *rdev) -+{ -+ struct spmi_regulator *vreg = rdev_get_drvdata(rdev); -+ u8 reg[2]; -+ -+ spmi_vreg_read(vreg, SPMI_COMMON_REG_VOLTAGE_RANGE, reg, 2); -+ -+ return ((reg[1] << SPMI_SMPS_VMPWM_VSET_UB_SHIFT) | reg[0]) * 1000; -+} -+ - static int spmi_regulator_common_list_voltage(struct regulator_dev *rdev, - unsigned selector) - { -@@ -1314,6 +1383,18 @@ static const struct regulator_ops spmi_s - .set_pull_down = spmi_regulator_common_set_pull_down, - }; - -+static const struct regulator_ops spmi_smps_vmpwm_ops = { -+ .enable = regulator_enable_regmap, -+ .disable = regulator_disable_regmap, -+ .is_enabled = regulator_is_enabled_regmap, -+ .set_voltage = spmi_regulator_smps_vmpwm_set_vol_uV, -+ .get_voltage = spmi_regulator_smps_vmpwm_get_vol_uV, -+ .map_voltage = spmi_regulator_common_map_voltage, -+ .list_voltage = spmi_regulator_common_list_voltage, -+ .set_mode = spmi_regulator_common_set_mode, -+ .get_mode = spmi_regulator_common_get_mode, -+}; -+ - static const struct regulator_ops spmi_ldo_ops = { - .enable = regulator_enable_regmap, - .disable = regulator_disable_regmap, -@@ -1459,6 +1540,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(BUCK, VMPWM_CTL, 0, INF, SMPS, smps_vmpwm, smps_vmpwm, 0), - 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/ipq807x/patches-5.15/0127-ipq807x-sdhc-Fixed-SDR104-mode-card-detection.patch b/target/linux/ipq807x/patches-5.15/0127-ipq807x-sdhc-Fixed-SDR104-mode-card-detection.patch deleted file mode 100644 index 65a0c6c83..000000000 --- a/target/linux/ipq807x/patches-5.15/0127-ipq807x-sdhc-Fixed-SDR104-mode-card-detection.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 6ac91c1597dfd688b5e818708aa4f8c55a41eefb Mon Sep 17 00:00:00 2001 -From: Vasudevan Murugesan -Date: Thu, 8 Jun 2017 19:13:48 +0530 -Subject: [PATCH] ipq807x: sdhc: Fixed SDR104 mode card detection - -Change-Id: I353356284d28d09d79bf7d318c4ebcdbc15e5b02 -Signed-off-by: Vasudevan Murugesan -Signed-off-by: Saravanan Jaganathan -(cherry picked from commit 080d3f390aa409ef2b5adf59a175b6bb2aa863fd) -Signed-off-by: Praveenkumar I - -Change-Id: Ie5edb7b3d972e06f3eb2525e10597b49e9bae14d ---- - drivers/regulator/qcom_spmi-regulator.c | 3 +++ - 1 file changed, 3 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_VMPWM_CTL = 0x0a, -+ SPMI_REGULATOR_SUBTYPE_HT_P150 = 0x35, - }; - - enum spmi_common_regulator_registers { -@@ -493,6 +494,7 @@ static struct spmi_voltage_range smps_ra - - static struct spmi_voltage_range smps_vmpwm_ranges[] = { - SPMI_VOLTAGE_RANGE(0, 664000, 664000, 1104000, 1104000, 8000), -+ SPMI_VOLTAGE_RANGE(1, 1104000, 1104000, 3300000, 3300000, 8000), - }; - - static struct spmi_voltage_range ftsmps_ranges[] = { -@@ -1540,6 +1542,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, LDO, smps_vmpwm, smps_vmpwm, 0), - SPMI_VREG(BUCK, VMPWM_CTL, 0, INF, SMPS, smps_vmpwm, smps_vmpwm, 0), - 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/ipq807x/patches-5.15/0128-ipq807x-spmi-regulator-Add-separate-voltage-range-fo.patch b/target/linux/ipq807x/patches-5.15/0128-ipq807x-spmi-regulator-Add-separate-voltage-range-fo.patch deleted file mode 100644 index ef37bbeee..000000000 --- a/target/linux/ipq807x/patches-5.15/0128-ipq807x-spmi-regulator-Add-separate-voltage-range-fo.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 93ed08e80c610330f90b20415093fe388835f355 Mon Sep 17 00:00:00 2001 -From: Praveenkumar I -Date: Mon, 13 Jul 2020 18:13:48 +0530 -Subject: [PATCH] ipq807x: spmi regulator: Add separate voltage range for LDO - -When LDO voltage range added in SMPS voltage range structure, -selector value used during set voltage is wrongly calculated. -Because the SMPS voltage range is also taken into account for LDO. - -So, a separate voltage range structure is introduced for LDO. - -Signed-off-by: Praveenkumar I -Change-Id: I883518ae0686762a3774750b1dd480c4fe7298f3 ---- - drivers/regulator/qcom_spmi-regulator.c | 8 ++++++-- - 1 file changed, 6 insertions(+), 2 deletions(-) - ---- a/drivers/regulator/qcom_spmi-regulator.c -+++ b/drivers/regulator/qcom_spmi-regulator.c -@@ -494,7 +494,10 @@ static struct spmi_voltage_range smps_ra - - static struct spmi_voltage_range smps_vmpwm_ranges[] = { - SPMI_VOLTAGE_RANGE(0, 664000, 664000, 1104000, 1104000, 8000), -- SPMI_VOLTAGE_RANGE(1, 1104000, 1104000, 3300000, 3300000, 8000), -+}; -+ -+static struct spmi_voltage_range ldo_vmpwm_ranges[] = { -+ SPMI_VOLTAGE_RANGE(0, 1104000, 1104000, 3300000, 3300000, 8000), - }; - - static struct spmi_voltage_range ftsmps_ranges[] = { -@@ -563,6 +566,7 @@ static DEFINE_SPMI_SET_POINTS(nldo3); - static DEFINE_SPMI_SET_POINTS(ln_ldo); - static DEFINE_SPMI_SET_POINTS(smps); - static DEFINE_SPMI_SET_POINTS(smps_vmpwm); -+static DEFINE_SPMI_SET_POINTS(ldo_vmpwm); - static DEFINE_SPMI_SET_POINTS(ftsmps); - static DEFINE_SPMI_SET_POINTS(ftsmps2p5); - static DEFINE_SPMI_SET_POINTS(ftsmps426); -@@ -1542,7 +1546,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, LDO, smps_vmpwm, smps_vmpwm, 0), -+ SPMI_VREG(LDO, HT_P150, 0, INF, LDO, smps_vmpwm, ldo_vmpwm, 0), - SPMI_VREG(BUCK, VMPWM_CTL, 0, INF, SMPS, smps_vmpwm, smps_vmpwm, 0), - 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/ipq807x/patches-5.15/0129-arm64-dts-ipq8074-add-SPMI-PMIC-regulators.patch b/target/linux/ipq807x/patches-5.15/0129-arm64-dts-ipq8074-add-SPMI-PMIC-regulators.patch deleted file mode 100644 index ce32bb366..000000000 --- a/target/linux/ipq807x/patches-5.15/0129-arm64-dts-ipq8074-add-SPMI-PMIC-regulators.patch +++ /dev/null @@ -1,65 +0,0 @@ -From c175f32484c75d0d3fe9c4024226c1067957d0a8 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Sun, 26 Dec 2021 19:04:26 +0100 -Subject: [PATCH] arm64: dts: ipq8074: add SPMI PMIC regulators - -PMD9655 is used in IPQ8074 and provides S3 for cores, -S4 for UBI core and LDO11 for SDIO/eMMC. - -So, lets add the nodes in preparation for DVFS later. - -Signed-off-by: Robert Marko ---- - arch/arm64/boot/dts/qcom/ipq8074.dtsi | 34 +++++++++++++++++++++++++++ - 1 file changed, 34 insertions(+) - ---- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -5,6 +5,7 @@ - - #include - #include -+#include - - / { - model = "Qualcomm Technologies, Inc. IPQ8074"; -@@ -450,6 +451,39 @@ - interrupt-controller; - #interrupt-cells = <4>; - cell-index = <0>; -+ -+ pmic@1 { -+ compatible ="qcom,spmi-pmic"; -+ reg = <0x1 SPMI_USID>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ regulators { -+ compatible = "qcom,pmd9655-regulators"; -+ -+ s3: s3 { -+ regulator-name = "pmd9655_s3"; -+ regulator-min-microvolt = <592000>; -+ regulator-max-microvolt = <1064000>; -+ regulator-always-on; -+ regulator-boot-on; -+ }; -+ -+ s4: s4 { -+ regulator-name = "pmd9655_s4"; -+ regulator-min-microvolt = <712000>; -+ regulator-max-microvolt = <992000>; -+ regulator-always-on; -+ regulator-boot-on; -+ }; -+ -+ ldo11: ldo11 { -+ regulator-name = "pmd9655_ldo11"; -+ regulator-min-microvolt = <1104000>; -+ regulator-max-microvolt = <3300000>; -+ }; -+ }; -+ }; - }; - - sdhc_1: sdhci@7824900 { diff --git a/target/linux/ipq807x/patches-5.15/0130-clk-qcom-clk-alpha-pll-add-support-for-APSS-PLL.patch b/target/linux/ipq807x/patches-5.15/0130-clk-qcom-clk-alpha-pll-add-support-for-APSS-PLL.patch deleted file mode 100644 index f8e02f933..000000000 --- a/target/linux/ipq807x/patches-5.15/0130-clk-qcom-clk-alpha-pll-add-support-for-APSS-PLL.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 5a127450125f71247b7384930459b892da227e28 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Tue, 28 Dec 2021 20:32:46 +0100 -Subject: [PATCH] clk: qcom: clk-alpha-pll: add support for APSS PLL - -APSS PLL type will be used by the IPQ8074 APSS driver for providing the -CPU core clocks and enabling CPU Frequency scaling. - -This is ported from the downstream 5.4 kernel. - -Signed-off-by: Robert Marko ---- - drivers/clk/qcom/clk-alpha-pll.c | 12 ++++++++++++ - drivers/clk/qcom/clk-alpha-pll.h | 1 + - 2 files changed, 13 insertions(+) - ---- a/drivers/clk/qcom/clk-alpha-pll.c -+++ b/drivers/clk/qcom/clk-alpha-pll.c -@@ -139,6 +139,18 @@ const u8 clk_alpha_pll_regs[][PLL_OFF_MA - [PLL_OFF_OPMODE] = 0x28, - [PLL_OFF_STATUS] = 0x38, - }, -+ [CLK_ALPHA_PLL_TYPE_APSS] = { -+ [PLL_OFF_L_VAL] = 0x08, -+ [PLL_OFF_ALPHA_VAL] = 0x10, -+ [PLL_OFF_ALPHA_VAL_U] = 0xff, -+ [PLL_OFF_USER_CTL] = 0x18, -+ [PLL_OFF_USER_CTL_U] = 0xff, -+ [PLL_OFF_CONFIG_CTL] = 0x20, -+ [PLL_OFF_CONFIG_CTL_U] = 0x24, -+ [PLL_OFF_TEST_CTL] = 0x30, -+ [PLL_OFF_TEST_CTL_U] = 0x34, -+ [PLL_OFF_STATUS] = 0x28, -+ }, - }; - EXPORT_SYMBOL_GPL(clk_alpha_pll_regs); - ---- a/drivers/clk/qcom/clk-alpha-pll.h -+++ b/drivers/clk/qcom/clk-alpha-pll.h -@@ -17,6 +17,7 @@ enum { - CLK_ALPHA_PLL_TYPE_LUCID = CLK_ALPHA_PLL_TYPE_TRION, - CLK_ALPHA_PLL_TYPE_AGERA, - CLK_ALPHA_PLL_TYPE_ZONDA, -+ CLK_ALPHA_PLL_TYPE_APSS, - CLK_ALPHA_PLL_TYPE_MAX, - }; - diff --git a/target/linux/ipq807x/patches-5.15/0131-clk-qcom-Add-DT-bindings-for-IPQ8074-APSS-clock-cont.patch b/target/linux/ipq807x/patches-5.15/0131-clk-qcom-Add-DT-bindings-for-IPQ8074-APSS-clock-cont.patch deleted file mode 100644 index 93fa2ff27..000000000 --- a/target/linux/ipq807x/patches-5.15/0131-clk-qcom-Add-DT-bindings-for-IPQ8074-APSS-clock-cont.patch +++ /dev/null @@ -1,30 +0,0 @@ -From ab17c6d31f07271b42c6c36c9ad785bdc2871e62 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Tue, 28 Dec 2021 20:36:45 +0100 -Subject: [PATCH] clk: qcom: Add DT bindings for IPQ8074 APSS clock controller - -Add DT-binding for the IPQ8074 APSS clock controller. - -Signed-off-by: Robert Marko ---- - include/dt-bindings/clock/qcom,apss-ipq8074.h | 14 ++++++++++++++ - 1 file changed, 14 insertions(+) - create mode 100644 include/dt-bindings/clock/qcom,apss-ipq8074.h - ---- /dev/null -+++ b/include/dt-bindings/clock/qcom,apss-ipq8074.h -@@ -0,0 +1,14 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (c) 2021, The Linux Foundation. All rights reserved. -+ */ -+ -+#ifndef _DT_BINDINGS_CLOCK_QCA_APSS_IPQ8074_H -+#define _DT_BINDINGS_CLOCK_QCA_APSS_IPQ8074_H -+ -+#define APSS_PLL_EARLY 0 -+#define APSS_PLL 1 -+#define APCS_ALIAS0_CLK_SRC 2 -+#define APCS_ALIAS0_CORE_CLK 3 -+ -+#endif diff --git a/target/linux/ipq807x/patches-5.15/0132-clk-qcom-Add-IPQ8074-APSS-clock-controller.patch b/target/linux/ipq807x/patches-5.15/0132-clk-qcom-Add-IPQ8074-APSS-clock-controller.patch deleted file mode 100644 index 519add036..000000000 --- a/target/linux/ipq807x/patches-5.15/0132-clk-qcom-Add-IPQ8074-APSS-clock-controller.patch +++ /dev/null @@ -1,220 +0,0 @@ -From c0333749b53881e61ecdfc62f253e24b01dda129 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Tue, 28 Dec 2021 20:37:55 +0100 -Subject: [PATCH] clk: qcom: Add IPQ8074 APSS clock controller - -IPQ8074 APSS clock controller provides the clock for the IPQ8074 CPU -cores, thus also providing support for CPU frequency scaling. - -It looks like they are clocked by the XO and a custom APSS type PLL. - -Signed-off-by: Robert Marko ---- - drivers/clk/qcom/Kconfig | 10 ++ - drivers/clk/qcom/Makefile | 1 + - drivers/clk/qcom/apss-ipq8074.c | 170 ++++++++++++++++++++++++++++++++ - 3 files changed, 181 insertions(+) - create mode 100644 drivers/clk/qcom/apss-ipq8074.c - ---- a/drivers/clk/qcom/Kconfig -+++ b/drivers/clk/qcom/Kconfig -@@ -135,6 +135,16 @@ config IPQ_APSS_6018 - Say Y if you want to support CPU frequency scaling on - ipq based devices. - -+config IPQ_APSS_8074 -+ tristate "IPQ8074 APSS Clock Controller" -+ depends on QCOM_APCS_IPC || COMPILE_TEST -+ help -+ Support for APSS clock controller on IPQ8074 platforms. The -+ APSS clock controller manages the Mux and enable block that feeds the -+ CPUs. -+ Say Y if you want to support CPU frequency scaling on -+ ipq based devices. -+ - config IPQ_GCC_4019 - tristate "IPQ4019 Global Clock Controller" - help ---- a/drivers/clk/qcom/Makefile -+++ b/drivers/clk/qcom/Makefile -@@ -23,6 +23,7 @@ obj-$(CONFIG_APQ_MMCC_8084) += mmcc-apq8 - obj-$(CONFIG_CLK_GFM_LPASS_SM8250) += lpass-gfm-sm8250.o - obj-$(CONFIG_IPQ_APSS_PLL) += apss-ipq-pll.o - obj-$(CONFIG_IPQ_APSS_6018) += apss-ipq6018.o -+obj-$(CONFIG_IPQ_APSS_8074) += apss-ipq8074.o - obj-$(CONFIG_IPQ_GCC_4019) += gcc-ipq4019.o - obj-$(CONFIG_IPQ_GCC_6018) += gcc-ipq6018.o - obj-$(CONFIG_IPQ_GCC_806X) += gcc-ipq806x.o ---- /dev/null -+++ b/drivers/clk/qcom/apss-ipq8074.c -@@ -0,0 +1,170 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (c) 2021, The Linux Foundation. All rights reserved. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include "common.h" -+#include "clk-regmap.h" -+#include "clk-pll.h" -+#include "clk-rcg.h" -+#include "clk-branch.h" -+#include "clk-alpha-pll.h" -+#include "clk-regmap-divider.h" -+#include "clk-regmap-mux.h" -+ -+#define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) } -+ -+enum { -+ P_XO, -+ P_GPLL0, -+ P_GPLL2, -+ P_GPLL4, -+ P_APSS_PLL_EARLY, -+ P_APSS_PLL -+}; -+ -+static struct clk_alpha_pll apss_pll_early = { -+ .offset = 0x5000, -+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_APSS], -+ .clkr = { -+ .enable_reg = 0x5000, -+ .enable_mask = BIT(0), -+ .hw.init = &(struct clk_init_data){ -+ .name = "apss_pll_early", -+ .parent_names = (const char *[]){ -+ "xo" -+ }, -+ .num_parents = 1, -+ .ops = &clk_alpha_pll_huayra_ops, -+ }, -+ }, -+}; -+ -+static struct clk_alpha_pll_postdiv apss_pll = { -+ .offset = 0x5000, -+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_APSS], -+ .width = 2, -+ .clkr.hw.init = &(struct clk_init_data){ -+ .name = "apss_pll", -+ .parent_names = (const char *[]){ "apss_pll_early" }, -+ .num_parents = 1, -+ .ops = &clk_alpha_pll_postdiv_ro_ops, -+ }, -+}; -+ -+static const char * const parents_apcs_alias0_clk_src[] = { -+ "xo", -+ "gpll0", -+ "gpll2", -+ "gpll4", -+ "apss_pll", -+ "apss_pll_early", -+}; -+ -+static const struct parent_map parents_apcs_alias0_clk_src_map[] = { -+ { P_XO, 0 }, -+ { P_GPLL0, 4 }, -+ { P_GPLL2, 2 }, -+ { P_GPLL4, 1 }, -+ { P_APSS_PLL, 3 }, -+ { P_APSS_PLL_EARLY, 5 }, -+}; -+ -+struct freq_tbl ftbl_apcs_alias0_clk_src[] = { -+ F(19200000, P_XO, 1, 0, 0), -+ F(403200000, P_APSS_PLL_EARLY, 1, 0, 0), -+ F(806400000, P_APSS_PLL_EARLY, 1, 0, 0), -+ F(1017600000, P_APSS_PLL_EARLY, 1, 0, 0), -+ F(1382400000, P_APSS_PLL_EARLY, 1, 0, 0), -+ F(1651200000, P_APSS_PLL_EARLY, 1, 0, 0), -+ F(1843200000, P_APSS_PLL_EARLY, 1, 0, 0), -+ F(1920000000, P_APSS_PLL_EARLY, 1, 0, 0), -+ F(2208000000UL, P_APSS_PLL_EARLY, 1, 0, 0), -+ { } -+}; -+ -+struct clk_rcg2 apcs_alias0_clk_src = { -+ .cmd_rcgr = 0x0050, -+ .freq_tbl = ftbl_apcs_alias0_clk_src, -+ .hid_width = 5, -+ .parent_map = parents_apcs_alias0_clk_src_map, -+ .clkr.hw.init = &(struct clk_init_data){ -+ .name = "apcs_alias0_clk_src", -+ .parent_names = parents_apcs_alias0_clk_src, -+ .num_parents = 6, -+ .ops = &clk_rcg2_ops, -+ .flags = CLK_SET_RATE_PARENT, -+ }, -+}; -+ -+static struct clk_branch apcs_alias0_core_clk = { -+ .halt_reg = 0x0058, -+ .halt_bit = 31, -+ .clkr = { -+ .enable_reg = 0x0058, -+ .enable_mask = BIT(0), -+ .hw.init = &(struct clk_init_data){ -+ .name = "apcs_alias0_core_clk", -+ .parent_names = (const char *[]){ -+ "apcs_alias0_clk_src" -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT | -+ CLK_IS_CRITICAL, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_regmap *apss_ipq8074_clks[] = { -+ [APSS_PLL_EARLY] = &apss_pll_early.clkr, -+ [APSS_PLL] = &apss_pll.clkr, -+ [APCS_ALIAS0_CLK_SRC] = &apcs_alias0_clk_src.clkr, -+ [APCS_ALIAS0_CORE_CLK] = &apcs_alias0_core_clk.clkr, -+}; -+ -+static const struct regmap_config apss_ipq8074_regmap_config = { -+ .reg_bits = 32, -+ .reg_stride = 4, -+ .val_bits = 32, -+ .max_register = 0x5ffc, -+ .fast_io = true, -+}; -+ -+static const struct qcom_cc_desc apss_ipq8074_desc = { -+ .config = &apss_ipq8074_regmap_config, -+ .clks = apss_ipq8074_clks, -+ .num_clks = ARRAY_SIZE(apss_ipq8074_clks), -+}; -+ -+static int apss_ipq8074_probe(struct platform_device *pdev) -+{ -+ struct regmap *regmap; -+ -+ regmap = dev_get_regmap(pdev->dev.parent, NULL); -+ if (!regmap) -+ return -ENODEV; -+ -+ return qcom_cc_really_probe(pdev, &apss_ipq8074_desc, regmap); -+} -+ -+static struct platform_driver apss_ipq8074_driver = { -+ .probe = apss_ipq8074_probe, -+ .driver = { -+ .name = "qcom,apss-ipq8074-clk", -+ }, -+}; -+ -+module_platform_driver(apss_ipq8074_driver); -+ -+MODULE_DESCRIPTION("Qualcomm IPQ8074 APSS clock driver"); -+MODULE_LICENSE("GPLv2"); diff --git a/target/linux/ipq807x/patches-5.15/0133-mailbox-qcom-apcs-ipc-add-IPQ8074-APSS-clock-control.patch b/target/linux/ipq807x/patches-5.15/0133-mailbox-qcom-apcs-ipc-add-IPQ8074-APSS-clock-control.patch deleted file mode 100644 index 8aaf3032c..000000000 --- a/target/linux/ipq807x/patches-5.15/0133-mailbox-qcom-apcs-ipc-add-IPQ8074-APSS-clock-control.patch +++ /dev/null @@ -1,39 +0,0 @@ -From cef0d7940ff741590c638ced909cb9e58b9d8bb0 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Tue, 28 Dec 2021 20:59:18 +0100 -Subject: [PATCH] mailbox: qcom-apcs-ipc: add IPQ8074 APSS clock controller - support - -IPQ8074 has the APSS clock controller utilizing the same register space as -the APCS, so provide acess to the APSS utilizing a child device like -IPQ6018 does as well, but just by utilizing the IPQ8074 specific APSS -clock driver. - -Also, APCS register space in IPQ8074 is 0x6000 so max_register needs to be -updated to 0x5FFC. - -Signed-off-by: Robert Marko ---- - drivers/mailbox/qcom-apcs-ipc-mailbox.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/drivers/mailbox/qcom-apcs-ipc-mailbox.c -+++ b/drivers/mailbox/qcom-apcs-ipc-mailbox.c -@@ -34,7 +34,7 @@ static const struct qcom_apcs_ipc_data i - }; - - static const struct qcom_apcs_ipc_data ipq8074_apcs_data = { -- .offset = 8, .clk_name = NULL -+ .offset = 8, .clk_name = "qcom,apss-ipq8074-clk" - }; - - static const struct qcom_apcs_ipc_data msm8916_apcs_data = { -@@ -73,7 +73,7 @@ static const struct regmap_config apcs_r - .reg_bits = 32, - .reg_stride = 4, - .val_bits = 32, -- .max_register = 0x1008, -+ .max_register = 0x5FFC, - .fast_io = true, - }; - diff --git a/target/linux/ipq807x/patches-5.15/0134-arm64-dts-ipq8074-update-APCS-node-due-to-clock-supp.patch b/target/linux/ipq807x/patches-5.15/0134-arm64-dts-ipq8074-update-APCS-node-due-to-clock-supp.patch deleted file mode 100644 index 60095b8cc..000000000 --- a/target/linux/ipq807x/patches-5.15/0134-arm64-dts-ipq8074-update-APCS-node-due-to-clock-supp.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 89b34e0f57eaa18fc04ff038372c8d1facf55fa8 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Tue, 28 Dec 2021 21:07:17 +0100 -Subject: [PATCH] arm64: dts: ipq8074: update APCS node due to clock support - -APCS now has support for providing the APSS clocks as the child device -for IPQ8074, so update the DT node to reflect the expanded register space -as well as add #clock-cells property as it now provides the APSS clock -that will be used for CPU 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 -@@ -961,8 +961,9 @@ - - apcs_glb: mailbox@b111000 { - compatible = "qcom,ipq8074-apcs-apps-global"; -- reg = <0x0b111000 0x1000>; -+ reg = <0x0b111000 0x6000>; - -+ #clock-cells = <1>; - #mbox-cells = <1>; - }; - diff --git a/target/linux/ipq807x/patches-5.15/0136-arm64-dts-ipq8074-add-label-to-cpus.patch b/target/linux/ipq807x/patches-5.15/0136-arm64-dts-ipq8074-add-label-to-cpus.patch deleted file mode 100644 index 9f217405b..000000000 --- a/target/linux/ipq807x/patches-5.15/0136-arm64-dts-ipq8074-add-label-to-cpus.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 9fb45b1b02930be459d5722250c84532ce53b787 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Fri, 31 Dec 2021 18:42:53 +0100 -Subject: [PATCH] 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 -@@ -26,7 +26,7 @@ - }; - }; - -- cpus { -+ cpus: cpus { - #address-cells = <0x1>; - #size-cells = <0x0>; - diff --git a/target/linux/ipq807x/patches-5.15/0139-clk-qcom-ipq8074-add-missing-networking-resets.patch b/target/linux/ipq807x/patches-5.15/0139-clk-qcom-ipq8074-add-missing-networking-resets.patch deleted file mode 100644 index c3939be26..000000000 --- a/target/linux/ipq807x/patches-5.15/0139-clk-qcom-ipq8074-add-missing-networking-resets.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 0981de6ff0a072fd25d919e661ac22890a7a1e34 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Sat, 1 Jan 2022 18:15:03 +0100 -Subject: [PATCH] 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 -@@ -4785,6 +4785,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 const struct of_device_id gcc_ipq8074_match_table[] = { ---- a/include/dt-bindings/clock/qcom,gcc-ipq8074.h -+++ b/include/dt-bindings/clock/qcom,gcc-ipq8074.h -@@ -367,5 +367,19 @@ - #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 - - #endif diff --git a/target/linux/ipq807x/patches-5.15/0141-clk-qcom-ipq8074-disable-USB-GDSC-s-SW_COLLAPSE.patch b/target/linux/ipq807x/patches-5.15/0141-clk-qcom-ipq8074-disable-USB-GDSC-s-SW_COLLAPSE.patch deleted file mode 100644 index e2bd2a8fb..000000000 --- a/target/linux/ipq807x/patches-5.15/0141-clk-qcom-ipq8074-disable-USB-GDSC-s-SW_COLLAPSE.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 1a33a943c643b43033af936f297898b540361c62 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Sat, 1 Jan 2022 19:11:55 +0100 -Subject: [PATCH] clk: qcom: ipq8074: disable USB GDSC-s SW_COLLAPSE - -Like in IPQ6018 Qualcomm intentionally disables the SW_COLLAPSE on the USB -GDSC-s. - -This could potentially be better handled by utilizing the GDSC driver, but -I am not familiar with it nor do I have datasheets. - -Signed-off-by: Robert Marko ---- - drivers/clk/qcom/gcc-ipq8074.c | 5 +++++ - 1 file changed, 5 insertions(+) - ---- a/drivers/clk/qcom/gcc-ipq8074.c -+++ b/drivers/clk/qcom/gcc-ipq8074.c -@@ -4836,6 +4836,11 @@ static int gcc_ipq8074_probe(struct plat - /* SW Workaround for UBI32 Huayra PLL */ - regmap_update_bits(regmap, 0x2501c, BIT(26), BIT(26)); - -+ /* Disable SW_COLLAPSE for USB0 GDSCR */ -+ regmap_update_bits(regmap, 0x3e078, BIT(0), 0x0); -+ /* Disable SW_COLLAPSE for USB1 GDSCR */ -+ regmap_update_bits(regmap, 0x3f078, BIT(0), 0x0); -+ - clk_alpha_pll_configure(&ubi32_pll_main, regmap, &ubi32_pll_config); - clk_alpha_pll_configure(&nss_crypto_pll_main, regmap, - &nss_crypto_pll_config); diff --git a/target/linux/ipq807x/patches-5.15/0142-clk-qcom-ipq8074-SW-workaround-for-UBI32-PLL-lock.patch b/target/linux/ipq807x/patches-5.15/0142-clk-qcom-ipq8074-SW-workaround-for-UBI32-PLL-lock.patch deleted file mode 100644 index 6e54c4a9b..000000000 --- a/target/linux/ipq807x/patches-5.15/0142-clk-qcom-ipq8074-SW-workaround-for-UBI32-PLL-lock.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 124d46f0397daf0bc13270ee43cc7d8166170f04 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Sat, 1 Jan 2022 19:14:59 +0100 -Subject: [PATCH] clk: qcom: ipq8074: SW workaround for UBI32 PLL lock - -UBI32 Huayra PLL fails to lock in 5 us in some SoC silicon and thus it -will cause the wait_for_pll() to timeout and thus return the error -indicating that the PLL failed to lock. - -This is bug in Huayra PLL HW for which SW workaround -is to set bit 26 of TEST_CTL register. - -This is ported from the QCA 5.4 based downstream kernel. - -Signed-off-by: Robert Marko ---- - drivers/clk/qcom/gcc-ipq8074.c | 3 +++ - 1 file changed, 3 insertions(+) - ---- a/drivers/clk/qcom/gcc-ipq8074.c -+++ b/drivers/clk/qcom/gcc-ipq8074.c -@@ -4841,6 +4841,9 @@ static int gcc_ipq8074_probe(struct plat - /* Disable SW_COLLAPSE for USB1 GDSCR */ - regmap_update_bits(regmap, 0x3f078, BIT(0), 0x0); - -+ /* SW Workaround for UBI32 Huayra PLL */ -+ regmap_update_bits(regmap, 0x2501c, BIT(26), BIT(26)); -+ - clk_alpha_pll_configure(&ubi32_pll_main, regmap, &ubi32_pll_config); - clk_alpha_pll_configure(&nss_crypto_pll_main, regmap, - &nss_crypto_pll_config); diff --git a/target/linux/ipq807x/patches-5.15/0145-clk-qcom-ipq8074-add-PPE-crypto-clock.patch b/target/linux/ipq807x/patches-5.15/0145-clk-qcom-ipq8074-add-PPE-crypto-clock.patch deleted file mode 100644 index 5cff4e651..000000000 --- a/target/linux/ipq807x/patches-5.15/0145-clk-qcom-ipq8074-add-PPE-crypto-clock.patch +++ /dev/null @@ -1,61 +0,0 @@ -From f05295ef5e58a042f3a66490f6e75c6af83a329f Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Sun, 13 Mar 2022 12:46:28 +0100 -Subject: [PATCH] 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 ---- - drivers/clk/qcom/gcc-ipq8074.c | 19 +++++++++++++++++++ - include/dt-bindings/clock/qcom,gcc-ipq8074.h | 1 + - 2 files changed, 20 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[] = { ---- 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/ipq807x/patches-5.15/0300-regulator-add-Qualcomm-CPR-regulators.patch b/target/linux/ipq807x/patches-5.15/0300-regulator-add-Qualcomm-CPR-regulators.patch deleted file mode 100644 index a3df7474b..000000000 --- a/target/linux/ipq807x/patches-5.15/0300-regulator-add-Qualcomm-CPR-regulators.patch +++ /dev/null @@ -1,66 +0,0 @@ -From c013e84fa1cc1b8cd1ded28639a0f9745360aae6 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Mon, 11 Apr 2022 14:35:36 +0200 -Subject: [PATCH] regulator: add Qualcomm CPR regulators - -Allow building Qualcomm CPR regulators. - -Signed-off-by: Robert Marko ---- - drivers/regulator/Kconfig | 33 +++++++++++++++++++++++++++++++++ - drivers/regulator/Makefile | 3 +++ - 2 files changed, 36 insertions(+) - ---- 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 diff --git a/target/linux/ipq807x/patches-5.15/0301-power-Add-Qualcomm-APM.patch b/target/linux/ipq807x/patches-5.15/0301-power-Add-Qualcomm-APM.patch deleted file mode 100644 index a7ff87826..000000000 --- a/target/linux/ipq807x/patches-5.15/0301-power-Add-Qualcomm-APM.patch +++ /dev/null @@ -1,27 +0,0 @@ -From d90ef31dbb0212b20099a07d34f27dbeb06c5c74 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Mon, 11 Apr 2022 14:38:08 +0200 -Subject: [PATCH] power: Add Qualcomm APM - -Allow building Qualcomm APM. - -Signed-off-by: Robert Marko ---- - drivers/power/Kconfig | 1 + - drivers/power/Makefile | 1 + - 2 files changed, 2 insertions(+) - ---- 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/ diff --git a/target/linux/ipq807x/patches-5.15/0600-5.15-qca-nss-ecm-support-CORE.patch b/target/linux/ipq807x/patches-5.15/0600-5.15-qca-nss-ecm-support-CORE.patch deleted file mode 100644 index a6be2c15f..000000000 --- a/target/linux/ipq807x/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/ipq807x/patches-5.15/0601-5.15-netfilter-export-udp_get_timeouts-function.patch b/target/linux/ipq807x/patches-5.15/0601-5.15-netfilter-export-udp_get_timeouts-function.patch deleted file mode 100644 index c0504805b..000000000 --- a/target/linux/ipq807x/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/ipq807x/patches-5.15/0602-5.15-qca-add-pppoe-offload-support.patch b/target/linux/ipq807x/patches-5.15/0602-5.15-qca-add-pppoe-offload-support.patch deleted file mode 100644 index e1412b752..000000000 --- a/target/linux/ipq807x/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/ipq807x/patches-5.15/0603-net-core-Flag-to-identify-ingress-shaping-done-for-e.patch b/target/linux/ipq807x/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/ipq807x/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/ipq807x/patches-5.15/0605-5.15-qca-add-add-nss-bridge-mgr-support.patch b/target/linux/ipq807x/patches-5.15/0605-5.15-qca-add-add-nss-bridge-mgr-support.patch deleted file mode 100644 index 4cf919974..000000000 --- a/target/linux/ipq807x/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/ipq807x/patches-5.15/0606-5.15-qca-nss-ecm-bonding-add-bond_get_id.patch b/target/linux/ipq807x/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/ipq807x/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/ipq807x/patches-5.15/0607-5.15-qca-nss-ecm-Add-bridge-join-and-leave-netdev-cmds.patch b/target/linux/ipq807x/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/ipq807x/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/ipq807x/patches-5.15/0900-arm64-dts-add-OpenWrt-DTS-files.patch b/target/linux/ipq807x/patches-5.15/0900-arm64-dts-add-OpenWrt-DTS-files.patch deleted file mode 100644 index e91a00083..000000000 --- a/target/linux/ipq807x/patches-5.15/0900-arm64-dts-add-OpenWrt-DTS-files.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 8aec79b6d4d59616eb6ce4fbfb94658b3e79d9ce Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Tue, 11 May 2021 13:29:33 +0200 -Subject: [PATCH] arm64: dts: add OpenWrt DTS files - -Lets add custom OpenWrt DTS files to Makefile. - -Signed-off-by: Robert Marko ---- - 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,13 @@ 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) += ipq8070-tl-er2260t.dtb -+dtb-$(CONFIG_ARCH_QCOM) += ipq8071-ax6.dtb -+dtb-$(CONFIG_ARCH_QCOM) += ipq8071-ax3600.dtb -+dtb-$(CONFIG_ARCH_QCOM) += ipq8071-mf269.dtb -+dtb-$(CONFIG_ARCH_QCOM) += ipq8072-301w.dtb -+dtb-$(CONFIG_ARCH_QCOM) += ipq8078-xtr10890.dtb -+dtb-$(CONFIG_ARCH_QCOM) += ipq8074-nbg7815.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/ipq807x/patches-5.15/0902-5.15-arm64-provide-dma-cache-routines-with-same-API-as-32.patch b/target/linux/ipq807x/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/ipq807x/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/ipq807x/patches-5.15/0903-5.15-arm64-mm-export-__dma_inv_area-and-__dma_clean_area.patch b/target/linux/ipq807x/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/ipq807x/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/ipq807x/patches-5.15/0905-export-ns.patch b/target/linux/ipq807x/patches-5.15/0905-export-ns.patch deleted file mode 100644 index 1cd45c536..000000000 --- a/target/linux/ipq807x/patches-5.15/0905-export-ns.patch +++ /dev/null @@ -1,37 +0,0 @@ ---- a/net/ipv6/ndisc.c -+++ b/net/ipv6/ndisc.c -@@ -651,6 +651,34 @@ void ndisc_send_ns(struct net_device *de - ndisc_send_skb(skb, daddr, saddr); - } - -+EXPORT_SYMBOL(ndisc_send_ns); -+ -+struct net_device *ipv6_dev_find_and_hold(struct net *net, struct in6_addr *addr, -+ int strict) -+{ -+ struct inet6_ifaddr *ifp; -+ struct net_device *dev; -+ -+ ifp = ipv6_get_ifaddr(net, addr, NULL, strict); -+ if (!ifp) -+ return NULL; -+ -+ if (!ifp->idev) { -+ in6_ifa_put(ifp); -+ return NULL; -+ } -+ -+ dev = ifp->idev->dev; -+ if (dev) -+ dev_hold(dev); -+ -+ in6_ifa_put(ifp); -+ -+ return dev; -+} -+ -+EXPORT_SYMBOL(ipv6_dev_find_and_hold); -+ - void ndisc_send_rs(struct net_device *dev, const struct in6_addr *saddr, - const struct in6_addr *daddr) - { diff --git a/target/linux/qualcommax/Makefile b/target/linux/qualcommax/Makefile new file mode 100644 index 000000000..825cb7578 --- /dev/null +++ b/target/linux/qualcommax/Makefile @@ -0,0 +1,21 @@ +include $(TOPDIR)/rules.mk + +ARCH:=aarch64 +BOARD:=qualcommax +BOARDNAME:=Qualcomm Atheros 802.11ax WiSoC-s +FEATURES:=squashfs ramdisk fpu nand rtc emmc +KERNELNAME:=Image dtbs +CPU_TYPE:=cortex-a53 +SUBTARGETS:=ipq807x + +KERNEL_PATCHVER:=6.1 + +include $(INCLUDE_DIR)/target.mk +DEFAULT_PACKAGES += \ + kmod-usb3 kmod-usb-dwc3 kmod-usb-dwc3-qcom \ + kmod-leds-gpio kmod-gpio-button-hotplug \ + kmod-qca-nss-dp kmod-ath11k-ahb \ + wpad-openssl uboot-envtools \ + e2fsprogs kmod-fs-ext4 losetup + +$(eval $(call BuildTarget)) diff --git a/target/linux/ipq807x/config-5.15 b/target/linux/qualcommax/config-6.1 similarity index 79% rename from target/linux/ipq807x/config-5.15 rename to target/linux/qualcommax/config-6.1 index e7ffe68cd..74010c7ff 100644 --- a/target/linux/ipq807x/config-5.15 +++ b/target/linux/qualcommax/config-6.1 @@ -1,8 +1,8 @@ CONFIG_64BIT=y -CONFIG_AF_UNIX_OOB=y # CONFIG_APQ_GCC_8084 is not set # CONFIG_APQ_MMCC_8084 is not set -CONFIG_AQUANTIA_PHY=y +CONFIG_ARCH_BINFMT_ELF_EXTRA_PHDRS=y +CONFIG_ARCH_CORRECT_STACKTRACE_ON_KRETPROBE=y CONFIG_ARCH_DMA_ADDR_T_64BIT=y CONFIG_ARCH_HIBERNATION_POSSIBLE=y CONFIG_ARCH_KEEP_MEMBLOCK=y @@ -11,33 +11,40 @@ 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_NR_GPIO=0 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_ARCH_WANTS_THP_SWAP=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_ERRATUM_2051678=y +CONFIG_ARM64_ERRATUM_2054223=y +CONFIG_ARM64_ERRATUM_2067961=y +CONFIG_ARM64_ERRATUM_2077057=y +CONFIG_ARM64_ERRATUM_2658417=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_SME=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_ARM64_WORKAROUND_TSB_FLUSH_FAILURE=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 @@ -47,29 +54,31 @@ CONFIG_ARM_GIC_V3_ITS_PCI=y 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_ASN1=y +CONFIG_ARM_QCOM_CPUFREQ_NVMEM=y CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y -CONFIG_BINARY_PRINTF=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_SHADOW_CALL_STACK=y CONFIG_CC_HAVE_STACKPROTECTOR_SYSREG=y -CONFIG_CLANG_VERSION=0 +CONFIG_CC_IMPLICIT_FALLTHROUGH="-Wimplicit-fallthrough=5" +CONFIG_CC_NO_ARRAY_BOUNDS=y CONFIG_CLONE_BACKWARDS=y -CONFIG_CLZ_TAB=y CONFIG_COMMON_CLK=y CONFIG_COMMON_CLK_QCOM=y +CONFIG_COMPACT_UNEVICTABLE_DEFAULT=1 # CONFIG_COMPAT_32BIT_TIME is not set +CONFIG_CONTEXT_TRACKING=y +CONFIG_CONTEXT_TRACKING_IDLE=y CONFIG_COREDUMP=y CONFIG_CPUFREQ_DT=y CONFIG_CPUFREQ_DT_PLATDEV=y CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=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 @@ -77,37 +86,19 @@ 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_STAT=y CONFIG_CPU_FREQ_THERMAL=y CONFIG_CPU_IDLE=y CONFIG_CPU_IDLE_GOV_MENU=y CONFIG_CPU_IDLE_MULTIPLE_DRIVERS=y +CONFIG_CPU_LITTLE_ENDIAN=y CONFIG_CPU_PM=y CONFIG_CPU_RMAP=y CONFIG_CPU_THERMAL=y CONFIG_CRC16=y CONFIG_CRC8=y -CONFIG_CRYPTO_AES_ARM64=y -CONFIG_CRYPTO_AES_ARM64_BS=y -CONFIG_CRYPTO_AES_ARM64_CE=y -CONFIG_CRYPTO_AES_ARM64_CE_BLK=y -CONFIG_CRYPTO_AES_ARM64_CE_CCM=y -CONFIG_CRYPTO_AES_ARM64_NEON_BLK=y -CONFIG_CRYPTO_ANSI_CPRNG=y -CONFIG_CRYPTO_ARCH_HAVE_LIB_CHACHA=y -CONFIG_CRYPTO_ARCH_HAVE_LIB_POLY1305=y CONFIG_CRYPTO_AUTHENC=y -CONFIG_CRYPTO_BLAKE2B=y -CONFIG_CRYPTO_BLAKE2S=y CONFIG_CRYPTO_CBC=y -CONFIG_CRYPTO_CFB=y -CONFIG_CRYPTO_CHACHA20=y -CONFIG_CRYPTO_CHACHA20POLY1305=y -CONFIG_CRYPTO_CHACHA20_NEON=y -CONFIG_CRYPTO_CMAC=m -CONFIG_CRYPTO_CRCT10DIF=y -CONFIG_CRYPTO_CRYPTD=y -CONFIG_CRYPTO_CURVE25519=y CONFIG_CRYPTO_DEFLATE=y CONFIG_CRYPTO_DEV_QCE=y CONFIG_CRYPTO_DEV_QCE_AEAD=y @@ -119,77 +110,42 @@ 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_DH=y -CONFIG_CRYPTO_DRBG=y -CONFIG_CRYPTO_DRBG_HMAC=y -CONFIG_CRYPTO_DRBG_MENU=y CONFIG_CRYPTO_ECB=y -CONFIG_CRYPTO_ECC=y -CONFIG_CRYPTO_ECDH=y -CONFIG_CRYPTO_ECDSA=y -CONFIG_CRYPTO_ECRDSA=y -CONFIG_CRYPTO_GHASH_ARM64_CE=y CONFIG_CRYPTO_HASH_INFO=y -CONFIG_CRYPTO_HMAC=y CONFIG_CRYPTO_HW=y -CONFIG_CRYPTO_JITTERENTROPY=y -CONFIG_CRYPTO_KEYWRAP=y CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y -CONFIG_CRYPTO_LIB_CHACHA_GENERIC=y -CONFIG_CRYPTO_LIB_CURVE25519_GENERIC=y CONFIG_CRYPTO_LIB_DES=y -CONFIG_CRYPTO_LIB_POLY1305_GENERIC=y +CONFIG_CRYPTO_LIB_SHA1=y CONFIG_CRYPTO_LIB_SHA256=y -CONFIG_CRYPTO_LIB_SM4=y -CONFIG_CRYPTO_LRW=y +CONFIG_CRYPTO_LIB_UTILS=y CONFIG_CRYPTO_LZO=y -CONFIG_CRYPTO_MD4=y -CONFIG_CRYPTO_MD5=y -CONFIG_CRYPTO_NHPOLY1305=y -CONFIG_CRYPTO_NHPOLY1305_NEON=y -CONFIG_CRYPTO_OFB=y -CONFIG_CRYPTO_POLY1305=y -CONFIG_CRYPTO_POLY1305_NEON=y CONFIG_CRYPTO_RNG=y CONFIG_CRYPTO_RNG2=y -CONFIG_CRYPTO_RNG_DEFAULT=y -CONFIG_CRYPTO_RSA=y CONFIG_CRYPTO_SHA1=y -CONFIG_CRYPTO_SHA1_ARM64_CE=y CONFIG_CRYPTO_SHA256=y -CONFIG_CRYPTO_SHA256_ARM64=y -CONFIG_CRYPTO_SHA2_ARM64_CE=y -CONFIG_CRYPTO_SHA3=y -CONFIG_CRYPTO_SHA3_ARM64=y -CONFIG_CRYPTO_SHA512=y -CONFIG_CRYPTO_SHA512_ARM64=y -CONFIG_CRYPTO_SHA512_ARM64_CE=y -CONFIG_CRYPTO_SIMD=y -CONFIG_CRYPTO_SM2=y -CONFIG_CRYPTO_SM3=y -CONFIG_CRYPTO_SM3_ARM64_CE=y -CONFIG_CRYPTO_SM4_ARM64_CE=y -CONFIG_CRYPTO_STREEBOG=y CONFIG_CRYPTO_XTS=y -CONFIG_CRYPTO_XXHASH=y CONFIG_CRYPTO_ZSTD=y CONFIG_DCACHE_WORD_ACCESS=y +CONFIG_DEBUG_INFO=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_EXCLUSIVE_SYSTEM_RAM=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_FW_LOADER_SYSFS=y +CONFIG_GCC11_NO_ARRAY_BOUNDS=y +CONFIG_GCC_SUPPORTS_DYNAMIC_FTRACE_WITH_REGS=y CONFIG_GENERIC_ALLOCATOR=y CONFIG_GENERIC_ARCH_TOPOLOGY=y CONFIG_GENERIC_BUG=y @@ -200,9 +156,9 @@ 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_IOREMAP=y CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y CONFIG_GENERIC_IRQ_SHOW=y CONFIG_GENERIC_IRQ_SHOW_LEVEL=y @@ -220,10 +176,8 @@ CONFIG_GENERIC_STRNCPY_FROM_USER=y CONFIG_GENERIC_STRNLEN_USER=y CONFIG_GENERIC_TIME_VSYSCALL=y CONFIG_GLOB=y -CONFIG_GPIOLIB=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 @@ -236,15 +190,15 @@ 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 is not set -CONFIG_IPQ_APSS_8074=y -# CONFIG_IPQ_APSS_PLL is not set +CONFIG_IPQ_APSS_6018=y +CONFIG_IPQ_APSS_PLL=y # CONFIG_IPQ_GCC_4019 is not set # CONFIG_IPQ_GCC_6018 is not set # CONFIG_IPQ_GCC_806X is not set -CONFIG_IPQ_GCC_8074=y +# CONFIG_IPQ_GCC_8074 is not set # CONFIG_IPQ_LCC_806X is not set CONFIG_IRQCHIP=y CONFIG_IRQ_DOMAIN=y @@ -254,10 +208,8 @@ CONFIG_IRQ_FORCED_THREADING=y CONFIG_IRQ_WORK=y # CONFIG_KPSS_XCC is not set CONFIG_LIBFDT=y -CONFIG_LLD_VERSION=0 CONFIG_LOCK_DEBUGGING_SUPPORT=y CONFIG_LOCK_SPIN_ON_OWNER=y -CONFIG_LTO_NONE=y CONFIG_LZO_COMPRESS=y CONFIG_LZO_DECOMPRESS=y CONFIG_MAILBOX=y @@ -269,9 +221,7 @@ 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 @@ -284,12 +234,13 @@ CONFIG_MMC_SDHCI_MSM=y # CONFIG_MMC_SDHCI_PCI is not set CONFIG_MMC_SDHCI_PLTFM=y CONFIG_MODULES_USE_ELF_RELA=y -CONFIG_MPILIB=y # CONFIG_MSM_GCC_8660 is not set +# CONFIG_MSM_GCC_8909 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_8976 is not set # CONFIG_MSM_GCC_8994 is not set # CONFIG_MSM_GCC_8996 is not set # CONFIG_MSM_GCC_8998 is not set @@ -315,7 +266,6 @@ CONFIG_NEED_DMA_MAP_STATE=y CONFIG_NEED_SG_DMA_LENGTH=y CONFIG_NET_FLOW_LIMIT=y CONFIG_NET_SELFTESTS=y -CONFIG_NET_SOCK_MSG=y CONFIG_NET_SWITCHDEV=y CONFIG_NLS=y CONFIG_NO_HZ_COMMON=y @@ -323,8 +273,10 @@ 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_QCOM_QFPROM=y +# CONFIG_NVMEM_QCOM_SEC_QFPROM is not set CONFIG_NVMEM_SYSFS=y +CONFIG_NVMEM_U_BOOT_ENV=y CONFIG_OF=y CONFIG_OF_ADDRESS=y CONFIG_OF_EARLY_FLATTREE=y @@ -333,8 +285,10 @@ CONFIG_OF_GPIO=y CONFIG_OF_IRQ=y CONFIG_OF_KOBJ=y CONFIG_OF_MDIO=y -CONFIG_OID_REGISTRY=y CONFIG_PADATA=y +CONFIG_PAGE_POOL=y +CONFIG_PAGE_SIZE_LESS_THAN_256KB=y +CONFIG_PAGE_SIZE_LESS_THAN_64KB=y CONFIG_PARTITION_PERCPU=y CONFIG_PCI=y CONFIG_PCIEAER=y @@ -356,6 +310,7 @@ CONFIG_PGTABLE_LEVELS=3 CONFIG_PHYLIB=y CONFIG_PHYS_ADDR_T_64BIT=y # CONFIG_PHY_QCOM_APQ8064_SATA is not set +# CONFIG_PHY_QCOM_EDP 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 @@ -366,50 +321,47 @@ CONFIG_PHY_QCOM_QUSB2=y # 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 is not set -# CONFIG_PINCTRL_IPQ8064 is not set -CONFIG_PINCTRL_IPQ8074=y -# CONFIG_PINCTRL_MDM9615 is not set +# CONFIG_PINCTRL_IPQ8074 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 is not set +# CONFIG_PINCTRL_QCM2290 is not set # CONFIG_PINCTRL_QCOM_SSBI_PMIC is not set # CONFIG_PINCTRL_QCS404 is not set # CONFIG_PINCTRL_SC7180 is not set +# CONFIG_PINCTRL_SC8280XP is not set # CONFIG_PINCTRL_SDM660 is not set # CONFIG_PINCTRL_SDM845 is not set +# CONFIG_PINCTRL_SM6350 is not set +# CONFIG_PINCTRL_SM6375 is not set # CONFIG_PINCTRL_SM8150 is not set # CONFIG_PINCTRL_SM8250 is not set +# CONFIG_PINCTRL_SM8450 is not set CONFIG_PM=y -# CONFIG_PM8916_WATCHDOG is not set CONFIG_PM_CLK=y CONFIG_PM_OPP=y +CONFIG_POSIX_CPU_TIMERS_TASK_WORK=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_PREEMPT_NONE_BUILD=y CONFIG_PRINTK_TIME=y CONFIG_PTP_1588_CLOCK_OPTIONAL=y +# CONFIG_QCM_DISPCC_2290 is not set +# CONFIG_QCM_GCC_2290 is not set # CONFIG_QCOM_A53PLL is not set # CONFIG_QCOM_AOSS_QMP is not set CONFIG_QCOM_APCS_IPC=y -CONFIG_QCOM_APM=y +# CONFIG_QCOM_APM is not set # 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_COINCELL is not set # CONFIG_QCOM_COMMAND_DB is not set # CONFIG_QCOM_CPR is not set # CONFIG_QCOM_EBI2 is not set @@ -417,9 +369,11 @@ CONFIG_QCOM_BAM_DMA=y # CONFIG_QCOM_GENI_SE is not set # CONFIG_QCOM_GSBI is not set # CONFIG_QCOM_HFPLL is not set +# CONFIG_QCOM_ICC_BWMON is not set # CONFIG_QCOM_IPCC is not set # CONFIG_QCOM_LLCC is not set CONFIG_QCOM_MDT_LOADER=y +# CONFIG_QCOM_MPM is not set # CONFIG_QCOM_OCMEM is not set # CONFIG_QCOM_PDC is not set CONFIG_QCOM_PIL_INFO=y @@ -428,8 +382,6 @@ 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_QMI_HELPERS is not set # CONFIG_QCOM_RMTFS_MEM is not set # CONFIG_QCOM_RPMH is not set CONFIG_QCOM_RPROC_COMMON=y @@ -441,6 +393,8 @@ CONFIG_QCOM_SMEM_STATE=y CONFIG_QCOM_SMP2P=y # CONFIG_QCOM_SMSM is not set CONFIG_QCOM_SOCINFO=y +# CONFIG_QCOM_SPM is not set +# CONFIG_QCOM_STATS is not set # CONFIG_QCOM_SYSMON is not set CONFIG_QCOM_TSENS=y # CONFIG_QCOM_WCNSS_CTRL is not set @@ -451,18 +405,14 @@ CONFIG_QCOM_WDT=y # CONFIG_QCS_TURING_404 is not set CONFIG_QUEUED_RWLOCKS=y CONFIG_QUEUED_SPINLOCKS=y +CONFIG_RANDSTRUCT_NONE=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_SPMI=y -# CONFIG_REGULATOR_QCOM_USB_VBUS is not set +# CONFIG_REGULATOR_CPR3 is not set +CONFIG_REGULATOR_FIXED_VOLTAGE=y # CONFIG_REGULATOR_VQMMC_IPQ4019 is not set CONFIG_RELOCATABLE=y CONFIG_REMOTEPROC=y @@ -474,12 +424,16 @@ CONFIG_RFS_ACCEL=y CONFIG_RODATA_FULL_DEFAULT_ENABLED=y CONFIG_RPMSG=y CONFIG_RPMSG_CHAR=y +# CONFIG_RPMSG_CTRL is not set # 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_RPMSG_TTY is not set CONFIG_RPS=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_I2C_AND_SPI=y CONFIG_RWSEM_SPIN_ON_OWNER=y # CONFIG_SCHED_CORE is not set CONFIG_SCHED_MC=y @@ -489,10 +443,14 @@ CONFIG_SCSI=y CONFIG_SCSI_COMMON=y # CONFIG_SCSI_LOWLEVEL is not set # CONFIG_SCSI_PROC_FS is not set +# CONFIG_SC_CAMCC_7280 is not set # CONFIG_SC_DISPCC_7180 is not set # CONFIG_SC_GCC_7180 is not set +# CONFIG_SC_GCC_8280XP is not set # CONFIG_SC_GPUCC_7180 is not set +# CONFIG_SC_LPASSCC_7280 is not set # CONFIG_SC_LPASS_CORECC_7180 is not set +# CONFIG_SC_LPASS_CORECC_7280 is not set # CONFIG_SC_MSS_7180 is not set # CONFIG_SC_VIDEOCC_7180 is not set # CONFIG_SDM_CAMCC_845 is not set @@ -502,22 +460,27 @@ CONFIG_SCSI_COMMON=y # CONFIG_SDM_GPUCC_845 is not set # CONFIG_SDM_LPASSCC_845 is not set # CONFIG_SDM_VIDEOCC_845 is not set +# CONFIG_SDX_GCC_65 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_SHORTCUT_FE is not set CONFIG_SMP=y +# CONFIG_SM_CAMCC_8450 is not set # CONFIG_SM_GCC_8150 is not set # CONFIG_SM_GCC_8250 is not set +# CONFIG_SM_GCC_8450 is not set +# CONFIG_SM_GPUCC_6350 is not set # CONFIG_SM_GPUCC_8150 is not set # CONFIG_SM_GPUCC_8250 is not set +# CONFIG_SM_GPUCC_8350 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_SOFTIRQ_ON_OWN_STACK=y CONFIG_SPARSEMEM=y CONFIG_SPARSEMEM_EXTREME=y CONFIG_SPARSEMEM_VMEMMAP=y @@ -527,10 +490,6 @@ 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 @@ -544,6 +503,7 @@ CONFIG_THREAD_INFO_IN_TASK=y CONFIG_TICK_CPU_ACCOUNTING=y CONFIG_TIMER_OF=y CONFIG_TIMER_PROBE=y +CONFIG_TRACE_IRQFLAGS_NMI_SUPPORT=y CONFIG_TREE_RCU=y CONFIG_TREE_SRCU=y CONFIG_UBIFS_FS=y @@ -554,16 +514,18 @@ CONFIG_USB=y CONFIG_USB_COMMON=y CONFIG_USB_SUPPORT=y CONFIG_VIRTIO=y +CONFIG_VIRTIO_ANCHOR=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_XOR_BLOCKS=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_COMMON=y CONFIG_ZSTD_COMPRESS=y CONFIG_ZSTD_DECOMPRESS=y diff --git a/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8070-cax1800.dts b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8070-cax1800.dts new file mode 100644 index 000000000..3415426a9 --- /dev/null +++ b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8070-cax1800.dts @@ -0,0 +1,322 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT +/* Copyright (c) 2021, Dirk Buchwalder */ + +/dts-v1/; + +#include "ipq8074-512m.dtsi" +#include "ipq8074-ac-cpu.dtsi" +#include "ipq8074-ess.dtsi" +#include +#include + +/ { + model = "Edimax CAX1800"; + compatible = "edimax,cax1800", "qcom,ipq8074"; + + aliases { + serial0 = &blsp1_uart5; + led-boot = &led_system_red; + led-failsafe = &led_system_red; + led-running = &led_system_green; + led-upgrade = &led_system_red; + /* Aliases as required by u-boot to patch MAC addresses */ + ethernet0 = &dp5; + label-mac-device = &dp5; + }; + + chosen { + stdout-path = "serial0:115200n8"; + bootargs-append = " root=/dev/ubiblock0_1"; + }; + + keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + gpios = <&tlmm 32 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + leds { + compatible = "gpio-leds"; + + led_system_red: system-red { + label = "red:system"; + gpios = <&tlmm 25 GPIO_ACTIVE_HIGH>; + }; + + led_system_green: system-green { + label = "green:system"; + gpios = <&tlmm 26 GPIO_ACTIVE_HIGH>; + }; + + led_system_blue: system-blue { + label = "blue:system"; + gpios = <&tlmm 27 GPIO_ACTIVE_HIGH>; + }; + }; +}; + +&tlmm { + mdio_pins: mdio-pins { + mdc { + pins = "gpio68"; + function = "mdc"; + drive-strength = <8>; + bias-pull-up; + }; + + mdio { + pins = "gpio69"; + function = "mdio"; + drive-strength = <8>; + bias-pull-up; + }; + }; +}; + +&blsp1_uart5 { + status = "okay"; +}; + +&prng { + status = "okay"; +}; + +&cryptobam { + status = "okay"; +}; + +&crypto { + 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 = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "rootfs"; + reg = <0x0000000 0x3400000>; + }; + }; + }; +}; + +&blsp1_spi1 { + pinctrl-0 = <&spi_0_pins>; + pinctrl-names = "default"; + cs-select = <0>; + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + reg = <0>; + compatible = "jedec,spi-nor"; + spi-max-frequency = <50000000>; + use-default-sizes; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "0:sbl1"; + reg = <0x0 0x50000>; + read-only; + }; + + partition@50000 { + label = "0:mibib"; + reg = <0x50000 0x10000>; + read-only; + }; + + partition@60000 { + label = "0:bootconfig"; + reg = <0x60000 0x20000>; + read-only; + }; + + partition@80000 { + label = "0:bootconfig1"; + reg = <0x80000 0x20000>; + read-only; + }; + + partition@a0000 { + label = "0:qsee"; + reg = <0xa0000 0x180000>; + read-only; + }; + + partition@220000 { + label = "0:qsee_1"; + reg = <0x220000 0x180000>; + read-only; + }; + + partition@3a0000 { + label = "0:devcfg"; + reg = <0x3a0000 0x10000>; + read-only; + }; + + partition@3b0000 { + label = "0:devcfg_1"; + reg = <0x3b0000 0x10000>; + read-only; + }; + + partition@3c0000 { + label = "0:apdp"; + reg = <0x3c0000 0x10000>; + read-only; + }; + + partition@3d0000 { + label = "0:apdp_1"; + reg = <0x3d0000 0x10000>; + read-only; + }; + + partition@3e0000 { + label = "0:rpm"; + reg = <0x3e0000 0x40000>; + read-only; + }; + + partition@420000 { + label = "0:rpm_1"; + reg = <0x420000 0x40000>; + read-only; + }; + + partition@460000 { + label = "0:cdt"; + reg = <0x460000 0x10000>; + read-only; + }; + + partition@470000 { + label = "0:cdt_1"; + reg = <0x470000 0x10000>; + read-only; + }; + + partition@480000 { + label = "0:appsblenv"; + reg = <0x480000 0x10000>; + }; + + partition@490000 { + label = "0:appsbl"; + reg = <0x490000 0xa0000>; + read-only; + }; + + partition@530000 { + label = "0:appsbl_1"; + reg = <0x530000 0xa0000>; + read-only; + }; + + partition@5d0000 { + label = "0:art"; + reg = <0x5d0000 0x40000>; + read-only; + }; + + partition@610000 { + label = "0:ethphyfw"; + reg = <0x610000 0x80000>; + read-only; + }; + }; + }; +}; + +&mdio { + status = "okay"; + + pinctrl-0 = <&mdio_pins>; + pinctrl-names = "default"; + + reset-gpios = <&tlmm 37 GPIO_ACTIVE_LOW>; + + qca8075: 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_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*/ + bm_tick_mode = <0>; /* bm tick mode */ + tm_tick_mode = <0>; /* tm tick mode */ + + 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"; +}; + +&dp5 { + status = "okay"; + phy-handle = <&qca8075>; + label = "lan"; +}; + +&wifi { + status = "okay"; + + qcom,ath11k-calibration-variant = "Edimax-CAX1800"; + qcom,ath11k-fw-memory-mode = <1>; +}; diff --git a/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8070-rm2-6.dts b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8070-rm2-6.dts new file mode 100644 index 000000000..ee9d23e09 --- /dev/null +++ b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8070-rm2-6.dts @@ -0,0 +1,250 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +/dts-v1/; + +#include "ipq8074-512m.dtsi" +#include "ipq8074-ac-cpu.dtsi" +#include "ipq8074-ess.dtsi" +#include +#include + +/ { + model = "CMCC RM2-6"; + compatible = "cmcc,rm2-6", "qcom,ipq8074"; + + aliases { + serial0 = &blsp1_uart5; + serial1 = &blsp1_uart3; + led-boot = &led_status_red; + led-failsafe = &led_status_red; + led-running = &led_status_blue; + led-upgrade = &led_status_amber; + /* + * Aliases as required by u-boot + * to patch MAC addresses + */ + ethernet0 = &dp4; + ethernet1 = &dp2; + ethernet2 = &dp5; + label-mac-device = &dp4; + }; + + chosen { + stdout-path = "serial0:115200n8"; + bootargs-append = " root=/dev/ubiblock0_1"; + }; + + keys { + compatible = "gpio-keys"; + + wps { + label = "wps"; + linux,code = ; + gpios = <&tlmm 27 GPIO_ACTIVE_LOW>; + }; + + reset { + label = "reset"; + linux,code = ; + gpios = <&tlmm 30 GPIO_ACTIVE_LOW>; + }; + }; + + leds { + compatible = "gpio-leds"; + + led_status_amber: status-amber { + label = "amber:status"; + gpio = <&tlmm 25 GPIO_ACTIVE_HIGH>; + }; + + led_status_blue: status-blue { + label = "blue:status"; + gpio = <&tlmm 26 GPIO_ACTIVE_HIGH>; + }; + + led_status_red: status-red { + label = "red:status"; + gpio = <&tlmm 31 GPIO_ACTIVE_HIGH>; + }; + }; + + fan: gpio-fan { + #cooling-cells = <2>; + compatible = "gpio-fan"; + gpio = <&tlmm 29 GPIO_ACTIVE_HIGH>; + gpio-fan,speed-map = <0 0>, <1 1>; + }; +}; + +&tlmm { + mdio_pins: mdio-pins { + mdc { + pins = "gpio68"; + function = "mdc"; + drive-strength = <8>; + bias-pull-up; + }; + + mdio { + pins = "gpio69"; + function = "mdio"; + drive-strength = <8>; + bias-pull-up; + }; + }; +}; + +&blsp1_uart3 { + status = "okay"; +}; + +&blsp1_uart5 { + status = "okay"; +}; + +&cryptobam { + status = "okay"; +}; + +&crypto { + status = "okay"; +}; + +&prng { + status = "okay"; +}; + +&qpic_bam { + status = "okay"; +}; + +&qpic_nand { + status = "okay"; + + nand@0 { + reg = <0>; + nand-ecc-strength = <8>; + nand-ecc-step-size = <512>; + nand-bus-width = <8>; + + partitions { + compatible = "qcom,smem-part"; + }; + }; +}; + +&cpu0_thermal { + trips { + cpu0_trip_active: cpu-active { + temperature = <60000>; + hysteresis = <2000>; + type = "active"; + }; + }; + + cooling-maps { + cpu-active { + cooling-device = <&fan 1 1>; + trip = <&cpu0_trip_active>; + }; + }; +}; + +&cluster_thermal { + trips { + cluster_active: cluster-active { + temperature = <60000>; + hysteresis = <2000>; + type = "active"; + }; + }; + + cooling-maps { + cluster-active { + cooling-device = <&fan 1 1>; + trip = <&cluster_active>; + }; + }; +}; + +&mdio { + status = "okay"; + + pinctrl-0 = <&mdio_pins>; + pinctrl-names = "default"; + reset-gpios = <&tlmm 37 GPIO_ACTIVE_LOW>; + + qca8075_1: ethernet-phy@1 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <1>; + }; + + 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_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*/ + bm_tick_mode = <0>; /* bm tick mode */ + tm_tick_mode = <0>; /* tm tick mode */ + + qcom,port_phyinfo { + port@2 { + port_id = <2>; + phy_address = <1>; + }; + port@4 { + port_id = <4>; + phy_address = <3>; + }; + port@5 { + port_id = <5>; + phy_address = <4>; + }; + }; +}; + +&edma { + status = "okay"; +}; + +/* Hi5630 PLC */ +&dp2 { + status = "okay"; + phy-handle = <&qca8075_1>; + label = "plc"; +}; + +&dp4 { + status = "okay"; + phy-handle = <&qca8075_3>; + label = "lan"; +}; + +&dp5 { + status = "okay"; + phy-handle = <&qca8075_4>; + label = "wan"; +}; + +&wifi { + status = "okay"; + + qcom,ath11k-calibration-variant = "CMCC-RM2-6"; + qcom,ath11k-fw-memory-mode = <1>; +}; diff --git a/target/linux/ipq807x/files-5.10/arch/arm64/boot/dts/qcom/ipq8071-ax3600.dts b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8071-ax3600.dts similarity index 100% rename from target/linux/ipq807x/files-5.10/arch/arm64/boot/dts/qcom/ipq8071-ax3600.dts rename to target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8071-ax3600.dts diff --git a/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8071-ax3600.dtsi b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8071-ax3600.dtsi new file mode 100644 index 000000000..f4ebfc8f4 --- /dev/null +++ b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8071-ax3600.dtsi @@ -0,0 +1,190 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT +/* Copyright (c) 2021, Robert Marko */ + +#include "ipq8074-512m.dtsi" +#include "ipq8074-ac-cpu.dtsi" +#include "ipq8074-ess.dtsi" +#include +#include + +/ { + aliases { + serial0 = &blsp1_uart5; + led-boot = &led_system_yellow; + led-failsafe = &led_system_yellow; + led-running = &led_system_blue; + led-upgrade = &led_system_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"; + gpios = <&tlmm 34 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; +}; + +&tlmm { + mdio_pins: mdio-pins { + mdc { + pins = "gpio68"; + function = "mdc"; + drive-strength = <8>; + bias-pull-up; + }; + + mdio { + pins = "gpio69"; + function = "mdio"; + drive-strength = <8>; + bias-pull-up; + }; + }; +}; + +&blsp1_uart5 { + status = "okay"; +}; + +&prng { + status = "okay"; +}; + +&cryptobam { + status = "okay"; +}; + +&crypto { + 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 37 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_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*/ + bm_tick_mode = <0>; /* bm tick mode */ + tm_tick_mode = <0>; /* tm tick mode */ + + 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 = "wan"; +}; + +&dp3 { + status = "okay"; + phy-handle = <&qca8075_2>; + label = "lan1"; +}; + +&dp4 { + status = "okay"; + phy-handle = <&qca8075_3>; + label = "lan2"; +}; + +&dp5 { + status = "okay"; + phy-handle = <&qca8075_4>; + label = "lan3"; +}; + +&wifi { + status = "okay"; + + qcom,ath11k-fw-memory-mode = <1>; +}; diff --git a/target/linux/ipq807x/files-5.10/arch/arm64/boot/dts/qcom/ipq8071-ax6.dts b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8071-ax6.dts similarity index 100% rename from target/linux/ipq807x/files-5.10/arch/arm64/boot/dts/qcom/ipq8071-ax6.dts rename to target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8071-ax6.dts diff --git a/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8071-eap102.dts b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8071-eap102.dts new file mode 100644 index 000000000..357b6368d --- /dev/null +++ b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8071-eap102.dts @@ -0,0 +1,389 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT +/* Copyright (c) 2022, Matthew Hagan */ + +/dts-v1/; + +#include "ipq8074.dtsi" +#include "ipq8074-ac-cpu.dtsi" +#include "ipq8074-ess.dtsi" +#include +#include + +/ { + model = "Edgecore EAP102"; + compatible = "edgecore,eap102", "qcom,ipq8074"; + + aliases { + serial0 = &blsp1_uart5; + serial1 = &blsp1_uart3; + led-boot = &led_system_green; + led-failsafe = &led_system_green; + led-running = &led_system_green; + led-upgrade = &led_system_green; + /* Aliases as required by u-boot to patch MAC addresses */ + ethernet0 = &dp5; + ethernet1 = &dp6; + label-mac-device = &dp5; + }; + + chosen { + stdout-path = "serial0:115200n8"; + bootargs-append = " root=/dev/ubiblock0_1"; + }; + + keys { + compatible = "gpio-keys"; + pinctrl-0 = <&button_pins>; + pinctrl-names = "default"; + + reset { + label = "reset"; + gpios = <&tlmm 66 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + leds { + compatible = "gpio-leds"; + + led_wanpoe { + label = "green:wanpoe"; + gpios = <&tlmm 46 GPIO_ACTIVE_HIGH>; + }; + + led_wlan2g { + label = "green:wlan2g"; + gpio = <&tlmm 47 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "phy1radio"; + }; + + led_wlan5g { + label = "green:wlan5g"; + gpio = <&tlmm 48 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "phy0radio"; + }; + + led_system_green: led_system { + label = "green:power"; + gpios = <&tlmm 50 GPIO_ACTIVE_HIGH>; + }; + }; +}; + +&tlmm { + mdio_pins: mdio-pins { + mdc { + pins = "gpio68"; + function = "mdc"; + drive-strength = <8>; + bias-pull-up; + }; + + mdio { + pins = "gpio69"; + function = "mdio"; + drive-strength = <8>; + bias-pull-up; + }; + }; + + button_pins: button_pins { + reset_button { + pins = "gpio66"; + function = "gpio"; + drive-strength = <8>; + bias-pull-up; + }; + }; +}; + +&blsp1_spi1 { + status = "okay"; + + flash@0 { + #address-cells = <1>; + #size-cells = <1>; + reg = <0>; + compatible = "jedec,spi-nor"; + spi-max-frequency = <50000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "0:sbl1"; + reg = <0x0 0x50000>; + read-only; + }; + + partition@50000 { + label = "0:mibib"; + reg = <0x50000 0x10000>; + read-only; + }; + + partition@60000 { + label = "0:bootconfig"; + reg = <0x60000 0x20000>; + read-only; + }; + + partition@80000 { + label = "0:bootconfig1"; + reg = <0x80000 0x20000>; + read-only; + }; + + partition@a0000 { + label = "0:qsee"; + reg = <0xa0000 0x180000>; + read-only; + }; + + partition@220000 { + label = "0:qsee_1"; + reg = <0x220000 0x180000>; + read-only; + }; + + partition@3a0000 { + label = "0:devcfg"; + reg = <0x3a0000 0x10000>; + read-only; + }; + + partition@3b0000 { + label = "0:devcfg_1"; + reg = <0x3b0000 0x10000>; + read-only; + }; + + partition@3c0000 { + label = "0:apdp"; + reg = <0x3c0000 0x10000>; + read-only; + }; + + partition@3d0000 { + label = "0:apdp_1"; + reg = <0x3d0000 0x10000>; + read-only; + }; + + partition@3e0000 { + label = "0:rpm"; + reg = <0x3e0000 0x40000>; + read-only; + }; + + partition@420000 { + label = "0:rpm_1"; + reg = <0x420000 0x40000>; + read-only; + }; + + partition@460000 { + label = "0:cdt"; + reg = <0x460000 0x10000>; + read-only; + }; + + partition@470000 { + label = "0:cdt_1"; + reg = <0x470000 0x10000>; + read-only; + }; + + partition@480000 { + label = "0:appsblenv"; + reg = <0x480000 0x10000>; + }; + + partition@490000 { + label = "0:appsbl"; + reg = <0x490000 0xc0000>; + read-only; + }; + + partition@550000 { + label = "0:appsbl_1"; + reg = <0x530000 0xc0000>; + read-only; + }; + + partition@610000 { + label = "0:art"; + reg = <0x610000 0x40000>; + read-only; + }; + + partition@650000 { + label = "0:ethphyfw"; + reg = <0x650000 0x80000>; + read-only; + }; + + partition@6d0000 { + label = "0:product_info"; + reg = <0x6d0000 0x80000>; + read-only; + }; + + partition@750000 { + label = "priv_data1"; + reg = <0x750000 0x10000>; + read-only; + }; + + partition@760000 { + label = "priv_data2"; + reg = <0x760000 0x10000>; + read-only; + }; + }; + }; +}; + +&blsp1_uart3 { + status = "okay"; +}; + +&blsp1_uart5 { + status = "okay"; +}; + +&crypto { + status = "okay"; +}; + +&cryptobam { + status = "okay"; +}; + +&prng { + status = "okay"; +}; + +&qpic_bam { + status = "okay"; +}; + +&qusb_phy_0 { + status = "okay"; +}; + +&ssphy_0 { + status = "okay"; +}; + +&usb_0 { + status = "okay"; +}; + +&qpic_nand { + status = "okay"; + + nand@0 { + reg = <0>; + nand-ecc-strength = <8>; + nand-ecc-step-size = <512>; + nand-bus-width = <8>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "rootfs1"; + reg = <0x0000000 0x3400000>; + }; + + partition@3400000 { + label = "0:wififw"; + reg = <0x3400000 0x800000>; + read-only; + }; + + partition@3c00000 { + label = "rootfs2"; + reg = <0x3c00000 0x3400000>; + }; + + partition@7000000 { + label = "0:wififw_1"; + reg = <0x7000000 0x800000>; + read-only; + }; + }; + }; +}; + +&mdio { + status = "okay"; + + pinctrl-0 = <&mdio_pins>; + pinctrl-names = "default"; + + qca8081_24: ethernet-phy@24 { + compatible = "ethernet-phy-id004d.d101"; + reg = <24>; + reset-gpios = <&tlmm 33 GPIO_ACTIVE_LOW>; + }; + + qca8081_28: ethernet-phy@28 { + compatible = "ethernet-phy-id004d.d101"; + reg = <28>; + reset-gpios = <&tlmm 44 GPIO_ACTIVE_LOW>; + }; +}; + +&switch { + status = "okay"; + + switch_cpu_bmp = <0x1>; /* cpu port bitmap */ + switch_lan_bmp = <0x3e>; /* lan port bitmap */ + switch_wan_bmp = <0x40>; /* wan port bitmap */ + switch_mac_mode = <0xff>; /* mac mode for uniphy instance0*/ + switch_mac_mode1 = <0xf>; /* mac mode for uniphy instance1*/ + switch_mac_mode2 = <0xf>; /* mac mode for uniphy instance2*/ + bm_tick_mode = <0>; /* bm tick mode */ + tm_tick_mode = <0>; /* tm tick mode */ + + qcom,port_phyinfo { + port@4 { + port_id = <5>; + phy_address = <24>; + port_mac_sel = "QGMAC_PORT"; + }; + port@5 { + port_id = <6>; + phy_address = <28>; + port_mac_sel = "QGMAC_PORT"; + }; + }; +}; + +&edma { + status = "okay"; +}; + +&dp5 { + status = "okay"; + phy-handle = <&qca8081_28>; + label = "wan"; +}; + +&dp6 { + status = "okay"; + phy-handle = <&qca8081_24>; + label = "lan"; +}; + +&wifi { + status = "okay"; + + qcom,ath11k-calibration-variant = "Edgecore-EAP102"; +}; diff --git a/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8071-mf269.dts b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8071-mf269.dts new file mode 100644 index 000000000..628f1c627 --- /dev/null +++ b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8071-mf269.dts @@ -0,0 +1,432 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +/dts-v1/; + +#include "ipq8074-512m.dtsi" +#include "ipq8074-ac-cpu.dtsi" +#include "ipq8074-ess.dtsi" +#include +#include + +/ { + model = "ZTE MF269"; + compatible = "zte,mf269", "qcom,ipq8074"; + + aliases { + serial0 = &blsp1_uart5; + led-boot = &led_power; + led-failsafe = &led_power; + led-running = &led_power; + led-upgrade = &led_power; + label-mac-device = &dp6_syn; + }; + + chosen { + stdout-path = "serial0:115200n8"; + bootargs-append = " root=/dev/ubiblock0_1"; + }; + + keys { + compatible = "gpio-keys"; + pinctrl-0 = <&button_pins>; + pinctrl-names = "default"; + + wps { + label = "wps"; + linux,code = ; + gpios = <&tlmm 37 GPIO_ACTIVE_LOW>; + }; + + reset { + label = "reset"; + linux,code = ; + gpios = <&tlmm 46 GPIO_ACTIVE_LOW>; + }; + }; + + leds { + compatible = "gpio-leds"; + + led_power: power { + label = "white:power"; + gpio = <&tlmm 56 GPIO_ACTIVE_HIGH>; + }; + }; +}; + +&tlmm { + button_pins: button_pins { + mux { + pins = "gpio37", "gpio46"; + function = "gpio"; + drive-strength = <8>; + bias-pull-up; + }; + }; + + i2c_pins: i2c-pins { + pins = "gpio21", "gpio22"; + function = "blsp4_i2c1"; + drive-strength = <8>; + bias-disable; + }; + + mdio_pins: mdio-pins { + mdc { + pins = "gpio68"; + function = "mdc"; + drive-strength = <8>; + bias-pull-up; + }; + + mdio { + pins = "gpio69"; + function = "mdio"; + drive-strength = <8>; + bias-pull-up; + }; + }; + + usb_pwr_pins: usb_pwr_pins { + mux { + pins = "gpio29"; + function = "gpio"; + drive-strength = <8>; + bias-disable; + output-high; + }; + }; +}; + +&blsp1_spi1 { + pinctrl-0 = <&spi_0_pins>; + pinctrl-names = "default"; + cs-select = <0>; + status = "okay"; + + flash@0 { + compatible = "jedec,spi-nor"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0>; + spi-max-frequency = <50000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "0:sbl1"; + reg = <0x0 0x50000>; + read-only; + }; + + partition@50000 { + label = "0:mibib"; + reg = <0x50000 0x10000>; + read-only; + }; + + partition@60000 { + label = "0:bootconfig"; + reg = <0x60000 0x20000>; + read-only; + }; + + partition@80000 { + label = "0:bootconfig1"; + reg = <0x80000 0x20000>; + read-only; + }; + + partition@a0000 { + label = "0:qsee"; + reg = <0xa0000 0x180000>; + read-only; + }; + + partition@220000 { + label = "0:qsee_1"; + reg = <0x220000 0x180000>; + read-only; + }; + + partition@3a0000 { + label = "0:devcfg"; + reg = <0x3a0000 0x10000>; + read-only; + }; + + partition@3b0000 { + label = "0:devcfg_1"; + reg = <0x3b0000 0x10000>; + read-only; + }; + + partition@3c0000 { + label = "0:apdp"; + reg = <0x3c0000 0x10000>; + read-only; + }; + + partition@3d0000 { + label = "0:apdp_1"; + reg = <0x3d0000 0x10000>; + read-only; + }; + + partition@3e0000 { + label = "0:rpm"; + reg = <0x3e0000 0x40000>; + read-only; + }; + + partition@420000 { + label = "0:rpm_1"; + reg = <0x420000 0x40000>; + read-only; + }; + + partition@460000 { + label = "0:cdt"; + reg = <0x460000 0x10000>; + read-only; + }; + + partition@470000 { + label = "0:cdt_1"; + reg = <0x470000 0x10000>; + read-only; + }; + + partition@480000 { + label = "0:appsblenv"; + reg = <0x480000 0x10000>; + }; + + partition@490000 { + label = "0:appsbl"; + reg = <0x490000 0xc0000>; + read-only; + }; + + partition@550000 { + label = "0:appsbl_1"; + reg = <0x550000 0xc0000>; + read-only; + }; + + partition@610000 { + label = "0:art"; + reg = <0x610000 0x40000>; + read-only; + }; + + partition@650000 { + label = "0:ethphyfw"; + reg = <0x650000 0x80000>; + read-only; + }; + }; + }; +}; + +&blsp1_i2c5 { + pinctrl-0 = <&i2c_pins>; + pinctrl-names = "default"; + status = "okay"; + + aw9106: gpio-expander@5b { + compatible = "aw9106b"; + reg = <0x5b>; + reset-gpios = <&tlmm 54 GPIO_ACTIVE_HIGH>; + }; +}; + +&blsp1_uart5 { + status = "okay"; +}; + +&cryptobam { + status = "okay"; +}; + +&crypto { + status = "okay"; +}; + +&prng { + status = "okay"; +}; + +&qpic_bam { + status = "okay"; +}; + +&qpic_nand { + status = "okay"; + + partitions { + status = "disabled"; + }; + + nand@0 { + reg = <0>; + nand-ecc-strength = <4>; + nand-ecc-step-size = <512>; + nand-bus-width = <8>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "fota-flag"; + reg = <0x0000000 0x00a0000>; + read-only; + }; + + partition@a0000 { + label = "mac"; + reg = <0x00a0000 0x0080000>; + read-only; + + compatible = "nvmem-cells"; + #address-cells = <1>; + #size-cells = <1>; + + macaddr_mac_0: macaddr@0 { + reg = <0x0 0x6>; + }; + }; + + partition@120000 { + label = "cfg-param"; + reg = <0x0120000 0x1400000>; + read-only; + }; + + partition@1520000 { + label = "log"; + reg = <0x1520000 0x0600000>; + read-only; + }; + + partition@1b20000 { + label = "oops"; + reg = <0x1b20000 0x00a0000>; + read-only; + }; + + partition@1bc0000 { + label = "web"; + reg = <0x1bc0000 0x0800000>; + read-only; + }; + + partition@23c0000 { + label = "oem-ubi"; + reg = <0x23c0000 0x3400000>; + }; + + partition@57c0000 { + label = "0:wififw"; + reg = <0x57c0000 0x0800000>; + read-only; + }; + + partition@5fc0000 { + label = "rootfs"; + reg = <0x5fc0000 0x9a00000>; + }; + }; + }; +}; + +&qusb_phy_0 { + status = "okay"; +}; + +&ssphy_0 { + status = "okay"; +}; + +&usb_0 { + pinctrl-0 = <&usb_pwr_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&mdio { + status = "okay"; + + pinctrl-0 = <&mdio_pins>; + pinctrl-names = "default"; + + qca8081_24: ethernet-phy@24 { + compatible = "ethernet-phy-id004d.d101"; + reg = <24>; + reset-gpios = <&tlmm 25 GPIO_ACTIVE_LOW>; + }; + + qca8081_28: ethernet-phy@28 { + compatible = "ethernet-phy-id004d.d101"; + reg = <28>; + reset-gpios = <&tlmm 44 GPIO_ACTIVE_LOW>; + }; +}; + +&switch { + status = "okay"; + + switch_cpu_bmp = <0x1>; /* cpu port bitmap */ + switch_lan_bmp = <0x3e>; /* lan port bitmap */ + switch_wan_bmp = <0x40>; /* wan port bitmap */ + switch_mac_mode = <0xff>; /* mac mode for uniphy instance0*/ + switch_mac_mode1 = <0xf>; /* mac mode for uniphy instance1*/ + switch_mac_mode2 = <0xf>; /* mac mode for uniphy instance2*/ + bm_tick_mode = <0>; /* bm tick mode */ + tm_tick_mode = <0>; /* tm tick mode */ + + qcom,port_phyinfo { + port@5 { + port_id = <5>; + phy_address = <24>; + port_mac_sel = "QGMAC_PORT"; + }; + port@6 { + port_id = <6>; + phy_address = <28>; + port_mac_sel = "QGMAC_PORT"; + }; + }; +}; + +&edma { + status = "okay"; +}; + +&dp5_syn { + status = "okay"; + phy-handle = <&qca8081_24>; + label = "lan"; + nvmem-cell-names = "mac-address"; + nvmem-cells = <&macaddr_mac_0 1>; +}; + +&dp6_syn { + status = "okay"; + phy-handle = <&qca8081_28>; + label = "wan"; + nvmem-cell-names = "mac-address"; + nvmem-cells = <&macaddr_mac_0 0>; +}; + +&wifi { + status = "okay"; + + qcom,ath11k-calibration-variant = "ZTE-MF269"; + qcom,ath11k-fw-memory-mode = <1>; +}; diff --git a/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8072-301w.dts b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8072-301w.dts new file mode 100644 index 000000000..d15b9f5b0 --- /dev/null +++ b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8072-301w.dts @@ -0,0 +1,409 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT +/* Copyright (c) 2021, Dirk Buchwalder */ + +/dts-v1/; + +#include "ipq8074.dtsi" +#include "ipq8074-hk-cpu.dtsi" +#include "ipq8074-ess.dtsi" +#include +#include +#include + +/ { + model = "QNAP 301w"; + compatible = "qnap,301w", "qcom,ipq8074"; + + aliases { + serial0 = &blsp1_uart5; + /* + * Aliases as required by u-boot + * to patch MAC addresses + */ + led-boot = &led_system_red; + led-failsafe = &led_system_red; + led-running = &led_pwr_green; + led-upgrade = &led_system_red; + ethernet0 = &dp1; + ethernet1 = &dp2; + ethernet2 = &dp3; + ethernet3 = &dp4; + ethernet4 = &dp5; + ethernet5 = &dp6_syn; + label-mac-device = &dp1; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + keys { + compatible = "gpio-keys"; + pinctrl-0 = <&button_pins>; + pinctrl-names = "default"; + + wps-button { + label = "wps"; + gpios = <&tlmm 57 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + + reset-button { + label = "reset"; + gpios = <&tlmm 67 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-0 = <&leds_pins>; + pinctrl-names = "default"; + + led_system_green: led-system-green { + label = "green:system"; + gpios = <&tlmm 1 GPIO_ACTIVE_HIGH>; + color = ; + }; + + led_system_red: led-system-red { + label = "red:system"; + gpios = <&tlmm 3 GPIO_ACTIVE_HIGH>; + color = ; + }; + + led_pwr_green: led-pwr-green { + label = "green:pwr"; + gpios = <&tlmm 4 GPIO_ACTIVE_HIGH>; + color = ; + }; + + led-wifi-green { + label = "green:wifi"; + gpios = <&tlmm 42 GPIO_ACTIVE_HIGH>; + color = ; + }; + + led-lan4-green { + label = "green:lan4"; + gpios = <&tlmm 6 GPIO_ACTIVE_HIGH>; + color = ; + }; + + led-lan4-amber { + label = "amber:lan4"; + gpios = <&tlmm 7 GPIO_ACTIVE_HIGH>; + color = ; + }; + + led-lan3-green { + label = "green:lan3"; + gpios = <&tlmm 8 GPIO_ACTIVE_HIGH>; + color = ; + }; + + led-lan3-amber { + label = "amber:lan3"; + gpios = <&tlmm 11 GPIO_ACTIVE_HIGH>; + color = ; + }; + + led-lan2-green { + label = "green:lan2"; + gpios = <&tlmm 12 GPIO_ACTIVE_HIGH>; + color = ; + }; + + led-lan2-amber { + label = "amber:lan2"; + gpios = <&tlmm 13 GPIO_ACTIVE_HIGH>; + color = ; + }; + + led-lan1-green { + label = "green:lan1"; + gpios = <&tlmm 14 GPIO_ACTIVE_HIGH>; + color = ; + }; + + led-lan1-amber { + label = "amber:lan1"; + gpios = <&tlmm 15 GPIO_ACTIVE_HIGH>; + color = ; + }; + + led-10g-1-green { + label = "green:10g_1"; + gpios = <&tlmm 54 GPIO_ACTIVE_HIGH>; + color = ; + }; + + led-10g-1-amber { + label = "amber:10g_1"; + gpios = <&tlmm 56 GPIO_ACTIVE_HIGH>; + color = ; + }; + + led-10g-2-green { + label = "green:10g_2"; + gpios = <&tlmm 51 GPIO_ACTIVE_HIGH>; + color = ; + }; + + led-10g-2-amber { + label = "amber:10g_2"; + gpios = <&tlmm 52 GPIO_ACTIVE_HIGH>; + color = ; + }; + }; +}; + +&tlmm { + mdio_pins: mdio-state { + mdc-pins { + pins = "gpio68"; + function = "mdc"; + drive-strength = <8>; + bias-pull-up; + }; + + mdio-pins { + pins = "gpio69"; + function = "mdio"; + drive-strength = <8>; + bias-pull-up; + }; + }; + + button_pins: button-state { + wps-pins { + pins = "gpio57"; + function = "gpio"; + drive-strength = <8>; + bias-pull-up; + }; + + rst-pins { + pins = "gpio67"; + function = "gpio"; + drive-strength = <8>; + bias-pull-up; + }; + }; + + leds_pins: leds-state { + pins = "gpio1", "gpio3", "gpio4", "gpio6", "gpio7", "gpio8", + "gpio11", "gpio12", "gpio13", "gpio14", "gpio15", "gpio42", + "gpio51", "gpio52", "gpio54", "gpio56"; + function = "gpio"; + drive-strength = <8>; + bias-pull-down; + }; +}; + +&blsp1_uart5 { + status = "okay"; +}; + +&prng { + status = "okay"; +}; + +&ssphy_0 { + status = "okay"; +}; + +&qusb_phy_0 { + status = "okay"; +}; + +&ssphy_1 { + status = "okay"; +}; + +&qusb_phy_1 { + status = "okay"; +}; + +&usb_0 { + status = "okay"; +}; + +&usb_1 { + status = "okay"; +}; + +&cryptobam { + status = "okay"; +}; + +&crypto { + status = "okay"; +}; + +&qpic_bam { + status = "okay"; +}; + +&blsp1_spi1 { + pinctrl-0 = <&spi_0_pins>; + pinctrl-names = "default"; + cs-gpios = <0>; + status = "okay"; + + flash@0 { + #address-cells = <1>; + #size-cells = <1>; + reg = <0>; + compatible = "jedec,spi-nor"; + spi-max-frequency = <50000000>; + + partitions { + compatible = "qcom,smem-part"; + }; + }; +}; + +&mdio { + status = "okay"; + + pinctrl-0 = <&mdio_pins>; + pinctrl-names = "default"; + reset-gpios = <&tlmm 37 GPIO_ACTIVE_LOW>; + + aqr113c_0: ethernet-phy@0 { + compatible ="ethernet-phy-ieee802.3-c45"; + reg = <0>; + reset-gpios = <&tlmm 59 GPIO_ACTIVE_LOW>; + }; + + aqr113c_8: ethernet-phy@8 { + compatible ="ethernet-phy-ieee802.3-c45"; + reg = <8>; + reset-gpios = <&tlmm 44 GPIO_ACTIVE_LOW>; + }; + + qca8075_16: ethernet-phy@16 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <16>; + }; + + qca8075_17: ethernet-phy@17 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <17>; + }; + + qca8075_18: ethernet-phy@18 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <18>; + }; + + qca8075_19: ethernet-phy@19 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <19>; + }; +}; + +&sdhc_1 { + status = "okay"; + + /* According to the stock dts from the QNAP gpl drop + * the emmc has a problem with the hs400 > hs200 speed switch. + * Therefore remove the mmc-hs400-1_8v property + */ + /delete-property/ mmc-hs400-1_8v; + mmc-hs200-1_8v; + mmc-ddr-1_8v; + vqmmc-supply = <&l11>; +}; + +&switch { + status = "okay"; + + switch_cpu_bmp = <0x1>; /* cpu port bitmap */ + switch_lan_bmp = <0x3e>; /* lan port bitmap */ + switch_wan_bmp = <0xc0>; /* wan port bitmap */ + switch_mac_mode = <0xb>; /* mac mode for uniphy instance0*/ + switch_mac_mode1 = <0xd>; /* mac mode for uniphy instance1*/ + switch_mac_mode2 = <0xd>; /* mac mode for uniphy instance2*/ + bm_tick_mode = <0>; /* bm tick mode */ + tm_tick_mode = <0>; /* tm tick mode */ + + qcom,port_phyinfo { + port@0 { + port_id = <1>; + phy_address = <16>; + }; + port@1 { + port_id = <2>; + phy_address = <17>; + }; + port@2 { + port_id = <3>; + phy_address = <18>; + }; + port@3 { + port_id = <4>; + phy_address = <19>; + }; + port@4 { + port_id = <5>; + phy_address = <8>; + compatible = "ethernet-phy-ieee802.3-c45"; + ethernet-phy-ieee802.3-c45; + }; + port@5 { + port_id = <6>; + phy_address = <0>; + compatible = "ethernet-phy-ieee802.3-c45"; + ethernet-phy-ieee802.3-c45; + }; + }; +}; + +&edma { + status = "okay"; +}; + +&dp1 { + status = "okay"; + phy-handle = <&qca8075_16>; + label = "lan4"; +}; + +&dp2 { + status = "okay"; + phy-handle = <&qca8075_17>; + label = "lan3"; +}; + +&dp3 { + status = "okay"; + phy-handle = <&qca8075_18>; + label = "lan2"; +}; + +&dp4 { + status = "okay"; + phy-handle = <&qca8075_19>; + label = "lan1"; +}; + +&dp5 { + status = "okay"; + qcom,mactype = <1>; + phy-handle = <&aqr113c_8>; + label = "10g-1"; +}; + +&dp6_syn { + status = "okay"; + phy-handle = <&aqr113c_0>; + label = "10g-2"; +}; + +&wifi { + status = "okay"; + + qcom,ath11k-calibration-variant = "QNAP-301w"; +}; diff --git a/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8072-aw1000.dts b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8072-aw1000.dts new file mode 100644 index 000000000..715398518 --- /dev/null +++ b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8072-aw1000.dts @@ -0,0 +1,352 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +/dts-v1/; + +#include "ipq8074.dtsi" +#include "ipq8074-hk-cpu.dtsi" +#include "ipq8074-ess.dtsi" +#include +#include + +/ { + model = "Arcadyan AW1000"; + compatible = "arcadyan,aw1000", "qcom,ipq8074"; + + aliases { + led-boot = &led_power; + led-failsafe = &led_power; + led-running = &led_power; + led-upgrade = &led_power; + serial0 = &blsp1_uart5; + /* + * Aliases as required by u-boot + * to patch MAC addresses + */ + ethernet0 = &dp1; + ethernet1 = &dp2; + ethernet2 = &dp3; + ethernet3 = &dp4; + ethernet4 = &dp6_syn; + label-mac-device = &dp1; + }; + + chosen { + stdout-path = "serial0:115200n8"; + bootargs-append = " root=/dev/ubiblock0_1"; + }; + + gpio-export { + compatible = "gpio-export"; + + lte-pwrkey { + gpio-export,name = "lte_pwrkey"; + gpio-export,output = <1>; + gpios = <&tlmm 54 GPIO_ACTIVE_HIGH>; + }; + + lte-power { + gpio-export,name = "lte_power"; + gpio-export,output = <1>; + gpios = <&tlmm 30 GPIO_ACTIVE_HIGH>; + }; + + lte-reset { + gpio-export,name = "lte_reset"; + gpio-export,output = <1>; + gpios = <&tlmm 63 GPIO_ACTIVE_HIGH>; + }; + + usb-vbus { + gpio-export,name = "usb_vbus"; + gpio-export,output = <0>; + gpios = <&tlmm 9 GPIO_ACTIVE_LOW>; + }; + }; + + keys { + compatible = "gpio-keys"; + + wlan { + label = "wlan"; + linux,code = ; + gpios = <&tlmm 2 GPIO_ACTIVE_LOW>; + }; + + wps { + label = "wps"; + linux,code = ; + gpios = <&tlmm 62 GPIO_ACTIVE_LOW>; + }; + + reset { + label = "reset"; + linux,code = ; + gpios = <&tlmm 67 GPIO_ACTIVE_LOW>; + }; + }; + + led-spi { + compatible = "spi-gpio"; + #address-cells = <1>; + #size-cells = <0>; + + sck-gpios = <&tlmm 18 GPIO_ACTIVE_HIGH>; + mosi-gpios = <&tlmm 19 GPIO_ACTIVE_HIGH>; + + led_gpio: led-gpio@0 { + compatible = "fairchild,74hc595"; + reg = <0>; + gpio-controller; + #gpio-cells = <2>; + registers-number = <2>; + spi-max-frequency = <1000000>; + enable-gpios = <&tlmm 20 GPIO_ACTIVE_HIGH>; + }; + }; + + leds { + compatible = "gpio-leds"; + + led_power: power { + label = "green:power"; + gpios = <&led_gpio 0 GPIO_ACTIVE_HIGH>; + }; + + wifi { + label = "green:wifi"; + gpios = <&led_gpio 1 GPIO_ACTIVE_HIGH>; + }; + + internet { + label = "green:internet"; + gpios = <&led_gpio 2 GPIO_ACTIVE_HIGH>; + }; + + 5g-red { + label = "red:5g"; + gpios = <&led_gpio 3 GPIO_ACTIVE_LOW>; + }; + + 5g-green { + label = "green:5g"; + gpios = <&led_gpio 4 GPIO_ACTIVE_LOW>; + }; + + 5g-blue { + label = "blue:5g"; + gpios = <&led_gpio 5 GPIO_ACTIVE_LOW>; + }; + + signal-red { + label = "red:signal"; + gpios = <&led_gpio 6 GPIO_ACTIVE_LOW>; + }; + + signal-green { + label = "green:signal"; + gpios = <&led_gpio 8 GPIO_ACTIVE_LOW>; + }; + + signal-blue { + label = "blue:signal"; + gpios = <&led_gpio 9 GPIO_ACTIVE_LOW>; + }; + + phone { + label = "green:phone"; + gpios = <&led_gpio 11 GPIO_ACTIVE_HIGH>; + }; + }; +}; + +&tlmm { + mdio_pins: mdio-pins { + mdc { + pins = "gpio68"; + function = "mdc"; + drive-strength = <8>; + bias-pull-up; + }; + + mdio { + pins = "gpio69"; + function = "mdio"; + drive-strength = <8>; + bias-pull-up; + }; + }; +}; + +&blsp1_uart5 { + status = "okay"; +}; + +&cryptobam { + status = "okay"; +}; + +&crypto { + status = "okay"; +}; + +&prng { + status = "okay"; +}; + +&qpic_bam { + status = "okay"; +}; + +&qpic_nand { + status = "okay"; + + nand@0 { + reg = <0>; + nand-ecc-strength = <8>; + nand-ecc-step-size = <512>; + nand-bus-width = <8>; + + partitions { + compatible = "qcom,smem-part"; + }; + }; +}; + +&qusb_phy_0 { + status = "okay"; +}; + +&qusb_phy_1 { + status = "okay"; +}; + +&ssphy_0 { + status = "okay"; +}; + +&ssphy_1 { + status = "okay"; +}; + +&usb_0 { + status = "okay"; +}; + +&usb_1 { + status = "okay"; +}; + +&mdio { + status = "okay"; + + pinctrl-0 = <&mdio_pins>; + pinctrl-names = "default"; + reset-gpios = <&tlmm 37 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>; + }; + + qca8081: ethernet-phy@28 { + compatible = "ethernet-phy-id004d.d101"; + reg = <28>; + reset-gpios = <&tlmm 64 GPIO_ACTIVE_LOW>; + }; +}; + +&switch { + status = "okay"; + + switch_cpu_bmp = <0x1>; /* cpu port bitmap */ + switch_lan_bmp = <0x3e>; /* lan port bitmap */ + switch_wan_bmp = <0x40>; /* wan port bitmap */ + switch_mac_mode = <0x0>; /* mac mode for uniphy instance0*/ + switch_mac_mode1 = <0xff>; /* mac mode for uniphy instance1*/ + switch_mac_mode2 = <0xf>; /* mac mode for uniphy instance2*/ + bm_tick_mode = <0>; /* bm tick mode */ + tm_tick_mode = <0>; /* tm tick mode */ + + 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>; + }; + port@5 { + port_id = <6>; + phy_address = <28>; + port_mac_sel = "QGMAC_PORT"; + }; + }; +}; + +&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"; +}; + +&dp6_syn { + status = "okay"; + phy-handle = <&qca8081>; + label = "wan"; +}; + +&wifi { + status = "okay"; + + qcom,ath11k-calibration-variant = "Arcadyan-AW1000"; +}; diff --git a/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8072-ax9000.dts b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8072-ax9000.dts new file mode 100644 index 000000000..fd1f32ada --- /dev/null +++ b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8072-ax9000.dts @@ -0,0 +1,343 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT +/* Copyright (c) 2021, Robert Marko */ + +/dts-v1/; + +#include "ipq8074.dtsi" +#include "ipq8074-hk-cpu.dtsi" +#include "ipq8074-ess.dtsi" +#include +#include +#include + +/ { + model = "Xiaomi AX9000"; + compatible = "xiaomi,ax9000", "qcom,ipq8074"; + + aliases { + serial0 = &blsp1_uart5; + led-boot = &led_system_yellow; + led-failsafe = &led_system_yellow; + led-running = &led_system_blue; + led-upgrade = &led_system_yellow; + label-mac-device = &dp5; + + ethernet0 = &dp1; + 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"; + gpios = <&tlmm 47 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + + wps { + label = "wps"; + gpios = <&tlmm 46 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + leds { + compatible = "gpio-leds"; + + led_system_blue: system-blue { + label = "blue:system"; + gpios = <&tlmm 48 GPIO_ACTIVE_HIGH>; + color = ; + }; + + led_system_yellow: system-yellow { + label = "yellow:system"; + gpios = <&tlmm 52 GPIO_ACTIVE_HIGH>; + color = ; + }; + + network-yellow { + label = "yellow:network"; + gpios = <&tlmm 50 GPIO_ACTIVE_HIGH>; + color = ; + }; + + network-blue { + label = "blue:network"; + gpios = <&tlmm 51 GPIO_ACTIVE_HIGH>; + color = ; + }; + + top-red { + label = "red:top"; + gpios = <&tlmm 63 GPIO_ACTIVE_HIGH>; + color = ; + default-state = "keep"; + }; + + top-green { + label = "green:top"; + gpios = <&tlmm 64 GPIO_ACTIVE_HIGH>; + color = ; + default-state = "keep"; + }; + + top-blue { + label = "blue:top"; + gpios = <&tlmm 66 GPIO_ACTIVE_HIGH>; + color = ; + default-state = "keep"; + }; + }; +}; + +&tlmm { + mdio_pins: mdio-pins { + mdc { + pins = "gpio68"; + function = "mdc"; + drive-strength = <8>; + bias-pull-up; + }; + + mdio { + pins = "gpio69"; + function = "mdio"; + drive-strength = <8>; + bias-pull-up; + }; + }; + + i2c_pins: i2c-pins { + pins = "gpio0", "gpio2"; + function = "blsp5_i2c"; + drive-strength = <8>; + bias-disable; + }; +}; + +&blsp1_uart5 { + status = "okay"; +}; + +&blsp1_i2c6 { + status = "okay"; + + pinctrl-0 = <&i2c_pins>; + pinctrl-names = "default"; +}; + +&prng { + status = "okay"; +}; + +&cryptobam { + status = "okay"; +}; + +&crypto { + 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"; + }; + }; +}; + +&qusb_phy_0 { + status = "okay"; +}; + +&ssphy_0 { + status = "okay"; +}; + +&usb_0 { + status = "okay"; +}; + +&mdio { + status = "okay"; + + pinctrl-0 = <&mdio_pins>; + pinctrl-names = "default"; + reset-gpios = <&tlmm 37 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>; + }; + + qca8081: ethernet-phy@24 { + compatible = "ethernet-phy-id004d.d101"; + reg = <24>; + reset-gpios = <&tlmm 44 GPIO_ACTIVE_LOW>; + }; +}; + +&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_mac_mode = <0xb>; /* mac mode for uniphy instance0*/ + switch_mac_mode1 = <0xc>; /* mac mode for uniphy instance1*/ + switch_mac_mode2 = <0xff>; /* mac mode for uniphy instance2*/ + bm_tick_mode = <0>; /* bm tick mode */ + tm_tick_mode = <0>; /* tm tick mode */ + + 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 = <24>; + port_mac_sel = "QGMAC_PORT"; + }; + }; +}; + +&edma { + status = "okay"; +}; + +&dp1 { + status = "okay"; + phy-handle = <&qca8075_0>; + label = "lan4"; +}; + +&dp2 { + status = "okay"; + phy-handle = <&qca8075_1>; + label = "lan3"; +}; + +&dp3 { + status = "okay"; + phy-handle = <&qca8075_2>; + label = "lan2"; +}; + +&dp4 { + status = "okay"; + phy-handle = <&qca8075_3>; + label = "lan1"; +}; + +&dp5 { + status = "okay"; + phy-handle = <&qca8081>; + label = "wan"; +}; + +&pcie_qmp0 { + status = "okay"; +}; + +&pcie0 { + status = "okay"; + + perst-gpio = <&tlmm 58 GPIO_ACTIVE_LOW>; + + bridge@0,0 { + reg = <0x00000000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + ranges; + + wifi@1,0 { + status = "okay"; + + compatible = "pci17cb,1104"; + reg = <0x00010000 0 0 0 0>; + + qcom,ath11k-calibration-variant = "Xiaomi-AX9000"; + }; + }; +}; + +&pcie_qmp1 { + status = "okay"; +}; + +&pcie1 { + status = "okay"; + + perst-gpio = <&tlmm 62 GPIO_ACTIVE_HIGH>; + + bridge@1,0 { + reg = <0x00010000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + ranges; + + wifi@1,0 { + status = "okay"; + + compatible = "qcom,ath10k"; + reg = <0x00010000 0 0 0 0>; + + qcom,ath10k-calibration-variant = "Xiaomi-AX9000"; + }; + }; +}; + +&wifi { + status = "okay"; + + qcom,ath11k-calibration-variant = "Xiaomi-AX9000"; +}; diff --git a/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8072-dl-wrx36.dts b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8072-dl-wrx36.dts new file mode 100644 index 000000000..5468e9e1f --- /dev/null +++ b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8072-dl-wrx36.dts @@ -0,0 +1,243 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT +/* Copyright (c) 2022, Robert Marko */ + +/dts-v1/; + +#include "ipq8074.dtsi" +#include "ipq8074-hk-cpu.dtsi" +#include "ipq8074-ess.dtsi" +#include +#include +#include + +/ { + model = "Dynalink DL-WRX36"; + compatible = "dynalink,dl-wrx36", "qcom,ipq8074"; + + aliases { + led-boot = &led_system_red; + led-failsafe = &led_system_red; + led-running = &led_system_blue; + led-upgrade = &led_system_red; + serial0 = &blsp1_uart5; + /* Aliases as required by u-boot to patch MAC addresses */ + ethernet0 = &dp6_syn; + ethernet1 = &dp4; + ethernet2 = &dp3; + ethernet3 = &dp2; + ethernet4 = &dp1; + label-mac-device = &dp6_syn; + }; + + chosen { + stdout-path = "serial0:115200n8"; + bootargs-append = " root=/dev/ubiblock0_1"; + }; + + keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + gpios = <&tlmm 34 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + + wps { + label = "wps"; + gpios = <&tlmm 63 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + leds { + compatible = "gpio-leds"; + + led_system_blue: system-blue { + label = "blue:system"; + gpios = <&tlmm 26 GPIO_ACTIVE_HIGH>; + color = ; + }; + + led_system_red: system-red { + label = "red:system"; + gpios = <&tlmm 25 GPIO_ACTIVE_HIGH>; + color = ; + }; + }; +}; + +&tlmm { + mdio_pins: mdio-pins { + mdc { + pins = "gpio68"; + function = "mdc"; + drive-strength = <8>; + bias-pull-up; + }; + + mdio { + pins = "gpio69"; + function = "mdio"; + drive-strength = <8>; + bias-pull-up; + }; + }; +}; + +&blsp1_uart5 { + status = "okay"; +}; + +&prng { + status = "okay"; +}; + +&cryptobam { + status = "okay"; +}; + +&crypto { + status = "okay"; +}; + +&qpic_bam { + status = "okay"; +}; + +&qpic_nand { + status = "okay"; + + nand@0 { + reg = <0>; + nand-ecc-strength = <8>; + nand-ecc-step-size = <512>; + nand-bus-width = <8>; + + partitions { + compatible = "qcom,smem-part"; + }; + }; +}; + +&qusb_phy_0 { + status = "okay"; +}; + +&ssphy_0 { + status = "okay"; +}; + +&usb_0 { + status = "okay"; +}; + +&mdio { + status = "okay"; + + pinctrl-0 = <&mdio_pins>; + pinctrl-names = "default"; + reset-gpios = <&tlmm 37 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>; + }; + + qca8081: ethernet-phy@28 { + compatible = "ethernet-phy-id004d.d101"; + reg = <28>; + reset-gpios = <&tlmm 44 GPIO_ACTIVE_LOW>; + }; +}; + +&switch { + status = "okay"; + + switch_cpu_bmp = <0x1>; /* cpu port bitmap */ + switch_lan_bmp = <0x3e>; /* lan port bitmap */ + switch_wan_bmp = <0x40>; /* wan port bitmap */ + switch_mac_mode = <0xb>; /* mac mode for uniphy instance0*/ + switch_mac_mode1 = <0xff>; /* mac mode for uniphy instance1*/ + switch_mac_mode2 = <0xc>; /* mac mode for uniphy instance2*/ + bm_tick_mode = <0>; /* bm tick mode */ + tm_tick_mode = <0>; /* tm tick mode */ + + 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@5 { + port_id = <6>; + phy_address = <28>; + port_mac_sel = "QGMAC_PORT"; + }; + }; +}; + +&edma { + status = "okay"; +}; + +&dp1 { + status = "okay"; + phy-handle = <&qca8075_0>; + label = "lan4"; +}; + +&dp2 { + status = "okay"; + phy-handle = <&qca8075_1>; + label = "lan3"; +}; + +&dp3 { + status = "okay"; + phy-handle = <&qca8075_2>; + label = "lan2"; +}; + +&dp4 { + status = "okay"; + phy-handle = <&qca8075_3>; + label = "lan1"; +}; + +&dp6_syn { + status = "okay"; + phy-handle = <&qca8081>; + label = "wan"; +}; + +&wifi { + status = "okay"; + qcom,ath11k-calibration-variant = "Dynalink-DL-WRX36"; +}; diff --git a/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8072-haze.dts b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8072-haze.dts new file mode 100644 index 000000000..3aa2e8878 --- /dev/null +++ b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8072-haze.dts @@ -0,0 +1,307 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +/dts-v1/; + +#include "ipq8074.dtsi" +#include "ipq8074-hk-cpu.dtsi" +#include "ipq8074-ess.dtsi" +#include +#include +#include + +/ { + model = "prpl Foundation Haze"; + compatible = "prpl,haze", "qcom,ipq8074"; + + aliases { + serial0 = &blsp1_uart5; + /* Aliases are required by U-Boot to patch MAC addresses */ + ethernet0 = &dp6_syn; + ethernet1 = &dp4; + ethernet2 = &dp3; + ethernet3 = &dp2; + label-mac-device = &dp6_syn; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + keys { + compatible = "gpio-keys"; + pinctrl-0 = <&button_pins>; + pinctrl-names = "default"; + + wps-button { + label = "wps"; + gpios = <&tlmm 42 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + + reset-button { + label = "reset"; + gpios = <&tlmm 44 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; +}; + +&tlmm { + mdio_pins: mdio-state { + mdc-pins { + pins = "gpio68"; + function = "mdc"; + drive-strength = <8>; + bias-pull-up; + }; + + mdio-pins { + pins = "gpio69"; + function = "mdio"; + drive-strength = <8>; + bias-pull-up; + }; + }; + + button_pins: button-state { + wps-pins { + pins = "gpio42"; + function = "gpio"; + drive-strength = <8>; + bias-pull-up; + }; + + rst-pins { + pins = "gpio44"; + function = "gpio"; + drive-strength = <8>; + bias-pull-up; + }; + }; +}; + +&blsp1_uart5 { + status = "okay"; +}; + +&prng { + status = "okay"; +}; + +&ssphy_0 { + status = "okay"; +}; + +&qusb_phy_0 { + status = "okay"; +}; + +&ssphy_1 { + status = "okay"; +}; + +&qusb_phy_1 { + status = "okay"; +}; + +&usb_0 { + status = "okay"; +}; + +&usb_1 { + status = "okay"; +}; + +&cryptobam { + status = "okay"; +}; + +&crypto { + status = "okay"; +}; + +&qpic_bam { + status = "okay"; +}; + +&blsp1_spi1 { + pinctrl-0 = <&spi_0_pins>; + pinctrl-names = "default"; + cs-gpios = <0>; + status = "okay"; + + flash@0 { + #address-cells = <1>; + #size-cells = <1>; + reg = <0>; + compatible = "jedec,spi-nor"; + spi-max-frequency = <50000000>; + + partitions { + compatible = "qcom,smem-part"; + }; + }; +}; + +&mdio { + status = "okay"; + + pinctrl-0 = <&mdio_pins>; + pinctrl-names = "default"; + reset-gpios = <&tlmm 22 GPIO_ACTIVE_LOW>; + + qca8075_1: ethernet-phy@0 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <0>; + }; + + qca8075_2: ethernet-phy@1 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <1>; + }; + + qca8075_3: ethernet-phy@2 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <2>; + }; + + qca8075_4: ethernet-phy@3 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <3>; + }; + + aqr113c: ethernet-phy@5 { + compatible ="ethernet-phy-ieee802.3-c45"; + reg = <8>; + reset-gpios = <&tlmm 43 GPIO_ACTIVE_LOW>; + }; +}; + +&sdhc_1 { + status = "okay"; + + vqmmc-supply = <&l11>; +}; + +&switch { + status = "okay"; + + switch_cpu_bmp = <0x1>; /* cpu port bitmap */ + switch_lan_bmp = <0x1e>; /* lan port bitmap */ + switch_wan_bmp = <0x60>; /* wan port bitmap */ + switch_mac_mode = <0x0>; /* mac mode for uniphy instance0*/ + switch_mac_mode1 = <0xe>; /* mac mode for uniphy instance1*/ + switch_mac_mode2 = <0xd>; /* mac mode for uniphy instance2*/ + bm_tick_mode = <0>; /* bm tick mode */ + tm_tick_mode = <0>; /* tm tick mode */ + + 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 = <6>; + phy_address = <8>; + compatible = "ethernet-phy-ieee802.3-c45"; + ethernet-phy-ieee802.3-c45; + }; + }; +}; + +&edma { + status = "okay"; +}; + +/* Dummy LAN port */ +&dp1 { + status = "disabled"; + phy-handle = <&qca8075_1>; + label = "lan4"; +}; + +&dp2 { + status = "okay"; + phy-handle = <&qca8075_2>; + label = "lan3"; +}; + +&dp3 { + status = "okay"; + phy-handle = <&qca8075_3>; + label = "lan2"; +}; + +&dp4 { + status = "okay"; + phy-handle = <&qca8075_4>; + label = "lan1"; +}; + +&dp6_syn { + status = "okay"; + qcom,mactype = <1>; + phy-handle = <&aqr113c>; + label = "wan"; +}; + +&pcie_qmp0 { + status = "okay"; +}; + +&pcie0 { + status = "okay"; + + perst-gpio = <&tlmm 58 GPIO_ACTIVE_LOW>; + + bridge@0,0 { + reg = <0x00020000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + ranges; + }; +}; + +&pcie_qmp1 { + status = "okay"; +}; + +&pcie1 { + status = "okay"; + + perst-gpio = <&tlmm 61 GPIO_ACTIVE_LOW>; + + bridge@1,0 { + reg = <0x00010000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + ranges; + + wifi@1,0 { + status = "okay"; + + compatible = "pci17cb,1104"; + reg = <0x00010000 0 0 0 0>; + + qcom,ath11k-calibration-variant = "prpl-Haze"; + }; + }; +}; + +&wifi { + status = "okay"; + + qcom,ath11k-calibration-variant = "prpl-Haze"; +}; diff --git a/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8072-wax218.dts b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8072-wax218.dts new file mode 100644 index 000000000..5bfcdcc8c --- /dev/null +++ b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8072-wax218.dts @@ -0,0 +1,191 @@ +/dts-v1/; + +#include "ipq8074.dtsi" +#include "ipq8074-hk-cpu.dtsi" +#include "ipq8074-ess.dtsi" + +#include +#include + +/ { + model = "Netgear WAX218"; + compatible = "netgear,wax218", "qcom,ipq8074"; + + aliases { + serial0 = &blsp1_uart5; + led-boot = &led_power_amber; + led-failsafe = &led_power_amber; + led-running = &led_power_amber; + led-upgrade = &led_power_amber; + }; + + chosen { + stdout-path = "serial0:115200n8"; + /* + * Netgear's U-Boot adds "ubi.mtd=rootfs root=mtd:ubi_rootfs" + * That fails to create a UBI block device, so add it here. + */ + bootargs-append = " ubi.block=0,rootfs root=/dev/ubiblock0_1"; + }; + + keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + gpios = <&tlmm 52 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + led_spi { + compatible = "spi-gpio"; + #address-cells = <1>; + #size-cells = <0>; + + sck-gpios = <&tlmm 18 GPIO_ACTIVE_HIGH>; + mosi-gpios = <&tlmm 19 GPIO_ACTIVE_HIGH>; + + led_gpio: led_gpio@0 { + compatible = "fairchild,74hc595"; + reg = <0>; + gpio-controller; + #gpio-cells = <2>; + registers-number = <1>; + enable-gpios = <&tlmm 20 GPIO_ACTIVE_HIGH>; + spi-max-frequency = <1000000>; + }; + }; + + leds { + compatible = "gpio-leds"; + + led_power_amber: led_power { + label = "amber:power"; + gpios = <&led_gpio 1 GPIO_ACTIVE_HIGH>; + }; + + led_lan { + label = "blue:lan"; + gpios = <&led_gpio 2 GPIO_ACTIVE_HIGH>; + }; + + led_wlan_2g { + label = "blue:wlan2g"; + gpios = <&led_gpio 3 GPIO_ACTIVE_HIGH>; + }; + + led_wlan_5g { + label = "blue:wlan5g"; + gpios = <&led_gpio 4 GPIO_ACTIVE_HIGH>; + }; + }; +}; + +&edma { + status = "okay"; +}; + +&switch { + status = "okay"; + + switch_cpu_bmp = <0x1>; + switch_lan_bmp = <0x3e>; + switch_wan_bmp = <0x40>; + switch_mac_mode = <0x00>; + switch_mac_mode1 = <0xff>; + switch_mac_mode2 = <0x0f>; + bm_tick_mode = <0>; + tm_tick_mode = <0>; + + qcom,port_phyinfo { + port@5 { + port_id = <6>; + phy_address = <28>; + port_mac_sel = "QGMAC_PORT"; + }; + }; +}; + +&tlmm { + mdio_pins: mdio-pins { + mdc { + pins = "gpio68"; + function = "mdc"; + drive-strength = <8>; + bias-pull-up; + }; + + mdio { + pins = "gpio69"; + function = "mdio"; + drive-strength = <8>; + bias-pull-up; + }; + }; +}; + +&mdio { + status = "okay"; + + pinctrl-0 = <&mdio_pins>; + pinctrl-names = "default"; + reset-gpios = <&tlmm 44 GPIO_ACTIVE_LOW>; + + qca8081_28: ethernet-phy@28 { + reg = <28>; + }; +}; + +&dp6_syn { + status = "okay"; + phy-handle = <&qca8081_28>; + label = "lan"; + nvmem-cells = <&macaddr_ubootenv_ethaddr>; + nvmem-cell-names = "mac-address"; +}; + +&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"; + + partition-0-appsblenv { + compatible = "fixed-partitions"; + label = "0:appsblenv"; + read-only; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + compatible = "u-boot,env"; + label = "env-data"; + reg = <0x0 0x40000>; + + macaddr_ubootenv_ethaddr: ethaddr {}; + }; + }; + }; + }; +}; + +&blsp1_uart5 { + status = "okay"; +}; + +&wifi { + status = "okay"; + + qcom,ath11k-calibration-variant = "Netgear-WAX218"; +}; diff --git a/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8072-wax620.dts b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8072-wax620.dts new file mode 100644 index 000000000..0cd20cc1e --- /dev/null +++ b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8072-wax620.dts @@ -0,0 +1,200 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +/dts-v1/; + +#include "ipq8074.dtsi" +#include "ipq8074-hk-cpu.dtsi" +#include "ipq8074-ess.dtsi" +#include +#include + +/ { + model = "Netgear WAX620"; + compatible = "netgear,wax620", "qcom,ipq8074"; + + aliases { + serial0 = &blsp1_uart5; + ethernet0 = &dp6; + led-boot = &led_system_blue; + led-failsafe = &led_system_red; + led-running = &led_system_green; + led-upgrade = &led_system_blue; + }; + + chosen { + stdout-path = "serial0:115200n8"; + /* + * Netgear's U-Boot adds "ubi.mtd=rootfs root=mtd:ubi_rootfs" + * That fails to create a UBI block device, so add it here. + */ + bootargs-append = " root=/dev/ubiblock0_1"; + }; + + keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + gpios = <&tlmm 52 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + led_spi { + compatible = "spi-gpio"; + #address-cells = <1>; + #size-cells = <0>; + + sck-gpios = <&tlmm 18 GPIO_ACTIVE_HIGH>; + mosi-gpios = <&tlmm 19 GPIO_ACTIVE_HIGH>; + + led_gpio: led_gpio@0 { + compatible = "fairchild,74hc595"; + reg = <0>; + gpio-controller; + #gpio-cells = <2>; + registers-number = <1>; + enable-gpios = <&tlmm 20 GPIO_ACTIVE_HIGH>; + spi-max-frequency = <1000000>; + }; + }; + + leds { + compatible = "gpio-leds"; + + led_system_red: system-red { + label = "system:red"; + gpios = <&tlmm 54 GPIO_ACTIVE_HIGH>; + }; + + led_system_green: system-green { + label = "system:green"; + gpios = <&tlmm 55 GPIO_ACTIVE_HIGH>; + }; + + led_system_blue: system-blue { + label = "system:blue"; + gpios = <&tlmm 56 GPIO_ACTIVE_HIGH>; + }; + + led_lan_g { + label = "lan:green"; + gpios = <&led_gpio 0 GPIO_ACTIVE_HIGH>; + }; + + led_lan_o { + label = "lan:orange"; + gpios = <&led_gpio 1 GPIO_ACTIVE_HIGH>; + }; + + led_2g_b { + label = "wlan2g:blue"; + gpios = <&led_gpio 2 GPIO_ACTIVE_HIGH>; + }; + + led_2g_g { + label = "wlan2g:green"; + gpios = <&led_gpio 3 GPIO_ACTIVE_HIGH>; + }; + + led_5g_b { + label = "wlan5g:blue"; + gpios = <&led_gpio 4 GPIO_ACTIVE_HIGH>; + }; + + led_5g_g { + label = "wlan5g:green"; + gpios = <&led_gpio 5 GPIO_ACTIVE_HIGH>; + }; + }; +}; + +&edma { + status = "okay"; +}; + +&switch { + status = "okay"; + + switch_cpu_bmp = <0x01>; + switch_lan_bmp = <0x3e>; + switch_wan_bmp = <0x40>; + switch_mac_mode = <0x00>; + switch_mac_mode1 = <0xff>; + switch_mac_mode2 = <0x0f>; + bm_tick_mode = <0x00>; + tm_tick_mode = <0x00>; + + qcom,port_phyinfo { + port@5 { + port_id = <6>; + phy_address = <28>; + port_mac_sel = "QGMAC_PORT"; + }; + }; +}; + +&tlmm { + mdio_pins: mdio-pins { + mdc { + pins = "gpio68"; + function = "mdc"; + drive-strength = <8>; + bias-pull-up; + }; + + mdio { + pins = "gpio69"; + function = "mdio"; + drive-strength = <8>; + bias-pull-up; + }; + }; +}; + +&mdio { + status = "okay"; + + pinctrl-0 = <&mdio_pins>; + pinctrl-names = "default"; + reset-gpios = <&tlmm 44 GPIO_ACTIVE_LOW>; + + qca8081_28: ethernet-phy@28 { + reg = <28>; + }; +}; + +&dp6 { + status = "okay"; + phy-handle = <&qca8081_28>; + label = "lan"; +}; + +&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"; + }; + }; +}; + +&blsp1_uart5 { + status = "okay"; +}; + +&wifi { + status = "okay"; + + qcom,ath11k-calibration-variant = "Netgear-WAX620"; +}; diff --git a/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8072-wpq873.dts b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8072-wpq873.dts new file mode 100644 index 000000000..2de34af8e --- /dev/null +++ b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8072-wpq873.dts @@ -0,0 +1,486 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT +/* Copyright 2023 Nokia */ + +/dts-v1/; + +#include "ipq8074.dtsi" +#include "ipq8074-hk-cpu.dtsi" +#include "ipq8074-ess.dtsi" +#include +#include +#include + +/ { + model = "Compex WPQ873"; + compatible = "compex,wpq873", "qcom,ipq8074"; + + aliases { + serial0 = &blsp1_uart5; + led-boot = &led_power_blue; + led-failsafe = &led_power_red; + led-running = &led_system_green; + led-upgrade = &led_system_blue; + /* Aliases as required by u-boot to patch MAC addresses */ + ethernet0 = &dp6; + ethernet1 = &dp2; + ethernet2 = &dp3; + ethernet3 = &dp4; + label-mac-device = &dp6; + }; + + chosen { + stdout-path = "serial0:115200n8"; + bootargs-append = " root=/dev/ubiblock0_1"; + }; + + keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + gpios = <&tlmm 21 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + leds { + compatible = "gpio-leds"; + + led_power_red: power-red { + label = "red:power"; + gpios = <&tlmm 42 GPIO_ACTIVE_HIGH>; + color = ; + }; + + led_power_blue: power-blue { + label = "blue:power"; + gpios = <&tlmm 43 GPIO_ACTIVE_HIGH>; + color = ; + }; + + led_system_red: system-red { + label = "red:system"; + gpios = <&tlmm 28 GPIO_ACTIVE_HIGH>; + color = ; + }; + + led_system_green: system-green { + label = "green:system"; + gpios = <&tlmm 18 GPIO_ACTIVE_HIGH>; + color = ; + }; + + led_system_blue: system-blue { + label = "blue:system"; + gpios = <&tlmm 19 GPIO_ACTIVE_HIGH>; + color = ; + }; + }; +}; + +&tlmm { + mdio_pins: mdio-pins { + mdc { + pins = "gpio68"; + function = "mdc"; + drive-strength = <8>; + bias-pull-up; + }; + + mdio { + pins = "gpio69"; + function = "mdio"; + drive-strength = <8>; + bias-pull-up; + }; + }; + + i2c_pins: i2c-pins { + pins = "gpio0", "gpio2"; + function = "blsp5_i2c"; + drive-strength = <8>; + bias-disable; + }; +}; + +&blsp1_uart5 { + status = "okay"; +}; + +&blsp1_i2c6 { + status = "okay"; + + pinctrl-0 = <&i2c_pins>; + pinctrl-names = "default"; +}; + +&prng { + status = "okay"; +}; + +&cryptobam { + status = "okay"; +}; + +&crypto { + status = "okay"; +}; + +&qpic_bam { + status = "okay"; +}; + +&blsp1_spi1 { + status = "okay"; +}; + +&tlmm { + mdio_pins: mdio-pins { + mdc { + pins = "gpio68"; + function = "mdc"; + drive-strength = <8>; + bias-pull-up; + }; + + mdio { + pins = "gpio69"; + function = "mdio"; + drive-strength = <8>; + bias-pull-up; + }; + }; + + button_pins: button_pins { + reset_button { + pins = "gpio66"; + function = "gpio"; + drive-strength = <8>; + bias-pull-up; + }; + }; +}; + +&blsp1_spi1 { + status = "okay"; + + flash@0 { + #address-cells = <1>; + #size-cells = <1>; + reg = <0>; + compatible = "jedec,spi-nor"; + spi-max-frequency = <50000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "0:sbl1"; + reg = <0x0 0x50000>; + read-only; + }; + + partition@50000 { + label = "0:mibib"; + reg = <0x50000 0x10000>; + read-only; + }; + + partition@60000 { + label = "0:bootconfig"; + reg = <0x60000 0x20000>; + read-only; + }; + + partition@80000 { + label = "0:bootconfig1"; + reg = <0x80000 0x20000>; + read-only; + }; + + partition@a0000 { + label = "0:qsee"; + reg = <0xa0000 0x180000>; + read-only; + }; + + partition@220000 { + label = "0:qsee_1"; + reg = <0x220000 0x180000>; + read-only; + }; + + partition@3a0000 { + label = "0:devcfg"; + reg = <0x3a0000 0x10000>; + read-only; + }; + + partition@3b0000 { + label = "0:devcfg_1"; + reg = <0x3b0000 0x10000>; + read-only; + }; + + partition@3c0000 { + label = "0:apdp"; + reg = <0x3c0000 0x10000>; + read-only; + }; + + partition@3d0000 { + label = "0:apdp_1"; + reg = <0x3d0000 0x10000>; + read-only; + }; + + partition@3e0000 { + label = "0:rpm"; + reg = <0x3e0000 0x40000>; + read-only; + }; + + partition@420000 { + label = "0:rpm_1"; + reg = <0x420000 0x40000>; + read-only; + }; + + partition@460000 { + label = "0:cdt"; + reg = <0x460000 0x10000>; + read-only; + }; + + partition@470000 { + label = "0:cdt_1"; + reg = <0x470000 0x10000>; + read-only; + }; + + partition@480000 { + label = "0:appsblenv"; + reg = <0x480000 0x10000>; + }; + + partition@490000 { + label = "0:appsbl"; + reg = <0x490000 0xa0000>; + read-only; + }; + + partition@550000 { + label = "0:appsbl_1"; + reg = <0x530000 0xa0000>; + read-only; + }; + + partition@610000 { + label = "0:art"; + reg = <0x5d0000 0x40000>; + read-only; + }; + + partition@650000 { + label = "0:ethphyfw"; + reg = <0x610000 0x80000>; + read-only; + }; + }; + }; +}; + +&qpic_nand { + status = "okay"; + + nand@0 { + reg = <0>; + nand-ecc-strength = <8>; + nand-ecc-step-size = <512>; + nand-bus-width = <8>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "rootfs"; + reg = <0x0000000 0x3400000>; + }; + + partition@3400000 { + label = "0:wififw"; + reg = <0x3400000 0x800000>; + read-only; + }; + + partition@3c00000 { + label = "rootfs_1"; + reg = <0x3c00000 0x3400000>; + }; + + partition@7000000 { + label = "0:wififw_1"; + reg = <0x7000000 0x800000>; + read-only; + }; + }; + }; +}; + +&qusb_phy_0 { + status = "okay"; +}; + +&qusb_phy_1 { + status = "okay"; +}; + +&ssphy_0 { + status = "okay"; +}; + +&ssphy_1 { + status = "okay"; +}; + +&usb_0 { + status = "okay"; +}; + +&usb_1 { + status = "okay"; +}; + + +&mdio { + status = "okay"; + pinctrl-0 = <&mdio_pins>; + pinctrl-names = "default"; + reset-gpios = <&tlmm 37 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>; + }; + + qca8081: ethernet-phy@28 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <28>; + reset-gpios = <&tlmm 44 GPIO_ACTIVE_LOW>; + }; +}; + +&switch { + status = "okay"; + + switch_cpu_bmp = <0x1>; /* cpu port bitmap */ + switch_lan_bmp = <0x3e>; /* lan port bitmap */ + switch_wan_bmp = <0x40>; /* wan port bitmap */ + switch_mac_mode = <0x0>; /* mac mode for uniphy instance0*/ + switch_mac_mode1 = <0x0f>; /* mac mode for uniphy instance1*/ + switch_mac_mode2 = <0x0f>; /* mac mode for uniphy instance2*/ + bm_tick_mode = <0>; /* bm tick mode */ + tm_tick_mode = <0>; /* tm tick mode */ + + qcom,port_phyinfo { + port@2 { + port_id = <2>; + phy_address = <1>; + }; + port@3 { + port_id = <3>; + phy_address = <2>; + }; + port@4 { + port_id = <4>; + phy_address = <3>; + }; + port@5 { + port_id = <6>; + phy_address = <28>; + port_mac_sel = "QGMAC_PORT"; + }; + }; +}; + +&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"; +}; + +&dp6 { + status = "okay"; + phy-handle = <&qca8081>; + label = "wan"; +}; + +&pcie_qmp0 { + status = "okay"; +}; + +&pcie0 { + status = "okay"; + + perst-gpio = <&tlmm 58 GPIO_ACTIVE_LOW>; + + bridge@0,0 { + reg = <0x00020000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + ranges; + }; +}; + +&pcie_qmp1 { + status = "okay"; +}; + +&pcie1 { + status = "okay"; + + perst-gpio = <&tlmm 62 GPIO_ACTIVE_HIGH>; + + bridge@1,0 { + reg = <0x00010000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + ranges; + }; +}; + +&wifi { + status = "okay"; + + qcom,ath11k-calibration-variant = "Compex-WPQ873"; +}; diff --git a/target/linux/ipq807x/files-5.15/arch/arm64/boot/dts/qcom/ipq8074-512m.dtsi b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8074-512m.dtsi similarity index 100% rename from target/linux/ipq807x/files-5.15/arch/arm64/boot/dts/qcom/ipq8074-512m.dtsi rename to target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8074-512m.dtsi diff --git a/target/linux/ipq807x/files-5.15/arch/arm64/boot/dts/qcom/ipq8074-ac-cpu.dtsi b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8074-ac-cpu.dtsi similarity index 70% rename from target/linux/ipq807x/files-5.15/arch/arm64/boot/dts/qcom/ipq8074-ac-cpu.dtsi rename to target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8074-ac-cpu.dtsi index 4207ece81..6cf8bad5b 100644 --- a/target/linux/ipq807x/files-5.15/arch/arm64/boot/dts/qcom/ipq8074-ac-cpu.dtsi +++ b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8074-ac-cpu.dtsi @@ -5,46 +5,24 @@ &CPU0 { cpu-supply = <&apc_vreg>; - operating-points-v2 = <&cpu_opp_table>; voltage-tolerance = <1>; }; &CPU1 { cpu-supply = <&apc_vreg>; - operating-points-v2 = <&cpu_opp_table>; voltage-tolerance = <1>; }; &CPU2 { cpu-supply = <&apc_vreg>; - operating-points-v2 = <&cpu_opp_table>; voltage-tolerance = <1>; }; &CPU3 { cpu-supply = <&apc_vreg>; - operating-points-v2 = <&cpu_opp_table>; voltage-tolerance = <1>; }; -&cpus { - cpu_opp_table: cpu_opp_table { - compatible = "operating-points-v2"; - opp-shared; - - opp-1017600000 { - opp-hz = /bits/ 64 <1017600000>; - opp-microvolt = <1>; - clock-latency-ns = <200000>; - }; - opp-1382400000 { - opp-hz = /bits/ 64 <1382400000>; - opp-microvolt = <2>; - clock-latency-ns = <200000>; - }; - }; -}; - &cpu0_thermal { trips { cpu0_passive: cpu-passive { @@ -52,12 +30,6 @@ hysteresis = <2000>; type = "passive"; }; - - cpu0_crit: cpu_crit { - temperature = <110000>; - hysteresis = <1000>; - type = "critical"; - }; }; cooling-maps { @@ -78,12 +50,6 @@ hysteresis = <2000>; type = "passive"; }; - - cpu1_crit: cpu_crit { - temperature = <110000>; - hysteresis = <1000>; - type = "critical"; - }; }; cooling-maps { @@ -104,12 +70,6 @@ hysteresis = <2000>; type = "passive"; }; - - cpu2_crit: cpu_crit { - temperature = <110000>; - hysteresis = <1000>; - type = "critical"; - }; }; cooling-maps { @@ -130,12 +90,6 @@ hysteresis = <2000>; type = "passive"; }; - - cpu3_crit: cpu_crit { - temperature = <110000>; - hysteresis = <1000>; - type = "critical"; - }; }; cooling-maps { @@ -156,12 +110,6 @@ hysteresis = <2000>; type = "passive"; }; - - cluster_crit: cluster_crit { - temperature = <110000>; - hysteresis = <1000>; - type = "critical"; - }; }; cooling-maps { diff --git a/target/linux/ipq807x/files-5.15/arch/arm64/boot/dts/qcom/ipq8074-cpr-regulator.dtsi b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8074-cpr-regulator.dtsi similarity index 99% rename from target/linux/ipq807x/files-5.15/arch/arm64/boot/dts/qcom/ipq8074-cpr-regulator.dtsi rename to target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8074-cpr-regulator.dtsi index e692cc942..e351a2e75 100644 --- a/target/linux/ipq807x/files-5.15/arch/arm64/boot/dts/qcom/ipq8074-cpr-regulator.dtsi +++ b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8074-cpr-regulator.dtsi @@ -1,5 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only +#include "pmp8074.dtsi" + &soc { apc_apm: apm@b111000 { compatible = "qcom,ipq807x-apm"; diff --git a/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8074-ess.dtsi b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8074-ess.dtsi new file mode 100644 index 000000000..129266c50 --- /dev/null +++ b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8074-ess.dtsi @@ -0,0 +1,531 @@ +// 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-ipq807x"; + reg = <0x3a000000 0x1000000>; + switch_access_mode = "local bus"; + switch_cpu_bmp = <0x1>; /* cpu port bitmap */ + switch_inner_bmp = <0x80>; /*inner port bitmap*/ + 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_UNIPHY2_AHB_CLK>, + <&gcc GCC_UNIPHY2_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_PORT6_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_NSS_PPE_BTQ_CLK>, + <&gcc GCC_MDIO_AHB_CLK>, + <&gcc GCC_NSS_NOC_CLK>, + <&gcc GCC_NSSNOC_SNOC_CLK>, + <&gcc GCC_MEM_NOC_NSS_AXI_CLK>, + <&gcc GCC_NSS_CRYPTO_CLK>, + <&gcc GCC_NSS_IMEM_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_NSS_PORT6_RX_CLK>, + <&gcc GCC_NSS_PORT6_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 GCC_UNIPHY2_PORT6_RX_CLK>, + <&gcc GCC_UNIPHY2_PORT6_TX_CLK>, + <&gcc NSS_PORT5_RX_CLK_SRC>, + <&gcc NSS_PORT5_TX_CLK_SRC>; + clock-names = "cmn_ahb_clk", "cmn_sys_clk", + "uniphy0_ahb_clk", "uniphy0_sys_clk", + "uniphy1_ahb_clk", "uniphy1_sys_clk", + "uniphy2_ahb_clk", "uniphy2_sys_clk", + "port1_mac_clk", "port2_mac_clk", + "port3_mac_clk", "port4_mac_clk", + "port5_mac_clk", "port6_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", "nss_ppe_btq_clk", + "gcc_mdio_ahb_clk", "gcc_nss_noc_clk", + "gcc_nssnoc_snoc_clk", + "gcc_mem_noc_nss_axi_clk", + "gcc_nss_crypto_clk", + "gcc_nss_imem_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", + "nss_port6_rx_clk", "nss_port6_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", + "uniphy2_port6_rx_clk", + "uniphy2_port6_tx_clk", + "nss_port5_rx_clk_src", + "nss_port5_tx_clk_src"; + 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_UNIPHY2_SOFT_RESET>, + <&gcc GCC_UNIPHY2_XPCS_RESET>, + <&gcc GCC_NSSPORT1_RESET>, + <&gcc GCC_NSSPORT2_RESET>, + <&gcc GCC_NSSPORT3_RESET>, + <&gcc GCC_NSSPORT4_RESET>, + <&gcc GCC_NSSPORT5_RESET>, + <&gcc GCC_NSSPORT6_RESET>; + reset-names = "ppe_rst", "uniphy0_soft_rst", + "uniphy0_xpcs_rst", "uniphy1_soft_rst", + "uniphy1_xpcs_rst", "uniphy2_soft_rst", + "uniphy2_xpcs_rst", "nss_port1_rst", + "nss_port2_rst", "nss_port3_rst", + "nss_port4_rst", "nss_port5_rst", + "nss_port6_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 = <0x3ab00000 0x76900>; + reg-names = "edma-reg-base"; + qcom,txdesc-ring-start = <23>; + qcom,txdesc-rings = <1>; + qcom,txcmpl-ring-start = <7>; + 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 = <0x3a001000 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 = <0x3a001200 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 = <0x3a001400 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 = <0x3a001600 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 = <0x3a001800 0x200>; + qcom,mactype = <0>; + local-mac-address = [000000000000]; + phy-mode = "sgmii"; + status = "disabled"; + }; + + dp6: dp6 { + device_type = "network"; + compatible = "qcom,nss-dp"; + qcom,id = <6>; + reg = <0x3a001a00 0x200>; + qcom,mactype = <0>; + local-mac-address = [000000000000]; + phy-mode = "sgmii"; + status = "disabled"; + }; + + dp5_syn: dp5-syn { + device_type = "network"; + compatible = "qcom,nss-dp"; + qcom,id = <5>; + reg = <0x3a003000 0x3fff>; + qcom,mactype = <1>; + local-mac-address = [000000000000]; + phy-mode = "sgmii"; + status = "disabled"; + }; + + dp6_syn: dp6-syn { + device_type = "network"; + compatible = "qcom,nss-dp"; + qcom,id = <6>; + reg = <0x3a007000 0x3fff>; + qcom,mactype = <1>; + local-mac-address = [000000000000]; + phy-mode = "sgmii"; + status = "disabled"; + }; +}; diff --git a/target/linux/ipq807x/files-5.15/arch/arm64/boot/dts/qcom/ipq8074-hk-cpu.dtsi b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8074-hk-cpu.dtsi similarity index 74% rename from target/linux/ipq807x/files-5.15/arch/arm64/boot/dts/qcom/ipq8074-hk-cpu.dtsi rename to target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8074-hk-cpu.dtsi index 861460c93..b7d746c44 100644 --- a/target/linux/ipq807x/files-5.15/arch/arm64/boot/dts/qcom/ipq8074-hk-cpu.dtsi +++ b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8074-hk-cpu.dtsi @@ -5,66 +5,24 @@ &CPU0 { cpu-supply = <&apc_vreg>; - operating-points-v2 = <&cpu_opp_table>; voltage-tolerance = <1>; }; &CPU1 { cpu-supply = <&apc_vreg>; - operating-points-v2 = <&cpu_opp_table>; voltage-tolerance = <1>; }; &CPU2 { cpu-supply = <&apc_vreg>; - operating-points-v2 = <&cpu_opp_table>; voltage-tolerance = <1>; }; &CPU3 { cpu-supply = <&apc_vreg>; - operating-points-v2 = <&cpu_opp_table>; voltage-tolerance = <1>; }; -&cpus { - cpu_opp_table: cpu_opp_table { - compatible = "operating-points-v2"; - opp-shared; - - opp-1017600000 { - opp-hz = /bits/ 64 <1017600000>; - opp-microvolt = <1>; - clock-latency-ns = <200000>; - }; - opp-1382400000 { - opp-hz = /bits/ 64 <1382400000>; - opp-microvolt = <2>; - clock-latency-ns = <200000>; - }; - opp-1651200000 { - opp-hz = /bits/ 64 <1651200000>; - opp-microvolt = <3>; - clock-latency-ns = <200000>; - }; - opp-1843200000 { - opp-hz = /bits/ 64 <1843200000>; - opp-microvolt = <4>; - clock-latency-ns = <200000>; - }; - opp-1920000000 { - opp-hz = /bits/ 64 <1920000000>; - opp-microvolt = <5>; - clock-latency-ns = <200000>; - }; - opp-2208000000 { - opp-hz = /bits/ 64 <2208000000>; - opp-microvolt = <6>; - clock-latency-ns = <200000>; - }; - }; -}; - &cpu0_thermal { trips { cpu0_passive_low: cpu-passive-low { @@ -78,12 +36,6 @@ hysteresis = <2000>; type = "passive"; }; - - cpu0_crit: cpu_crit { - temperature = <110000>; - hysteresis = <1000>; - type = "critical"; - }; }; cooling-maps { @@ -117,12 +69,6 @@ hysteresis = <2000>; type = "passive"; }; - - cpu1_crit: cpu_crit { - temperature = <110000>; - hysteresis = <1000>; - type = "critical"; - }; }; cooling-maps { @@ -156,12 +102,6 @@ hysteresis = <2000>; type = "passive"; }; - - cpu2_crit: cpu_crit { - temperature = <110000>; - hysteresis = <1000>; - type = "critical"; - }; }; cooling-maps { @@ -195,12 +135,6 @@ hysteresis = <2000>; type = "passive"; }; - - cpu3_crit: cpu_crit { - temperature = <110000>; - hysteresis = <1000>; - type = "critical"; - }; }; cooling-maps { @@ -234,12 +168,6 @@ hysteresis = <2000>; type = "passive"; }; - - cluster_crit: cluster_crit { - temperature = <110000>; - hysteresis = <1000>; - type = "critical"; - }; }; cooling-maps { diff --git a/target/linux/ipq807x/files-5.15/arch/arm64/boot/dts/qcom/ipq8074-nbg7815.dts b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8074-nbg7815.dts similarity index 80% rename from target/linux/ipq807x/files-5.15/arch/arm64/boot/dts/qcom/ipq8074-nbg7815.dts rename to target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8074-nbg7815.dts index 7d5272a5e..2924ac3a9 100644 --- a/target/linux/ipq807x/files-5.15/arch/arm64/boot/dts/qcom/ipq8074-nbg7815.dts +++ b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8074-nbg7815.dts @@ -13,7 +13,6 @@ #include #include - / { model = "Zyxel NBG7815"; compatible = "zyxel,nbg7815", "qcom,ipq8074"; @@ -59,7 +58,6 @@ }; }; - &blsp1_uart3 { status = "okay"; }; @@ -84,28 +82,16 @@ status = "okay"; }; - &blsp1_spi1 { pinctrl-0 = <&spi_0_pins>; pinctrl-names = "default"; cs-gpios = <0>; status = "okay"; - /* - * Bootloader will find the NAND DT node by the compatible and - * then "fixup" it by adding the partitions from the SMEM table - * using the legacy bindings thus making it impossible for us - * to change the partition table or utilize NVMEM for calibration. - * So add a dummy partitions node that bootloader will populate - * and set it as disabled so the kernel ignores it instead of - * printing warnings due to the broken way bootloader adds the - * partitions. - */ partitions { status = "disabled"; }; - flash@0 { #address-cells = <1>; #size-cells = <1>; @@ -220,6 +206,7 @@ reg = <0x600000 0x10000>; macaddr_lan: ethaddr { + #nvmem-cell-cells = <1>; }; }; @@ -345,55 +332,52 @@ status = "okay"; }; -&soc { - dp1: dp1 { - status = "okay"; - phy-handle = <&qca8075_1>; - label = "eth0"; - nvmem-cells = <&macaddr_lan>; - nvmem-cell-names = "mac-address-ascii"; - }; +&dp1 { + status = "okay"; + phy-handle = <&qca8075_1>; + label = "lan1"; + nvmem-cells = <&macaddr_lan 0>; + nvmem-cell-names = "mac-address"; +}; - dp2: dp2 { - status = "okay"; - phy-handle = <&qca8075_2>; - label = "eth1"; - nvmem-cells = <&macaddr_lan>; - nvmem-cell-names = "mac-address-ascii"; - }; +&dp2 { + status = "okay"; + phy-handle = <&qca8075_2>; + label = "lan2"; + nvmem-cells = <&macaddr_lan 0>; + nvmem-cell-names = "mac-address"; +}; - dp3: dp3 { - status = "okay"; - phy-handle = <&qca8075_3>; - label = "eth2"; - nvmem-cells = <&macaddr_lan>; - nvmem-cell-names = "mac-address-ascii"; - }; +&dp3 { + status = "okay"; + phy-handle = <&qca8075_3>; + label = "lan3"; + nvmem-cells = <&macaddr_lan 0>; + nvmem-cell-names = "mac-address"; +}; - dp4: dp4 { - status = "okay"; - phy-handle = <&qca8075_4>; - label = "eth3"; - nvmem-cells = <&macaddr_lan>; - nvmem-cell-names = "mac-address-ascii"; - }; +&dp4 { + status = "okay"; + phy-handle = <&qca8075_4>; + label = "lan4"; + nvmem-cells = <&macaddr_lan 0>; + nvmem-cell-names = "mac-address"; +}; - dp5: dp5 { - status = "okay"; - phy-handle = <&qca8081>; - label = "eth4"; - nvmem-cells = <&macaddr_lan>; - nvmem-cell-names = "mac-address-ascii"; - mac-address-increment = <1>; - }; +&dp5 { + status = "okay"; + phy-handle = <&qca8081>; + label = "wan"; + nvmem-cells = <&macaddr_lan 1>; + nvmem-cell-names = "mac-address"; +}; - dp6: dp6_syn { - status = "okay"; - phy-handle = <&aqr113c>; - label = "eth5"; - nvmem-cells = <&macaddr_lan>; - nvmem-cell-names = "mac-address-ascii"; - }; +&dp6_syn { + status = "okay"; + phy-handle = <&aqr113c>; + label = "10g"; + nvmem-cells = <&macaddr_lan 0>; + nvmem-cell-names = "mac-address"; }; &blsp1_i2c2 { @@ -413,6 +397,7 @@ /delete-property/ mmc-hs400-1_8v; mmc-hs200-1_8v; mmc-ddr-1_8v; + vqmmc-supply = <&l11>; }; &ssphy_0 { diff --git a/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8074-rax120v2.dts b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8074-rax120v2.dts new file mode 100644 index 000000000..4034c326f --- /dev/null +++ b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8074-rax120v2.dts @@ -0,0 +1,552 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +/dts-v1/; + +#include "ipq8074.dtsi" +#include "ipq8074-ess.dtsi" +#include "ipq8074-hk-cpu.dtsi" +#include +#include +#include + +/ { + model = "Netgear RAX120v2"; + compatible = "netgear,rax120v2", "qcom,ipq8074"; + + aliases { + serial0 = &blsp1_uart5; + + led-running = &led_system_white; + led-upgrade = &led_system_white; + led-internet = &led_wan_white; + label-mac-device = &dp1; + }; + + chosen { + stdout-path = "serial0:115200n8"; + bootargs-append = " ubi.mtd=rootfs root=/dev/ubiblock0_0"; + }; + + keys { + compatible = "gpio-keys"; + + rfkill { + label = "rfkill"; + gpios = <&tlmm 25 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + + wps { + label = "wps"; + gpios = <&tlmm 57 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + + reset { + label = "reset"; + gpios = <&tlmm 54 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + led_spi { + compatible = "spi-gpio"; + #address-cells = <1>; + #size-cells = <0>; + + sck-gpios = <&tlmm 18 GPIO_ACTIVE_HIGH>; + mosi-gpios = <&tlmm 19 GPIO_ACTIVE_HIGH>; + + led_gpio: led_gpio@0 { + compatible = "fairchild,74hc595"; + reg = <0>; + gpio-controller; + #gpio-cells = <2>; + registers-number = <2>; + enable-gpios = <&tlmm 20 GPIO_ACTIVE_HIGH>; + spi-max-frequency = <1000000>; + }; + }; + + leds { + compatible = "gpio-leds"; + + led_system_white: system-white { + label = "white:system"; + gpios = <&led_gpio 0 GPIO_ACTIVE_LOW>; + color = ; + }; + + led_24g_white { + label = "white:24g"; + gpios = <&led_gpio 1 GPIO_ACTIVE_LOW>; + color = ; + linux,default-trigger = "phy1radio"; + }; + + led_5g_white { + label = "white:5g"; + gpios = <&led_gpio 2 GPIO_ACTIVE_LOW>; + color = ; + linux,default-trigger = "phy0radio"; + }; + + led_usb1_white { + label = "white:usb1"; + gpios = <&led_gpio 3 GPIO_ACTIVE_LOW>; + color = ; + }; + + led_usb2_white { + label = "white:usb2"; + gpios = <&led_gpio 4 GPIO_ACTIVE_LOW>; + color = ; + }; + + led_wan_white: wan-white { + label = "white:wan"; + gpios = <&led_gpio 5 GPIO_ACTIVE_LOW>; + color = ; + }; + + led_aqr_green { + label = "green:aqr"; + gpios = <&led_gpio 6 GPIO_ACTIVE_LOW>; + color = ; + }; + + led_aqr_red { + label = "red:aqr"; + gpios = <&led_gpio 10 GPIO_ACTIVE_LOW>; + color = ; + }; + + led_aqr_white { + label = "white:aqr"; + gpios = <&led_gpio 11 GPIO_ACTIVE_LOW>; + color = ; + }; + + led_wps_white { + label = "white:wps"; + gpios = <&tlmm 40 GPIO_ACTIVE_HIGH>; + color = ; + }; + }; +}; + +&tlmm { + mdio_pins: mdio-pins { + mdc { + pins = "gpio68"; + function = "mdc"; + drive-strength = <8>; + bias-pull-up; + }; + + mdio { + pins = "gpio69"; + function = "mdio"; + drive-strength = <8>; + bias-pull-up; + }; + }; +}; + +&mdio { + status = "okay"; + + pinctrl-0 = <&mdio_pins>; + pinctrl-names = "default"; + reset-gpios = <&tlmm 37 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>; + }; + + aqr111b0: ethernet-phy@7 { + compatible ="ethernet-phy-ieee802.3-c45"; + reg = <7>; + reset-gpios = <&tlmm 59 GPIO_ACTIVE_LOW>; + }; +}; + +&switch { + status = "okay"; + + switch_lan_bmp = <0x3e>; /* lan port bitmap */ + switch_wan_bmp = <0x40>; /* wan port bitmap */ + switch_mac_mode = <0x0>; /* mac mode for uniphy instance0*/ + switch_mac_mode1 = <0xff>; /* mac mode for uniphy instance1*/ + switch_mac_mode2 = <0xd>; /* mac mode for uniphy instance2*/ + bm_tick_mode = <0>; /* bm tick mode */ + tm_tick_mode = <0>; /* tm tick mode */ + + qcom,port_phyinfo { + port@1 { + port_id = <1>; + phy_address = <0>; + }; + port@2 { + port_id = <2>; + phy_address = <1>; + }; + port@3 { + port_id = <3>; + phy_address = <2>; + }; + port@4 { + port_id = <4>; + phy_address = <3>; + }; + port@5 { + port_id = <5>; + phy_address = <4>; + }; + port@6 { + port_id = <6>; + phy_address = <7>; + compatible = "ethernet-phy-ieee802.3-c45"; + ethernet-phy-ieee802.3-c45; + }; + }; +}; + +&edma { + status = "okay"; +}; + +&dp1 { + status = "okay"; + phy-handle = <&qca8075_0>; + label = "lan4"; + nvmem-cells = <&macaddr_dp1>; + nvmem-cell-names = "mac-address"; +}; + +&dp2 { + status = "okay"; + phy-handle = <&qca8075_1>; + label = "lan3"; + nvmem-cells = <&macaddr_dp2>; + nvmem-cell-names = "mac-address"; +}; + +&dp3 { + status = "okay"; + phy-handle = <&qca8075_2>; + label = "lan2"; + nvmem-cells = <&macaddr_dp3>; + nvmem-cell-names = "mac-address"; +}; + +&dp4 { + status = "okay"; + phy-handle = <&qca8075_3>; + label = "lan1"; + nvmem-cells = <&macaddr_dp4>; + nvmem-cell-names = "mac-address"; +}; + +&dp5 { + status = "okay"; + phy-handle = <&qca8075_4>; + label = "wan"; + nvmem-cells = <&macaddr_dp5>; + nvmem-cell-names = "mac-address"; +}; + +&dp6_syn { + status = "okay"; + phy-handle = <&aqr111b0>; + label = "lan5"; + nvmem-cells = <&macaddr_dp6_syn>; + nvmem-cell-names = "mac-address"; +}; + +&blsp1_uart5 { + status = "okay"; +}; + +&blsp1_i2c2 { + status = "okay"; + + g761@3e { + compatible = "gmt,g763"; + reg = <0x3e>; + clocks =<&sleep_clk>; + fan_gear_mode = <0>; + fan_start = <1>; + pwm_polarity = <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 = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "0:sbl1"; + reg = <0x00 0x100000>; + read-only; + }; + + partition@100000 { + label = "0:mibib"; + reg = <0x100000 0x100000>; + read-only; + }; + + partition@200000 { + label = "0:bootconfig"; + reg = <0x200000 0x80000>; + read-only; + }; + + partition@280000 { + label = "0:bootconfig_1"; + reg = <0x280000 0x80000>; + read-only; + }; + + partition@300000 { + label = "0:qsee"; + reg = <0x300000 0x300000>; + read-only; + }; + + partition@600000 { + label = "0:qsee_1"; + reg = <0x600000 0x300000>; + read-only; + }; + + partition@900000 { + label = "0:devcfg"; + reg = <0x900000 0x80000>; + read-only; + }; + + partition@980000 { + label = "0:devcfg_1"; + reg = <0x980000 0x80000>; + read-only; + }; + + partition@a00000 { + label = "0:apdp"; + reg = <0xa00000 0x80000>; + read-only; + }; + + partition@a80000 { + label = "0:apdp_1"; + reg = <0xa80000 0x80000>; + read-only; + }; + + partition@b00000 { + label = "0:rpm"; + reg = <0xb00000 0x80000>; + read-only; + }; + + partition@b80000 { + label = "0:rpm_1"; + reg = <0xb80000 0x80000>; + read-only; + }; + + partition@c00000 { + label = "0:cdt"; + reg = <0xc00000 0x80000>; + read-only; + }; + + partition@c80000 { + label = "0:cdt_1"; + reg = <0xc80000 0x80000>; + read-only; + }; + + partition@d00000 { + label = "0:appsblenv"; + reg = <0xd00000 0x80000>; + }; + + partition@d80000 { + label = "0:appsbl"; + reg = <0xd80000 0x100000>; + read-only; + }; + + partition@e80000 { + label = "0:appsbl_1"; + reg = <0xe80000 0x100000>; + read-only; + }; + + partition@f80000 { + label = "0:art"; + reg = <0xf80000 0x80000>; + read-only; + }; + + partition@1000000 { + label = "0:art.bak"; + reg = <0x1000000 0x0080000>; + read-only; + }; + + partition@1080000 { + label = "config"; + reg = <0x1080000 0x0100000>; + read-only; + }; + + partition@1180000 { + label = "boarddata1"; + reg = <0x1180000 0x0100000>; + read-only; + + compatible = "nvmem-cells"; + #address-cells = <1>; + #size-cells = <1>; + + macaddr_dp1: macaddr@0 { + reg = <0x0 0x6>; + }; + + macaddr_dp2: macaddr@1 { + reg = <0x6 0x6>; + }; + + macaddr_dp3: macaddr@2 { + reg = <0xc 0x6>; + }; + + macaddr_dp4: macaddr@3 { + reg = <0x12 0x6>; + }; + + macaddr_dp5: macaddr@4 { + reg = <0x18 0x6>; + }; + + macaddr_dp6_syn: macaddr@5 { + reg = <0x1e 0x6>; + }; + }; + + partition@1280000 { + label = "boarddata2"; + reg = <0x1280000 0x0100000>; + read-only; + }; + + partition@1380000 { + label = "pot"; + reg = <0x1380000 0x0100000>; + read-only; + }; + + partition@1480000 { + label = "dnidata"; + reg = <0x1480000 0x0500000>; + read-only; + }; + + partition@1980000 { + label = "kernel"; + reg = <0x1980000 0x1d00000>; + }; + + partition@7e00000 { + label = "ethphyfw"; + reg = <0x7e00000 0x80000>; + }; + + partition@e8800000 { + label = "rootfs"; + reg = <0xe880000 0x11780000>; + }; + }; + }; +}; + +&qusb_phy_0 { + status = "okay"; +}; + +&qusb_phy_1 { + status = "okay"; +}; + +&ssphy_0 { + status = "okay"; +}; + +&ssphy_1 { + status = "okay"; +}; + +&usb_0 { + status = "okay"; +}; + +&usb_1 { + status = "okay"; +}; + +&wifi{ + status = "okay"; + + qcom,ath11k-calibration-variant = "Netgear-RAX120v2"; +}; + +&cryptobam { + status = "okay"; +}; + +&crypto { + status = "okay"; +}; + +&prng { + status = "okay"; +}; diff --git a/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8074-wax630.dts b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8074-wax630.dts new file mode 100644 index 000000000..5e7b32801 --- /dev/null +++ b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8074-wax630.dts @@ -0,0 +1,252 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +/dts-v1/; + +#include "ipq8074.dtsi" +#include "ipq8074-hk-cpu.dtsi" +#include "ipq8074-ess.dtsi" +#include +#include +#include + +/ { + model = "Netgear WAX630"; + compatible = "netgear,wax630", "qcom,ipq8074"; + + aliases { + serial0 = &blsp1_uart5; + + ethernet0 = &dp6_syn; + ethernet1 = &dp4; + label-mac-device = &dp6_syn; + + led-boot = &led_system_blue; + led-failsafe = &led_system_red; + led-running = &led_system_green; + led-upgrade = &led_system_blue; + }; + + chosen { + stdout-path = "serial0:115200n8"; + bootargs-append = " root=/dev/ubiblock0_1"; + }; + + keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + gpios = <&tlmm 54 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + led-spi { + compatible = "spi-gpio"; + #address-cells = <1>; + #size-cells = <0>; + + sck-gpios = <&tlmm 18 GPIO_ACTIVE_HIGH>; + mosi-gpios = <&tlmm 19 GPIO_ACTIVE_HIGH>; + + led_gpio: led-gpio@0 { + compatible = "fairchild,74hc595"; + reg = <0>; + gpio-controller; + #gpio-cells = <2>; + registers-number = <1>; + enable-gpios = <&tlmm 20 GPIO_ACTIVE_HIGH>; + spi-max-frequency = <1000000>; + }; + }; + + leds { + compatible = "gpio-leds"; + + led_system_red: system-red { + label = "system:red"; + gpios = <&tlmm 22 GPIO_ACTIVE_LOW>; + default-state = "off"; + }; + + led_system_green: system-green { + label = "system:green"; + gpios = <&tlmm 38 GPIO_ACTIVE_LOW>; + default-state = "off"; + }; + + led_system_blue: system-blue { + label = "system:blue"; + gpios = <&tlmm 21 GPIO_ACTIVE_LOW>; + default-state = "off"; + }; + + lan1-green { + label = "lan1:green"; + gpios = <&tlmm 26 GPIO_ACTIVE_LOW>; + default-state = "off"; + }; + + lan1-orange { + label = "lan1:orange"; + gpios = <&tlmm 27 GPIO_ACTIVE_LOW>; + default-state = "off"; + }; + + lan2-green { + label = "lan2:green"; + gpios = <&tlmm 57 GPIO_ACTIVE_LOW>; + default-state = "off"; + }; + + lan2-orange { + label = "lan2:orange"; + gpios = <&tlmm 60 GPIO_ACTIVE_LOW>; + default-state = "off"; + }; + + 2g-blue { + label = "wlan2g:blue"; + gpios = <&tlmm 29 GPIO_ACTIVE_LOW>; + default-state = "off"; + }; + + 2g-green { + label = "wlan2g:green"; + gpios = <&tlmm 30 GPIO_ACTIVE_LOW>; + default-state = "off"; + }; + + 5g-low-blue { + label = "wlan5g_low:blue"; + gpios = <&tlmm 33 GPIO_ACTIVE_LOW>; + default-state = "off"; + }; + + 5g-low-green { + label = "wlan5g_low:green"; + gpios = <&tlmm 34 GPIO_ACTIVE_LOW>; + default-state = "off"; + }; + + 5g-high-blue { + label = "wlan5g_high:blue"; + gpios = <&tlmm 31 GPIO_ACTIVE_LOW>; + default-state = "off"; + }; + + 5g-high-green { + label = "wlan5g_high:green"; + gpios = <&tlmm 32 GPIO_ACTIVE_LOW>; + default-state = "off"; + }; + }; +}; + +&edma { + status = "okay"; +}; + +&switch { + status = "okay"; + + switch_cpu_bmp = <0x01>; + switch_lan_bmp = <0x3e>; + switch_wan_bmp = <0x40>; + switch_mac_mode = <0x00>; + switch_mac_mode1 = <0xff>; + switch_mac_mode2 = <0x0d>; + bm_tick_mode = <0x00>; + tm_tick_mode = <0x00>; + + qcom,port_phyinfo { + port@3 { + port_id = <4>; + phy_address = <3>; + }; + + port@5 { + port_id = <6>; + phy_address = <28>; + port_mac_sel = "QGMAC_PORT"; + }; + }; +}; + +&tlmm { + mdio_pins: mdio-pins { + mdc { + pins = "gpio68"; + function = "mdc"; + drive-strength = <8>; + bias-pull-up; + }; + + mdio { + pins = "gpio69"; + function = "mdio"; + drive-strength = <8>; + bias-pull-up; + }; + }; +}; + +&mdio { + status = "okay"; + + pinctrl-0 = <&mdio_pins>; + pinctrl-names = "default"; + reset-gpios = <&tlmm 37 GPIO_ACTIVE_LOW>; + + qca8075: ethernet-phy@3 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <3>; + }; + + qca8081: ethernet-phy@28 { + compatible = "ethernet-phy-id004d.d101"; + reg = <28>; + reset-gpios = <&tlmm 25 GPIO_ACTIVE_LOW>; + }; +}; + +&dp4 { + status = "okay"; + phy-handle = <&qca8075>; + label = "lan2"; +}; + +&dp6_syn { + status = "okay"; + phy-handle = <&qca8081>; + label = "lan1"; +}; + +&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"; + }; + }; +}; + +&blsp1_uart5 { + status = "okay"; +}; + +&wifi { + status = "okay"; + + qcom,ath11k-calibration-variant = "Netgear-WAX630"; +}; diff --git a/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8074-wxr-5950ax12.dts b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8074-wxr-5950ax12.dts new file mode 100644 index 000000000..32386dc93 --- /dev/null +++ b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8074-wxr-5950ax12.dts @@ -0,0 +1,376 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +/dts-v1/; + +#include "ipq8074.dtsi" +#include "ipq8074-hk-cpu.dtsi" +#include "ipq8074-ess.dtsi" +#include +#include +#include + +/ { + model = "Buffalo WXR-5950AX12"; + compatible = "buffalo,wxr-5950ax12", "qcom,ipq8074"; + + aliases { + serial0 = &blsp1_uart5; + led-boot = &led_power_white; + led-failsafe = &led_power_red; + led-running = &led_power_white; + led-upgrade = &led_power_white; + label-mac-device = &dp5_syn; + }; + + chosen { + stdout-path = "serial0:115200n8"; + bootargs-append = " ubi.mtd=user_property root=/dev/ubiblock1_0"; + }; + + leds { + compatible = "gpio-leds"; + + led-0 { + label = "white:router"; + gpios = <&tlmm 21 GPIO_ACTIVE_HIGH>; + color = ; + }; + + led-1 { + label = "red:router"; + gpios = <&tlmm 22 GPIO_ACTIVE_HIGH>; + color = ; + }; + + led_power_red: led-2 { + label = "red:power"; + gpios = <&tlmm 31 GPIO_ACTIVE_HIGH>; + color = ; + function = LED_FUNCTION_POWER; + }; + + led_power_white: led-3 { + label = "white:power"; + gpios = <&tlmm 34 GPIO_ACTIVE_HIGH>; + color = ; + function = LED_FUNCTION_POWER; + }; + + led-4 { + label = "white:internet"; + gpios = <&tlmm 43 GPIO_ACTIVE_HIGH>; + color = ; + }; + + led-5 { + label = "red:internet"; + gpios = <&tlmm 44 GPIO_ACTIVE_HIGH>; + color = ; + }; + + led-6 { + label = "red:wireless"; + gpios = <&tlmm 55 GPIO_ACTIVE_HIGH>; + color = ; + function = LED_FUNCTION_WLAN; + }; + + led-7 { + label = "white:wireless"; + gpios = <&tlmm 56 GPIO_ACTIVE_HIGH>; + color = ; + function = LED_FUNCTION_WLAN; + }; + }; + + keys { + compatible = "gpio-keys"; + + /* + * mode: 3x position switch + * + * - ROUTER + * - AP + * - WB (Wireless Bridge) + */ + ap { + label = "mode-ap"; + gpios = <&tlmm 29 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + + bridge { + label = "mode-wb"; + gpios = <&tlmm 30 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + + /* + * op: 2x position switch + * + * - AUTO + * - MANUAL (select Router/AP/WB manually) + */ + manual { + label = "op-manual"; + gpios = <&tlmm 52 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + + wps { + label = "wps"; + gpios = <&tlmm 51 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + + reset { + label = "reset"; + gpios = <&tlmm 54 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + reg_usb_vbus: regulator-5v-vbus { + compatible = "regulator-fixed"; + regulator-name = "vbus"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + gpio = <&tlmm 64 GPIO_ACTIVE_HIGH>; + enable-active-high; + regulator-always-on; + }; +}; + +&tlmm { + mdio_pins: mdio-pins { + mdc { + pins = "gpio68"; + function = "mdc"; + drive-strength = <8>; + bias-pull-up; + }; + + mdio { + pins = "gpio69"; + function = "mdio"; + drive-strength = <8>; + bias-pull-up; + }; + }; +}; + +&blsp1_uart5 { + status = "okay"; +}; + +&prng { + status = "okay"; +}; + +&cryptobam { + status = "okay"; +}; + +&crypto { + 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"; + + partition-0-appsblenv { + compatible = "fixed-partitions"; + label = "0:appsblenv"; + read-only; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + compatible = "u-boot,env"; + label = "env-data"; + reg = <0x0 0x40000>; + + macaddr_appsblenv_ethaddr: ethaddr { + }; + }; + }; + }; + }; +}; + +&mdio { + status = "okay"; + pinctrl-0 = <&mdio_pins>; + pinctrl-names = "default"; + /* + * RESET pins of phy chips + * + * WXR-5950AX12 has 2x RESET pins for QCA8075 and AQR113C. + * The pin of QCA8075 is for the chip and not phys in the chip, the + * pin of AQR113C is for 2x chips. So both pins are not appropriate + * to declare them as reset-gpios in phy nodes. + * Multiple entries in reset-gpios of mdio may not be supported, but + * leave the following as-is to show that the those reset pin exists. + */ + reset-gpios = <&tlmm 37 GPIO_ACTIVE_LOW>, /* QCA8075 RESET */ + <&tlmm 63 GPIO_ACTIVE_LOW>; /* AQR113C RESET (2x) */ + + aqr113c_1: ethernet-phy@0 { + compatible = "ethernet-phy-ieee802.3-c45"; + reg = <0x0>; + }; + + aqr113c_2: ethernet-phy@8 { + compatible = "ethernet-phy-ieee802.3-c45"; + reg = <0x8>; + }; + + qca8075_1: ethernet-phy@18 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <0x18>; + }; + + qca8075_2: ethernet-phy@19 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <0x19>; + }; + + qca8075_3: ethernet-phy@1a { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <0x1a>; + }; + + qca8075_4: ethernet-phy@1b { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <0x1b>; + }; + + qca8075_5: ethernet-phy@1c { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <0x1c>; + }; +}; + +&switch { + status = "okay"; + + switch_cpu_bmp = <0x1>; + switch_lan_bmp = <0x3e>; + switch_wan_bmp = <0x40>; + switch_mac_mode = <0xb>; + switch_mac_mode1 = <0xd>; + switch_mac_mode2 = <0xd>; + bm_tick_mode = <0>; + tm_tick_mode = <0>; + + qcom,port_phyinfo { + port@0 { + port_id = <1>; + phy_address = <0x18>; + }; + + port@1 { + port_id = <2>; + phy_address = <0x19>; + }; + + port@2 { + port_id = <3>; + phy_address = <0x1a>; + }; + + port@3 { + port_id = <4>; + phy_address = <0x1b>; + }; + + port@4 { + port_id = <5>; + ethernet-phy-ieee802.3-c45; + phy_address = <0x0>; + }; + + port@5 { + port_id = <6>; + ethernet-phy-ieee802.3-c45; + phy_address = <0x8>; + }; + }; +}; + +&edma { + status = "okay"; +}; + +&dp2 { + status = "okay"; + phy-handle = <&qca8075_2>; + label = "lan4"; + nvmem-cells = <&macaddr_appsblenv_ethaddr>; + nvmem-cell-names = "mac-address"; +}; + +&dp3 { + status = "okay"; + phy-handle = <&qca8075_3>; + label = "lan3"; + nvmem-cells = <&macaddr_appsblenv_ethaddr>; + nvmem-cell-names = "mac-address"; +}; + +&dp4 { + status = "okay"; + phy-handle = <&qca8075_4>; + label = "lan2"; + nvmem-cells = <&macaddr_appsblenv_ethaddr>; + nvmem-cell-names = "mac-address"; +}; + +&dp5_syn { + status = "okay"; + phy-handle = <&aqr113c_1>; + label = "wan"; + nvmem-cells = <&macaddr_appsblenv_ethaddr>; + nvmem-cell-names = "mac-address"; +}; + +&dp6_syn { + status = "okay"; + phy-handle = <&aqr113c_2>; + label = "lan1"; + nvmem-cells = <&macaddr_appsblenv_ethaddr>; + nvmem-cell-names = "mac-address"; +}; + +&ssphy_0 { + status = "okay"; +}; + +&qusb_phy_0 { + status = "okay"; +}; + +&usb_0 { + status = "okay"; + + vbus-supply = <®_usb_vbus>; +}; + +&wifi { + status = "okay"; + + qcom,ath11k-calibration-variant = "Buffalo-WXR-5950AX12"; +}; diff --git a/target/linux/ipq807x/image/Makefile b/target/linux/qualcommax/image/Makefile similarity index 87% rename from target/linux/ipq807x/image/Makefile rename to target/linux/qualcommax/image/Makefile index 4b0a657c0..f59ad0c15 100644 --- a/target/linux/ipq807x/image/Makefile +++ b/target/linux/qualcommax/image/Makefile @@ -3,7 +3,6 @@ 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 diff --git a/target/linux/qualcommax/image/ipq807x.mk b/target/linux/qualcommax/image/ipq807x.mk new file mode 100644 index 000000000..6406d0013 --- /dev/null +++ b/target/linux/qualcommax/image/ipq807x.mk @@ -0,0 +1,271 @@ +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/EmmcImage + IMAGES += factory.bin sysupgrade.bin + IMAGE/factory.bin := append-rootfs | pad-rootfs | pad-to 64k + IMAGE/sysupgrade.bin/squashfs := append-rootfs | pad-to 64k | sysupgrade-tar rootfs=$$$$@ | append-metadata +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 Build/wax6xx-netgear-tar + mkdir $@.tmp + mv $@ $@.tmp/nand-ipq807x-apps.img + md5sum $@.tmp/nand-ipq807x-apps.img | cut -c 1-32 > $@.tmp/nand-ipq807x-apps.md5sum + echo $(DEVICE_MODEL) > $@.tmp/metadata.txt + echo $(DEVICE_MODEL)"_V9.9.9.9" > $@.tmp/version + tar -C $@.tmp/ -cf $@ . + rm -rf $@.tmp +endef + +define Device/buffalo_wxr-5950ax12 + $(call Device/FitImage) + DEVICE_VENDOR := Buffalo + DEVICE_MODEL := WXR-5950AX12 + BLOCKSIZE := 128k + PAGESIZE := 2048 + DEVICE_DTS_CONFIG := config@hk01 + SOC := ipq8074 + IMAGES := sysupgrade.bin + IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata + DEVICE_PACKAGES := ipq-wifi-buffalo_wxr-5950ax12 +endef +TARGET_DEVICES += buffalo_wxr-5950ax12 + +define Device/cmcc_rm2-6 + $(call Device/FitImage) + $(call Device/UbiFit) + DEVICE_VENDOR := CMCC + DEVICE_MODEL := RM2-6 + BLOCKSIZE := 128k + PAGESIZE := 2048 + DEVICE_DTS_CONFIG := config@ac02 + SOC := ipq8070 + IMAGE/factory.ubi := append-ubi | qsdk-ipq-factory-nand + DEVICE_PACKAGES := ipq-wifi-cmcc_rm2-6 kmod-hwmon-gpiofan +endef +TARGET_DEVICES += cmcc_rm2-6 + +define Device/compex_wpq873 + $(call Device/FitImage) + $(call Device/UbiFit) + DEVICE_VENDOR := Compex + DEVICE_MODEL := WPQ873 + BLOCKSIZE := 128k + PAGESIZE := 2048 + DEVICE_DTS_CONFIG := config@hk09.wpq873 + SOC := ipq8072 + DEVICE_PACKAGES := ipq-wifi-compex_wpq873 + IMAGE/factory.ubi := append-ubi | qsdk-ipq-factory-nand +endef +TARGET_DEVICES += compex_wpq873 + +define Device/dynalink_dl-wrx36 + $(call Device/FitImage) + $(call Device/UbiFit) + DEVICE_VENDOR := Dynalink + DEVICE_MODEL := DL-WRX36 + BLOCKSIZE := 128k + PAGESIZE := 2048 + DEVICE_DTS_CONFIG := config@rt5010w-d350-rev0 + SOC := ipq8072 + DEVICE_PACKAGES := ipq-wifi-dynalink_dl-wrx36 +endef +TARGET_DEVICES += dynalink_dl-wrx36 + +define Device/edgecore_eap102 + $(call Device/FitImage) + $(call Device/UbiFit) + DEVICE_VENDOR := Edgecore + DEVICE_MODEL := EAP102 + BLOCKSIZE := 128k + PAGESIZE := 2048 + DEVICE_DTS_CONFIG := config@ac02 + SOC := ipq8071 + DEVICE_PACKAGES := ipq-wifi-edgecore_eap102 + IMAGE/factory.ubi := append-ubi | qsdk-ipq-factory-nand +endef +TARGET_DEVICES += edgecore_eap102 + +define Device/edimax_cax1800 + $(call Device/FitImage) + $(call Device/UbiFit) + DEVICE_VENDOR := Edimax + DEVICE_MODEL := CAX1800 + BLOCKSIZE := 128k + PAGESIZE := 2048 + DEVICE_DTS_CONFIG := config@ac03 + SOC := ipq8070 + DEVICE_PACKAGES := ipq-wifi-edimax_cax1800 +endef +TARGET_DEVICES += edimax_cax1800 + +define Device/netgear_rax120v2 + $(call Device/FitImage) + $(call Device/UbiFit) + DEVICE_VENDOR := Netgear + DEVICE_MODEL := RAX120v2 + BLOCKSIZE := 128k + PAGESIZE := 2048 + DEVICE_DTS_CONFIG := config@hk01 + SOC := ipq8074 + KERNEL_SIZE := 29696k + NETGEAR_BOARD_ID := RAX120 + NETGEAR_HW_ID := 29765589+0+512+1024+4x4+8x8 + DEVICE_PACKAGES := ipq-wifi-netgear_rax120v2 kmod-spi-gpio \ + kmod-spi-bitbang kmod-gpio-nxp-74hc164 kmod-hwmon-g761 + IMAGES = web-ui-factory.img sysupgrade.bin + IMAGE/web-ui-factory.img := append-image initramfs-uImage.itb | \ + pad-offset $$$$(BLOCKSIZE) 64 | append-uImage-fakehdr filesystem | \ + netgear-dni + IMAGE/sysupgrade.bin := append-kernel | pad-offset $$$$(BLOCKSIZE) 64 | \ + append-uImage-fakehdr filesystem | sysupgrade-tar kernel=$$$$@ | \ + append-metadata +endef +TARGET_DEVICES += netgear_rax120v2 + +define Device/netgear_wax218 + $(call Device/FitImage) + $(call Device/UbiFit) + DEVICE_VENDOR := Netgear + DEVICE_MODEL := WAX218 + DEVICE_DTS_CONFIG := config@hk07 + BLOCKSIZE := 128k + PAGESIZE := 2048 + SOC := ipq8072 +ifneq ($(CONFIG_TARGET_ROOTFS_INITRAMFS),) + ARTIFACTS := web-ui-factory.fit + ARTIFACT/web-ui-factory.fit := append-image initramfs-uImage.itb | \ + ubinize-kernel | qsdk-ipq-factory-nand +endif + DEVICE_PACKAGES := kmod-spi-gpio kmod-spi-bitbang kmod-gpio-nxp-74hc164 \ + ipq-wifi-netgear_wax218 +endef +TARGET_DEVICES += netgear_wax218 + +define Device/netgear_wax620 + $(call Device/FitImage) + $(call Device/UbiFit) + DEVICE_VENDOR := Netgear + DEVICE_MODEL := WAX620 + DEVICE_DTS_CONFIG := config@hk07 + BLOCKSIZE := 128k + PAGESIZE := 2048 + SOC := ipq8072 + DEVICE_PACKAGES := kmod-spi-gpio kmod-gpio-nxp-74hc164 \ + ipq-wifi-netgear_wax620 +endef +TARGET_DEVICES += netgear_wax620 + +define Device/netgear_wax630 + $(call Device/FitImage) + $(call Device/UbiFit) + DEVICE_VENDOR := Netgear + DEVICE_MODEL := WAX630 + DEVICE_DTS_CONFIG := config@hk01 + BLOCKSIZE := 128k + PAGESIZE := 2048 + SOC := ipq8074 + IMAGES := ui-factory.tar factory.ubi sysupgrade.bin + IMAGE/ui-factory.tar := append-ubi | wax6xx-netgear-tar + DEVICE_PACKAGES := kmod-spi-gpio ipq-wifi-netgear_wax630 +endef +TARGET_DEVICES += netgear_wax630 + +define Device/prpl_haze + $(call Device/FitImage) + $(call Device/EmmcImage) + DEVICE_VENDOR := prpl Foundation + DEVICE_MODEL := Haze + DEVICE_DTS_CONFIG := config@hk09 + SOC := ipq8072 + DEVICE_PACKAGES := ath11k-firmware-qcn9074 ipq-wifi-prpl_haze kmod-ath11k-pci \ + mkf2fs f2fsck kmod-fs-f2fs +endef +TARGET_DEVICES += prpl_haze + +define Device/qnap_301w + $(call Device/FitImage) + $(call Device/EmmcImage) + DEVICE_VENDOR := QNAP + DEVICE_MODEL := 301w + DEVICE_DTS_CONFIG := config@hk01 + KERNEL_SIZE := 16384k + SOC := ipq8072 + DEVICE_PACKAGES := ipq-wifi-qnap_301w kmod-phy-aquantia +endef +TARGET_DEVICES += qnap_301w + +define Device/redmi_ax6 + $(call Device/xiaomi_ax3600) + DEVICE_VENDOR := Redmi + DEVICE_MODEL := AX6 + DEVICE_PACKAGES := ipq-wifi-redmi_ax6 +endef +TARGET_DEVICES += redmi_ax6 + +define Device/xiaomi_ax3600 + $(call Device/FitImage) + $(call Device/UbiFit) + DEVICE_VENDOR := Xiaomi + DEVICE_MODEL := AX3600 + BLOCKSIZE := 128k + PAGESIZE := 2048 + DEVICE_DTS_CONFIG := config@ac04 + SOC := ipq8071 + DEVICE_PACKAGES := ipq-wifi-xiaomi_ax3600 +endef +TARGET_DEVICES += xiaomi_ax3600 + +define Device/xiaomi_ax9000 + $(call Device/FitImage) + $(call Device/UbiFit) + DEVICE_VENDOR := Xiaomi + DEVICE_MODEL := AX9000 + BLOCKSIZE := 128k + PAGESIZE := 2048 + DEVICE_DTS_CONFIG := config@hk14 + SOC := ipq8072 + DEVICE_PACKAGES := ipq-wifi-xiaomi_ax9000 kmod-ath11k-pci ath11k-firmware-qcn9074 +endef +TARGET_DEVICES += xiaomi_ax9000 + +define Device/zte_mf269 + $(call Device/FitImage) + $(call Device/UbiFit) + DEVICE_VENDOR := ZTE + DEVICE_MODEL := MF269 + BLOCKSIZE := 128k + PAGESIZE := 2048 + DEVICE_DTS_CONFIG := config@ac04 + SOC := ipq8071 + DEVICE_PACKAGES := ipq-wifi-zte_mf269 +endef +TARGET_DEVICES += zte_mf269 + +define Device/zyxel_nbg7815 + $(call Device/FitImage) + $(call Device/EmmcImage) + DEVICE_VENDOR := ZYXEL + DEVICE_MODEL := NBG7815 + DEVICE_DTS_CONFIG := config@nbg7815 + SOC := ipq8074 + DEVICE_PACKAGES := ipq-wifi-zyxel_nbg7815 kmod-ath11k-pci \ + kmod-bluetooth kmod-hwmon-tmp103 +endef +TARGET_DEVICES += zyxel_nbg7815 diff --git a/target/linux/qualcommax/ipq807x/base-files/etc/board.d/01_leds b/target/linux/qualcommax/ipq807x/base-files/etc/board.d/01_leds new file mode 100644 index 000000000..5e478d75e --- /dev/null +++ b/target/linux/qualcommax/ipq807x/base-files/etc/board.d/01_leds @@ -0,0 +1,47 @@ + +. /lib/functions/uci-defaults.sh + +board_config_update + +board=$(board_name) + +case "$board" in +arcadyan,aw1000) + ucidef_set_led_netdev "5g" "5G" "green:5g" "wwan0" + ucidef_set_led_netdev "wan" "WAN" "green:internet" "wan" + ;; +edgecore,eap102) + ucidef_set_led_netdev "wan" "WAN" "green:wanpoe" "wan" + ;; +netgear,rax120v2) + ucidef_set_led_netdev "aqr" "AQR" "white:aqr" "lan5" + ;; +netgear,wax218) + ucidef_set_led_netdev "lan" "LAN" "blue:lan" "lan" + ucidef_set_led_wlan "wlan5g" "WIFI 5GHz" "blue:wlan5g" "phy0radio" + ucidef_set_led_wlan "wlan2g" "WIFI 2.4GHz" "blue:wlan2g" "phy1radio" + ;; +netgear,wax620) + ucidef_set_led_netdev "lan" "LAN" "lan:green" "lan" + ;; +netgear,wax630) + ucidef_set_led_netdev "lan1" "LAN1" "lan1:green" "lan1" + ucidef_set_led_netdev "lan2" "LAN2" "lan2:green" "lan2" + ;; +redmi,ax6|\ +xiaomi,ax3600) + ucidef_set_led_netdev "wan" "WAN" "blue:network" "wan" + ;; +qnap,301w) + ucidef_set_led_netdev "lan1" "LAN1" "green:lan1" "lan1" + ucidef_set_led_netdev "lan2" "LAN2" "green:lan2" "lan2" + ucidef_set_led_netdev "lan3" "LAN3" "green:lan3" "lan3" + ucidef_set_led_netdev "lan4" "LAN4" "green:lan4" "lan4" + ucidef_set_led_netdev "10G_1" "10G_1" "green:10g_1" "10g-1" + ucidef_set_led_netdev "10G_2" "10G_2" "green:10g_2" "10g-2" + ;; +esac + +board_config_flush + +exit 0 diff --git a/target/linux/qualcommax/ipq807x/base-files/etc/board.d/02_network b/target/linux/qualcommax/ipq807x/base-files/etc/board.d/02_network new file mode 100644 index 000000000..7c630e096 --- /dev/null +++ b/target/linux/qualcommax/ipq807x/base-files/etc/board.d/02_network @@ -0,0 +1,66 @@ +# +# Copyright (c) 2015 The Linux Foundation. All rights reserved. +# Copyright (c) 2011-2015 OpenWrt.org +# + +. /lib/functions/uci-defaults.sh +. /lib/functions/system.sh + +ipq807x_setup_interfaces() +{ + local board="$1" + + case "$board" in + arcadyan,aw1000|\ + buffalo,wxr-5950ax12|\ + dynalink,dl-wrx36|\ + xiaomi,ax9000) + ucidef_set_interfaces_lan_wan "lan1 lan2 lan3 lan4" "wan" + ;; + cmcc,rm2-6) + ucidef_set_interfaces_lan_wan "lan plc" "wan" + ;; + compex,wpq873|\ + redmi,ax6|\ + xiaomi,ax3600) + ucidef_set_interfaces_lan_wan "lan1 lan2 lan3" "wan" + ;; + edgecore,eap102|\ + yuncore,ax880|\ + zte,mf269) + ucidef_set_interfaces_lan_wan "lan" "wan" + ;; + edimax,cax1800) + ucidef_set_interfaces_lan_wan "lan" + ;; + netgear,rax120v2) + ucidef_set_interfaces_lan_wan "lan1 lan2 lan3 lan4 lan5" "wan" + ;; + netgear,wax218|\ + netgear,wax620) + ucidef_set_interface_lan "lan" "dhcp" + ;; + netgear,wax630) + ucidef_set_interface_lan "lan1 lan2" "dhcp" + ;; + prpl,haze) + ucidef_set_interfaces_lan_wan "lan1 lan2 lan3" "wan" + ;; + qnap,301w) + ucidef_set_interfaces_lan_wan "lan1 lan2 lan3 lan4 10g-2" "10g-1" + ;; + zyxel,nbg7815) + ucidef_set_interfaces_lan_wan "lan1 lan2 lan3 lan4 10g" "wan" + ;; + *) + echo "Unsupported hardware. Network interfaces not initialized" + ;; + esac +} + +board_config_update +board=$(board_name) +ipq807x_setup_interfaces $board +board_config_flush + +exit 0 diff --git a/target/linux/qualcommax/ipq807x/base-files/etc/hotplug.d/firmware/11-ath11k-caldata b/target/linux/qualcommax/ipq807x/base-files/etc/hotplug.d/firmware/11-ath11k-caldata new file mode 100644 index 000000000..dc86f5c54 --- /dev/null +++ b/target/linux/qualcommax/ipq807x/base-files/etc/hotplug.d/firmware/11-ath11k-caldata @@ -0,0 +1,50 @@ +#!/bin/sh + +[ -e /lib/firmware/$FIRMWARE ] && exit 0 + +. /lib/functions/caldata.sh + +board=$(board_name) + +case "$FIRMWARE" in +"ath11k/IPQ8074/hw2.0/cal-ahb-c000000.wifi.bin") + case "$board" in + arcadyan,aw1000|\ + buffalo,wxr-5950ax12|\ + cmcc,rm2-6|\ + compex,wpq873|\ + dynalink,dl-wrx36|\ + edgecore,eap102|\ + edimax,cax1800|\ + netgear,rax120v2|\ + netgear,wax218|\ + netgear,wax620|\ + netgear,wax630|\ + qnap,301w|\ + redmi,ax6|\ + xiaomi,ax3600|\ + xiaomi,ax9000|\ + zte,mf269|\ + zyxel,nbg7815) + caldata_extract "0:art" 0x1000 0x20000 + ;; + prpl,haze) + caldata_extract_mmc "0:ART" 0x1000 0x20000 + ;; + esac + ;; +"ath11k/QCN9074/hw1.0/cal-pci-0000:01:00.0.bin"|\ +"ath11k/QCN9074/hw1.0/cal-pci-0001:01:00.0.bin") + case "$board" in + prpl,haze) + caldata_extract_mmc "0:ART" 0x26800 0x20000 + ;; + xiaomi,ax9000) + caldata_extract "0:art" 0x26800 0x20000 + ;; + esac + ;; +*) + exit 1 + ;; +esac diff --git a/target/linux/qualcommax/ipq807x/base-files/etc/hotplug.d/ieee80211/11_fix_wifi_mac b/target/linux/qualcommax/ipq807x/base-files/etc/hotplug.d/ieee80211/11_fix_wifi_mac new file mode 100644 index 000000000..783227f82 --- /dev/null +++ b/target/linux/qualcommax/ipq807x/base-files/etc/hotplug.d/ieee80211/11_fix_wifi_mac @@ -0,0 +1,22 @@ +[ "$ACTION" == "add" ] || exit 0 + +PHYNBR=${DEVPATH##*/phy} + +[ -n $PHYNBR ] || exit 0 + +. /lib/functions.sh +. /lib/functions/system.sh + +board=$(board_name) + +case "$board" in + arcadyan,aw1000) + [ "$PHYNBR" = "0" ] && macaddr_add $(get_mac_label) 1 > /sys${DEVPATH}/macaddress + [ "$PHYNBR" = "1" ] && macaddr_add $(get_mac_label) 2 > /sys${DEVPATH}/macaddress + ;; + cmcc,rm2-6|\ + zte,mf269) + [ "$PHYNBR" = "0" ] && macaddr_add $(get_mac_label) 2 > /sys${DEVPATH}/macaddress + [ "$PHYNBR" = "1" ] && macaddr_add $(get_mac_label) 3 > /sys${DEVPATH}/macaddress + ;; +esac diff --git a/target/linux/qualcommax/ipq807x/base-files/etc/init.d/bootcount b/target/linux/qualcommax/ipq807x/base-files/etc/init.d/bootcount new file mode 100755 index 000000000..6917446a9 --- /dev/null +++ b/target/linux/qualcommax/ipq807x/base-files/etc/init.d/bootcount @@ -0,0 +1,13 @@ +#!/bin/sh /etc/rc.common + +START=99 + +boot() { + case $(board_name) in + edgecore,eap102) + fw_setenv upgrade_available 0 + # Unset changed flag after sysupgrade complete + fw_setenv changed + ;; + esac +} diff --git a/target/linux/qualcommax/ipq807x/base-files/lib/upgrade/buffalo.sh b/target/linux/qualcommax/ipq807x/base-files/lib/upgrade/buffalo.sh new file mode 100644 index 000000000..d0ed25889 --- /dev/null +++ b/target/linux/qualcommax/ipq807x/base-files/lib/upgrade/buffalo.sh @@ -0,0 +1,55 @@ +. /lib/functions.sh + +# Prepare UBI devices for OpenWrt installation +# - rootfs (mtd22) +# - remove "ubi_rootfs" volume (rootfs on stock) +# - remove "fw_hash" volume (firmware hash) +# - user_property (mtd24) +# - remove "user_property_ubi" volume (user configuration) +# - remove "extra_property" volume (gzipped syslog) +buffalo_upgrade_prepare() { + local ubi_rootdev ubi_propdev + + if ! ubi_rootdev="$(nand_attach_ubi rootfs)" || \ + ! ubi_propdev="$(nand_attach_ubi user_property)"; then + echo "failed to attach UBI volume \"rootfs\" or \"user_property\", rebooting..." + reboot -f + fi + + ubirmvol /dev/$ubi_rootdev -N ubi_rootfs &> /dev/null || true + ubirmvol /dev/$ubi_rootdev -N fw_hash &> /dev/null || true + + ubirmvol /dev/$ubi_propdev -N user_property_ubi &> /dev/null || true + ubirmvol /dev/$ubi_propdev -N extra_property &> /dev/null || true +} + +# Re-create small dummy ubi_rootfs volume and update +# fw_hash volume to pass the checking by U-Boot +# - rootfs (mtd22) +# - re-create "ubi_rootfs" volume +# - re-create and update "fw_hash" volume +# - rootfs_recover (mtd23) +# - update "fw_hash" volume +buffalo_upgrade_optvol() { + local ubi_rootdev ubi_rcvrdev + local hashvol_root hashvol_rcvr + + if ! ubi_rootdev="$(nand_attach_ubi rootfs)" || \ + ! ubi_rcvrdev="$(nand_attach_ubi rootfs_recover)"; then + echo "failed to attach UBI volume \"rootfs\" or \"rootfs_recover\", rebooting..." + reboot -f + fi + + ubimkvol /dev/$ubi_rootdev -N ubi_rootfs -S 1 + ubimkvol /dev/$ubi_rootdev -N fw_hash -S 1 -t static + + if ! hashvol_root="$(nand_find_volume $ubi_rootdev fw_hash)" || \ + ! hashvol_rcvr="$(nand_find_volume $ubi_rcvrdev fw_hash)"; then + echo "\"fw_hash\" volume in \"rootfs\" or \"rootfs_recover\" not found, rebooting..." + reboot -f + fi + + echo -n "00000000000000000000000000000000" > /tmp/dummyhash.txt + ubiupdatevol /dev/$hashvol_root /tmp/dummyhash.txt + ubiupdatevol /dev/$hashvol_rcvr /tmp/dummyhash.txt +} diff --git a/target/linux/ipq807x/base-files/lib/upgrade/mmc.sh b/target/linux/qualcommax/ipq807x/base-files/lib/upgrade/mmc.sh similarity index 80% rename from target/linux/ipq807x/base-files/lib/upgrade/mmc.sh rename to target/linux/qualcommax/ipq807x/base-files/lib/upgrade/mmc.sh index dac9ddd56..2e37eec6b 100644 --- a/target/linux/ipq807x/base-files/lib/upgrade/mmc.sh +++ b/target/linux/qualcommax/ipq807x/base-files/lib/upgrade/mmc.sh @@ -3,11 +3,11 @@ # # this can be used as a generic mmc upgrade script -# just add a device entry in platform.sh, +# just add a device entry in platform.sh, # define "kernelname" and "rootfsname" and call mmc_do_upgrade -# after the kernel and rootfs flash a loopdev (as overlay) is +# after the kernel and rootfs flash a loopdev (as overlay) is # setup on top of the rootfs partition -# for the proper function a padded rootfs image is needed, basically +# for the proper function a padded rootfs image is needed, basically # append "pad-to 64k" to the image definition # this is based on the ipq806x zyxel.sh mmc upgrade @@ -18,11 +18,11 @@ mmc_do_upgrade() { local rootfs= local kernel= - [ -z "$kernel" ] && kernel=$(find_mmc_part ${kernelname}) - [ -z "$rootfs" ] && rootfs=$(find_mmc_part ${rootfsname}) + [ -z "$kernel" ] && kernel=$(find_mmc_part ${kernelname}) + [ -z "$rootfs" ] && rootfs=$(find_mmc_part ${rootfsname}) - [ -z "$kernel" ] && echo "Upgrade failed: kernel partition not found! Rebooting..." && reboot -f - [ -z "$rootfs" ] && echo "Upgrade failed: rootfs partition not found! Rebooting..." && reboot -f + [ -z "$kernel" ] && echo "Upgrade failed: kernel partition not found! Rebooting..." && reboot -f + [ -z "$rootfs" ] && echo "Upgrade failed: rootfs partition not found! Rebooting..." && reboot -f mmc_do_flash $tar_file $kernel $rootfs @@ -33,7 +33,7 @@ mmc_do_flash() { local tar_file=$1 local kernel=$2 local rootfs=$3 - + # keep sure its unbound losetup --detach-all || { echo Failed to detach all loop devices. Skip this try. diff --git a/target/linux/qualcommax/ipq807x/base-files/lib/upgrade/platform.sh b/target/linux/qualcommax/ipq807x/base-files/lib/upgrade/platform.sh new file mode 100644 index 000000000..4c8a38c26 --- /dev/null +++ b/target/linux/qualcommax/ipq807x/base-files/lib/upgrade/platform.sh @@ -0,0 +1,69 @@ +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 + arcadyan,aw1000|\ + cmcc,rm2-6|\ + compex,wpq873|\ + dynalink,dl-wrx36|\ + edimax,cax1800|\ + netgear,rax120v2|\ + netgear,wax218|\ + netgear,wax620|\ + netgear,wax630|\ + zte,mf269) + nand_do_upgrade "$1" + ;; + buffalo,wxr-5950ax12) + CI_KERN_UBIPART="rootfs" + CI_ROOT_UBIPART="user_property" + buffalo_upgrade_prepare + nand_do_flash_file "$1" || nand_do_upgrade_failed + nand_do_restore_config || nand_do_upgrade_failed + buffalo_upgrade_optvol + ;; + edgecore,eap102) + active="$(fw_printenv -n active)" + if [ "$active" -eq "1" ]; then + CI_UBIPART="rootfs2" + else + CI_UBIPART="rootfs1" + fi + # force altbootcmd which handles partition change in u-boot + fw_setenv bootcount 3 + fw_setenv upgrade_available 1 + nand_do_upgrade "$1" + ;; + prpl,haze|\ + qnap,301w) + kernelname="0:HLOS" + rootfsname="rootfs" + mmc_do_upgrade "$1" + ;; + zyxel,nbg7815) + local config_mtdnum="$(find_mtd_index 0:bootconfig)" + [ -z "$config_mtdnum" ] && reboot + part_num="$(hexdump -e '1/1 "%01x|"' -n 1 -s 168 -C /dev/mtd$config_mtdnum | cut -f 1 -d "|" | head -n1)" + if [ "$part_num" -eq "0" ]; then + kernelname="0:HLOS" + rootfsname="rootfs" + mmc_do_upgrade "$1" + else + kernelname="0:HLOS_1" + rootfsname="rootfs_1" + mmc_do_upgrade "$1" + fi + ;; + *) + default_do_upgrade "$1" + ;; + esac +} diff --git a/target/linux/qualcommax/ipq807x/config-default b/target/linux/qualcommax/ipq807x/config-default new file mode 100644 index 000000000..18483d05b --- /dev/null +++ b/target/linux/qualcommax/ipq807x/config-default @@ -0,0 +1,30 @@ +CONFIG_ARM_PSCI_CPUIDLE_DOMAIN=y +CONFIG_DT_IDLE_GENPD=y +CONFIG_IPQ_GCC_8074=y +# CONFIG_MFD_HI6421_SPMI is not set +CONFIG_MFD_SPMI_PMIC=y +# CONFIG_NVMEM_SPMI_SDAM is not set +CONFIG_PINCTRL_IPQ8074=y +CONFIG_PINCTRL_QCOM_SPMI_PMIC=y +# CONFIG_PM8916_WATCHDOG is not set +CONFIG_PM_GENERIC_DOMAINS=y +CONFIG_PM_GENERIC_DOMAINS_OF=y +# CONFIG_POWER_RESET_QCOM_PON is not set +CONFIG_QCOM_APM=y +# CONFIG_QCOM_COINCELL is not set +CONFIG_QCOM_GDSC=y +CONFIG_QCOM_SPMI_ADC5=y +# CONFIG_QCOM_SPMI_RRADC is not set +CONFIG_QCOM_VADC_COMMON=y +CONFIG_REGMAP_SPMI=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_SPMI=y +# CONFIG_REGULATOR_QCOM_USB_VBUS is not set +CONFIG_RTC_DRV_PM8XXX=y +CONFIG_SPMI=y +# CONFIG_SPMI_HISI3670 is not set +CONFIG_SPMI_MSM_PMIC_ARB=y +# CONFIG_SPMI_PMIC_CLKDIV is not set diff --git a/target/linux/qualcommax/ipq807x/target.mk b/target/linux/qualcommax/ipq807x/target.mk new file mode 100644 index 000000000..d5aff23ef --- /dev/null +++ b/target/linux/qualcommax/ipq807x/target.mk @@ -0,0 +1,7 @@ +SUBTARGET:=ipq807x +BOARDNAME:=Qualcomm Atheros IPQ807x +DEFAULT_PACKAGES += ath11k-firmware-ipq8074 + +define Target/Description + Build firmware images for Qualcomm Atheros IPQ807x based boards. +endef diff --git a/target/linux/qualcommax/patches-6.1/0001-v6.2-arm64-dts-qcom-ipq8074-add-A53-PLL-node.patch b/target/linux/qualcommax/patches-6.1/0001-v6.2-arm64-dts-qcom-ipq8074-add-A53-PLL-node.patch new file mode 100644 index 000000000..dd57eae36 --- /dev/null +++ b/target/linux/qualcommax/patches-6.1/0001-v6.2-arm64-dts-qcom-ipq8074-add-A53-PLL-node.patch @@ -0,0 +1,32 @@ +From 6463c10bfdbd684ec7ecfd408ea541283215a088 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Fri, 19 Aug 2022 00:06:28 +0200 +Subject: [PATCH] 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 +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20220818220628.339366-9-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 +@@ -675,6 +675,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/qualcommax/patches-6.1/0002-v6.2-thermal-drivers-tsens-Add-support-for-combined-inter.patch b/target/linux/qualcommax/patches-6.1/0002-v6.2-thermal-drivers-tsens-Add-support-for-combined-inter.patch new file mode 100644 index 000000000..032072599 --- /dev/null +++ b/target/linux/qualcommax/patches-6.1/0002-v6.2-thermal-drivers-tsens-Add-support-for-combined-inter.patch @@ -0,0 +1,134 @@ +From e593e834fe8ba9bf314d8215ac05d8787f81efda Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Fri, 19 Aug 2022 00:02:42 +0200 +Subject: [PATCH] thermal/drivers/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 +Reviewed-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20220818220245.338396-2-robimarko@gmail.com +Signed-off-by: Daniel Lezcano +--- + 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 +@@ -532,6 +532,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(struct thermal_zone_device *tz, int low, int high) + { + struct tsens_sensor *s = tz->devdata; +@@ -1074,13 +1095,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 +@@ -493,6 +493,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? +@@ -502,6 +503,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/qualcommax/patches-6.1/0003-v6.2-thermal-drivers-tsens-Allow-configuring-min-and-max-.patch b/target/linux/qualcommax/patches-6.1/0003-v6.2-thermal-drivers-tsens-Allow-configuring-min-and-max-.patch new file mode 100644 index 000000000..363061813 --- /dev/null +++ b/target/linux/qualcommax/patches-6.1/0003-v6.2-thermal-drivers-tsens-Allow-configuring-min-and-max-.patch @@ -0,0 +1,101 @@ +From 7805365fee582056b32c69cf35aafbb94b14a8ca Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Fri, 19 Aug 2022 00:02:43 +0200 +Subject: [PATCH] thermal/drivers/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 +Link: https://lore.kernel.org/r/20220818220245.338396-3-robimarko@gmail.com +Signed-off-by: Daniel Lezcano +--- + 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 +@@ -573,8 +573,8 @@ static int tsens_set_trips(struct therma + 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 +@@ -499,6 +499,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; +@@ -508,6 +510,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/qualcommax/patches-6.1/0004-v6.2-thermal-drivers-tsens-Add-IPQ8074-support.patch b/target/linux/qualcommax/patches-6.1/0004-v6.2-thermal-drivers-tsens-Add-IPQ8074-support.patch new file mode 100644 index 000000000..eaea69395 --- /dev/null +++ b/target/linux/qualcommax/patches-6.1/0004-v6.2-thermal-drivers-tsens-Add-IPQ8074-support.patch @@ -0,0 +1,74 @@ +From 0164d794cbc58488a7321272e95958d10cf103a4 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Fri, 19 Aug 2022 00:02:44 +0200 +Subject: [PATCH] thermal/drivers/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 +Link: https://lore.kernel.org/r/20220818220245.338396-4-robimarko@gmail.com +Signed-off-by: Daniel Lezcano +--- + 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 +@@ -981,6 +981,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 +@@ -597,6 +597,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/ipq807x/patches-5.15/0122-arm64-dts-ipq8074-add-thermal-nodes.patch b/target/linux/qualcommax/patches-6.1/0005-v6.2-arm64-dts-qcom-ipq8074-add-thermal-nodes.patch similarity index 82% rename from target/linux/ipq807x/patches-5.15/0122-arm64-dts-ipq8074-add-thermal-nodes.patch rename to target/linux/qualcommax/patches-6.1/0005-v6.2-arm64-dts-qcom-ipq8074-add-thermal-nodes.patch index 80a3344ad..bad75e459 100644 --- a/target/linux/ipq807x/patches-5.15/0122-arm64-dts-ipq8074-add-thermal-nodes.patch +++ b/target/linux/qualcommax/patches-6.1/0005-v6.2-arm64-dts-qcom-ipq8074-add-thermal-nodes.patch @@ -1,7 +1,7 @@ -From bf718a63d90b0921064892fa0e4dcf3db5233b1a Mon Sep 17 00:00:00 2001 +From c3cc0c2a17f552be2426200e47a9e2c62cf449ce Mon Sep 17 00:00:00 2001 From: Robert Marko -Date: Fri, 24 Dec 2021 20:33:59 +0100 -Subject: [PATCH] arm64: dts: ipq8074: add thermal nodes +Date: Fri, 19 Aug 2022 00:02:45 +0200 +Subject: [PATCH] arm64: dts: qcom: ipq8074: add thermal nodes IPQ8074 has a tsens v2.3.0 peripheral which monitors temperatures around the various subsystems on the @@ -12,13 +12,15 @@ CPU cooling will come in later patches after CPU frequency scaling is supported. Signed-off-by: Robert Marko +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20220818220245.338396-5-robimarko@gmail.com --- 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 -@@ -331,6 +331,16 @@ +@@ -274,6 +274,16 @@ status = "disabled"; }; @@ -27,17 +29,17 @@ Signed-off-by: Robert Marko + reg = <0x4a9000 0x1000>, /* TM */ + <0x4a8000 0x1000>; /* SROT */ + interrupts = ; -+ interrupt-names = "uplow"; ++ interrupt-names = "combined"; + #qcom,sensors = <16>; + #thermal-sensor-cells = <1>; + }; + - cryptobam: dma@704000 { + cryptobam: dma-controller@704000 { compatible = "qcom,bam-v1.7.0"; reg = <0x00704000 0x20000>; -@@ -1083,4 +1093,90 @@ - status = "disabled"; - }; +@@ -874,4 +884,90 @@ + , + ; }; + + thermal-zones { diff --git a/target/linux/qualcommax/patches-6.1/0006-v6.2-arm64-dts-qcom-ipq8074-add-clocks-to-APCS.patch b/target/linux/qualcommax/patches-6.1/0006-v6.2-arm64-dts-qcom-ipq8074-add-clocks-to-APCS.patch new file mode 100644 index 000000000..e22985164 --- /dev/null +++ b/target/linux/qualcommax/patches-6.1/0006-v6.2-arm64-dts-qcom-ipq8074-add-clocks-to-APCS.patch @@ -0,0 +1,29 @@ +From 0df592a0a1a3fff9133977192677aa915afc174f Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Fri, 19 Aug 2022 00:08:49 +0200 +Subject: [PATCH] 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 +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20220818220849.339732-4-robimarko@gmail.com +--- + arch/arm64/boot/dts/qcom/ipq8074.dtsi | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi ++++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi +@@ -680,6 +680,8 @@ + apcs_glb: mailbox@b111000 { + compatible = "qcom,ipq8074-apcs-apps-global"; + reg = <0x0b111000 0x1000>; ++ clocks = <&a53pll>, <&xo>; ++ clock-names = "pll", "xo"; + + #clock-cells = <1>; + #mbox-cells = <1>; diff --git a/target/linux/qualcommax/patches-6.1/0007-v6.2-clk-qcom-ipq8074-convert-to-parent-data.patch b/target/linux/qualcommax/patches-6.1/0007-v6.2-clk-qcom-ipq8074-convert-to-parent-data.patch new file mode 100644 index 000000000..c209adbc0 --- /dev/null +++ b/target/linux/qualcommax/patches-6.1/0007-v6.2-clk-qcom-ipq8074-convert-to-parent-data.patch @@ -0,0 +1,3601 @@ +From e6c5115d6845f25eda7e162dcd783a2044215867 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Sun, 30 Oct 2022 18:57:01 +0100 +Subject: [PATCH] clk: qcom: ipq8074: convert to parent data + +Convert the IPQ8074 GCC driver to use parent data instead of global +name matching. + +Utilize ARRAY_SIZE for num_parents instead of hardcoding the value. + +Signed-off-by: Robert Marko +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20221030175703.1103224-1-robimarko@gmail.com +--- + drivers/clk/qcom/gcc-ipq8074.c | 1781 +++++++++++++++----------------- + 1 file changed, 813 insertions(+), 968 deletions(-) + +--- a/drivers/clk/qcom/gcc-ipq8074.c ++++ b/drivers/clk/qcom/gcc-ipq8074.c +@@ -49,349 +49,6 @@ enum { + P_UNIPHY2_TX, + }; + +-static const char * const gcc_xo_gpll0_gpll0_out_main_div2[] = { +- "xo", +- "gpll0", +- "gpll0_out_main_div2", +-}; +- +-static const struct parent_map gcc_xo_gpll0_gpll0_out_main_div2_map[] = { +- { P_XO, 0 }, +- { P_GPLL0, 1 }, +- { P_GPLL0_DIV2, 4 }, +-}; +- +-static const struct parent_map gcc_xo_gpll0_map[] = { +- { P_XO, 0 }, +- { P_GPLL0, 1 }, +-}; +- +-static const char * const gcc_xo_gpll0_gpll2_gpll0_out_main_div2[] = { +- "xo", +- "gpll0", +- "gpll2", +- "gpll0_out_main_div2", +-}; +- +-static const struct parent_map gcc_xo_gpll0_gpll2_gpll0_out_main_div2_map[] = { +- { P_XO, 0 }, +- { P_GPLL0, 1 }, +- { P_GPLL2, 2 }, +- { P_GPLL0_DIV2, 4 }, +-}; +- +-static const char * const gcc_xo_gpll0_sleep_clk[] = { +- "xo", +- "gpll0", +- "sleep_clk", +-}; +- +-static const struct parent_map gcc_xo_gpll0_sleep_clk_map[] = { +- { P_XO, 0 }, +- { P_GPLL0, 2 }, +- { P_SLEEP_CLK, 6 }, +-}; +- +-static const char * const gcc_xo_gpll6_gpll0_gpll0_out_main_div2[] = { +- "xo", +- "gpll6", +- "gpll0", +- "gpll0_out_main_div2", +-}; +- +-static const struct parent_map gcc_xo_gpll6_gpll0_gpll0_out_main_div2_map[] = { +- { P_XO, 0 }, +- { P_GPLL6, 1 }, +- { P_GPLL0, 3 }, +- { P_GPLL0_DIV2, 4 }, +-}; +- +-static const char * const gcc_xo_gpll0_out_main_div2_gpll0[] = { +- "xo", +- "gpll0_out_main_div2", +- "gpll0", +-}; +- +-static const struct parent_map gcc_xo_gpll0_out_main_div2_gpll0_map[] = { +- { P_XO, 0 }, +- { P_GPLL0_DIV2, 2 }, +- { P_GPLL0, 1 }, +-}; +- +-static const char * const gcc_usb3phy_0_cc_pipe_clk_xo[] = { +- "usb3phy_0_cc_pipe_clk", +- "xo", +-}; +- +-static const struct parent_map gcc_usb3phy_0_cc_pipe_clk_xo_map[] = { +- { P_USB3PHY_0_PIPE, 0 }, +- { P_XO, 2 }, +-}; +- +-static const char * const gcc_usb3phy_1_cc_pipe_clk_xo[] = { +- "usb3phy_1_cc_pipe_clk", +- "xo", +-}; +- +-static const struct parent_map gcc_usb3phy_1_cc_pipe_clk_xo_map[] = { +- { P_USB3PHY_1_PIPE, 0 }, +- { P_XO, 2 }, +-}; +- +-static const char * const gcc_pcie20_phy0_pipe_clk_xo[] = { +- "pcie20_phy0_pipe_clk", +- "xo", +-}; +- +-static const struct parent_map gcc_pcie20_phy0_pipe_clk_xo_map[] = { +- { P_PCIE20_PHY0_PIPE, 0 }, +- { P_XO, 2 }, +-}; +- +-static const char * const gcc_pcie20_phy1_pipe_clk_xo[] = { +- "pcie20_phy1_pipe_clk", +- "xo", +-}; +- +-static const struct parent_map gcc_pcie20_phy1_pipe_clk_xo_map[] = { +- { P_PCIE20_PHY1_PIPE, 0 }, +- { P_XO, 2 }, +-}; +- +-static const char * const gcc_xo_gpll0_gpll6_gpll0_div2[] = { +- "xo", +- "gpll0", +- "gpll6", +- "gpll0_out_main_div2", +-}; +- +-static const struct parent_map gcc_xo_gpll0_gpll6_gpll0_div2_map[] = { +- { P_XO, 0 }, +- { P_GPLL0, 1 }, +- { P_GPLL6, 2 }, +- { P_GPLL0_DIV2, 4 }, +-}; +- +-static const char * const gcc_xo_gpll0_gpll6_gpll0_out_main_div2[] = { +- "xo", +- "gpll0", +- "gpll6", +- "gpll0_out_main_div2", +-}; +- +-static const struct parent_map gcc_xo_gpll0_gpll6_gpll0_out_main_div2_map[] = { +- { P_XO, 0 }, +- { P_GPLL0, 1 }, +- { P_GPLL6, 2 }, +- { P_GPLL0_DIV2, 3 }, +-}; +- +-static const char * const gcc_xo_bias_pll_nss_noc_clk_gpll0_gpll2[] = { +- "xo", +- "bias_pll_nss_noc_clk", +- "gpll0", +- "gpll2", +-}; +- +-static const struct parent_map gcc_xo_bias_pll_nss_noc_clk_gpll0_gpll2_map[] = { +- { P_XO, 0 }, +- { P_BIAS_PLL_NSS_NOC, 1 }, +- { P_GPLL0, 2 }, +- { P_GPLL2, 3 }, +-}; +- +-static const char * const gcc_xo_nss_crypto_pll_gpll0[] = { +- "xo", +- "nss_crypto_pll", +- "gpll0", +-}; +- +-static const struct parent_map gcc_xo_nss_crypto_pll_gpll0_map[] = { +- { P_XO, 0 }, +- { P_NSS_CRYPTO_PLL, 1 }, +- { P_GPLL0, 2 }, +-}; +- +-static const char * const gcc_xo_ubi32_pll_gpll0_gpll2_gpll4_gpll6[] = { +- "xo", +- "ubi32_pll", +- "gpll0", +- "gpll2", +- "gpll4", +- "gpll6", +-}; +- +-static const struct parent_map gcc_xo_ubi32_gpll0_gpll2_gpll4_gpll6_map[] = { +- { P_XO, 0 }, +- { P_UBI32_PLL, 1 }, +- { P_GPLL0, 2 }, +- { P_GPLL2, 3 }, +- { P_GPLL4, 4 }, +- { P_GPLL6, 5 }, +-}; +- +-static const char * const gcc_xo_gpll0_out_main_div2[] = { +- "xo", +- "gpll0_out_main_div2", +-}; +- +-static const struct parent_map gcc_xo_gpll0_out_main_div2_map[] = { +- { P_XO, 0 }, +- { P_GPLL0_DIV2, 1 }, +-}; +- +-static const char * const gcc_xo_bias_gpll0_gpll4_nss_ubi32[] = { +- "xo", +- "bias_pll_cc_clk", +- "gpll0", +- "gpll4", +- "nss_crypto_pll", +- "ubi32_pll", +-}; +- +-static const struct parent_map gcc_xo_bias_gpll0_gpll4_nss_ubi32_map[] = { +- { P_XO, 0 }, +- { P_BIAS_PLL, 1 }, +- { P_GPLL0, 2 }, +- { P_GPLL4, 3 }, +- { P_NSS_CRYPTO_PLL, 4 }, +- { P_UBI32_PLL, 5 }, +-}; +- +-static const char * const gcc_xo_gpll0_gpll4[] = { +- "xo", +- "gpll0", +- "gpll4", +-}; +- +-static const struct parent_map gcc_xo_gpll0_gpll4_map[] = { +- { P_XO, 0 }, +- { P_GPLL0, 1 }, +- { P_GPLL4, 2 }, +-}; +- +-static const char * const gcc_xo_uniphy0_rx_tx_ubi32_bias[] = { +- "xo", +- "uniphy0_gcc_rx_clk", +- "uniphy0_gcc_tx_clk", +- "ubi32_pll", +- "bias_pll_cc_clk", +-}; +- +-static const struct parent_map gcc_xo_uniphy0_rx_tx_ubi32_bias_map[] = { +- { P_XO, 0 }, +- { P_UNIPHY0_RX, 1 }, +- { P_UNIPHY0_TX, 2 }, +- { P_UBI32_PLL, 5 }, +- { P_BIAS_PLL, 6 }, +-}; +- +-static const char * const gcc_xo_uniphy0_tx_rx_ubi32_bias[] = { +- "xo", +- "uniphy0_gcc_tx_clk", +- "uniphy0_gcc_rx_clk", +- "ubi32_pll", +- "bias_pll_cc_clk", +-}; +- +-static const struct parent_map gcc_xo_uniphy0_tx_rx_ubi32_bias_map[] = { +- { P_XO, 0 }, +- { P_UNIPHY0_TX, 1 }, +- { P_UNIPHY0_RX, 2 }, +- { P_UBI32_PLL, 5 }, +- { P_BIAS_PLL, 6 }, +-}; +- +-static const char * const gcc_xo_uniphy0_rx_tx_uniphy1_rx_tx_ubi32_bias[] = { +- "xo", +- "uniphy0_gcc_rx_clk", +- "uniphy0_gcc_tx_clk", +- "uniphy1_gcc_rx_clk", +- "uniphy1_gcc_tx_clk", +- "ubi32_pll", +- "bias_pll_cc_clk", +-}; +- +-static const struct parent_map +-gcc_xo_uniphy0_rx_tx_uniphy1_rx_tx_ubi32_bias_map[] = { +- { P_XO, 0 }, +- { P_UNIPHY0_RX, 1 }, +- { P_UNIPHY0_TX, 2 }, +- { P_UNIPHY1_RX, 3 }, +- { P_UNIPHY1_TX, 4 }, +- { P_UBI32_PLL, 5 }, +- { P_BIAS_PLL, 6 }, +-}; +- +-static const char * const gcc_xo_uniphy0_tx_rx_uniphy1_tx_rx_ubi32_bias[] = { +- "xo", +- "uniphy0_gcc_tx_clk", +- "uniphy0_gcc_rx_clk", +- "uniphy1_gcc_tx_clk", +- "uniphy1_gcc_rx_clk", +- "ubi32_pll", +- "bias_pll_cc_clk", +-}; +- +-static const struct parent_map +-gcc_xo_uniphy0_tx_rx_uniphy1_tx_rx_ubi32_bias_map[] = { +- { P_XO, 0 }, +- { P_UNIPHY0_TX, 1 }, +- { P_UNIPHY0_RX, 2 }, +- { P_UNIPHY1_TX, 3 }, +- { P_UNIPHY1_RX, 4 }, +- { P_UBI32_PLL, 5 }, +- { P_BIAS_PLL, 6 }, +-}; +- +-static const char * const gcc_xo_uniphy2_rx_tx_ubi32_bias[] = { +- "xo", +- "uniphy2_gcc_rx_clk", +- "uniphy2_gcc_tx_clk", +- "ubi32_pll", +- "bias_pll_cc_clk", +-}; +- +-static const struct parent_map gcc_xo_uniphy2_rx_tx_ubi32_bias_map[] = { +- { P_XO, 0 }, +- { P_UNIPHY2_RX, 1 }, +- { P_UNIPHY2_TX, 2 }, +- { P_UBI32_PLL, 5 }, +- { P_BIAS_PLL, 6 }, +-}; +- +-static const char * const gcc_xo_uniphy2_tx_rx_ubi32_bias[] = { +- "xo", +- "uniphy2_gcc_tx_clk", +- "uniphy2_gcc_rx_clk", +- "ubi32_pll", +- "bias_pll_cc_clk", +-}; +- +-static const struct parent_map gcc_xo_uniphy2_tx_rx_ubi32_bias_map[] = { +- { P_XO, 0 }, +- { P_UNIPHY2_TX, 1 }, +- { P_UNIPHY2_RX, 2 }, +- { P_UBI32_PLL, 5 }, +- { P_BIAS_PLL, 6 }, +-}; +- +-static const char * const gcc_xo_gpll0_gpll6_gpll0_sleep_clk[] = { +- "xo", +- "gpll0", +- "gpll6", +- "gpll0_out_main_div2", +- "sleep_clk", +-}; +- +-static const struct parent_map gcc_xo_gpll0_gpll6_gpll0_sleep_clk_map[] = { +- { P_XO, 0 }, +- { P_GPLL0, 1 }, +- { P_GPLL6, 2 }, +- { P_GPLL0_DIV2, 4 }, +- { P_SLEEP_CLK, 6 }, +-}; +- + static struct clk_alpha_pll gpll0_main = { + .offset = 0x21000, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], +@@ -400,8 +57,9 @@ static struct clk_alpha_pll gpll0_main = + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gpll0_main", +- .parent_names = (const char *[]){ +- "xo" ++ .parent_data = &(const struct clk_parent_data){ ++ .fw_name = "xo", ++ .name = "xo", + }, + .num_parents = 1, + .ops = &clk_alpha_pll_ops, +@@ -414,9 +72,8 @@ static struct clk_fixed_factor gpll0_out + .div = 2, + .hw.init = &(struct clk_init_data){ + .name = "gpll0_out_main_div2", +- .parent_names = (const char *[]){ +- "gpll0_main" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &gpll0_main.clkr.hw }, + .num_parents = 1, + .ops = &clk_fixed_factor_ops, + }, +@@ -428,9 +85,8 @@ static struct clk_alpha_pll_postdiv gpll + .width = 4, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gpll0", +- .parent_names = (const char *[]){ +- "gpll0_main" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &gpll0_main.clkr.hw }, + .num_parents = 1, + .ops = &clk_alpha_pll_postdiv_ro_ops, + }, +@@ -444,8 +100,9 @@ static struct clk_alpha_pll gpll2_main = + .enable_mask = BIT(2), + .hw.init = &(struct clk_init_data){ + .name = "gpll2_main", +- .parent_names = (const char *[]){ +- "xo" ++ .parent_data = &(const struct clk_parent_data){ ++ .fw_name = "xo", ++ .name = "xo", + }, + .num_parents = 1, + .ops = &clk_alpha_pll_ops, +@@ -460,9 +117,8 @@ static struct clk_alpha_pll_postdiv gpll + .width = 4, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gpll2", +- .parent_names = (const char *[]){ +- "gpll2_main" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &gpll2_main.clkr.hw }, + .num_parents = 1, + .ops = &clk_alpha_pll_postdiv_ro_ops, + }, +@@ -476,8 +132,9 @@ static struct clk_alpha_pll gpll4_main = + .enable_mask = BIT(5), + .hw.init = &(struct clk_init_data){ + .name = "gpll4_main", +- .parent_names = (const char *[]){ +- "xo" ++ .parent_data = &(const struct clk_parent_data){ ++ .fw_name = "xo", ++ .name = "xo", + }, + .num_parents = 1, + .ops = &clk_alpha_pll_ops, +@@ -492,9 +149,8 @@ static struct clk_alpha_pll_postdiv gpll + .width = 4, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gpll4", +- .parent_names = (const char *[]){ +- "gpll4_main" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &gpll4_main.clkr.hw }, + .num_parents = 1, + .ops = &clk_alpha_pll_postdiv_ro_ops, + }, +@@ -509,8 +165,9 @@ static struct clk_alpha_pll gpll6_main = + .enable_mask = BIT(7), + .hw.init = &(struct clk_init_data){ + .name = "gpll6_main", +- .parent_names = (const char *[]){ +- "xo" ++ .parent_data = &(const struct clk_parent_data){ ++ .fw_name = "xo", ++ .name = "xo", + }, + .num_parents = 1, + .ops = &clk_alpha_pll_ops, +@@ -525,9 +182,8 @@ static struct clk_alpha_pll_postdiv gpll + .width = 2, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gpll6", +- .parent_names = (const char *[]){ +- "gpll6_main" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &gpll6_main.clkr.hw }, + .num_parents = 1, + .ops = &clk_alpha_pll_postdiv_ro_ops, + }, +@@ -538,9 +194,8 @@ static struct clk_fixed_factor gpll6_out + .div = 2, + .hw.init = &(struct clk_init_data){ + .name = "gpll6_out_main_div2", +- .parent_names = (const char *[]){ +- "gpll6_main" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &gpll6_main.clkr.hw }, + .num_parents = 1, + .ops = &clk_fixed_factor_ops, + }, +@@ -555,8 +210,9 @@ static struct clk_alpha_pll ubi32_pll_ma + .enable_mask = BIT(6), + .hw.init = &(struct clk_init_data){ + .name = "ubi32_pll_main", +- .parent_names = (const char *[]){ +- "xo" ++ .parent_data = &(const struct clk_parent_data){ ++ .fw_name = "xo", ++ .name = "xo", + }, + .num_parents = 1, + .ops = &clk_alpha_pll_huayra_ops, +@@ -570,9 +226,8 @@ static struct clk_alpha_pll_postdiv ubi3 + .width = 2, + .clkr.hw.init = &(struct clk_init_data){ + .name = "ubi32_pll", +- .parent_names = (const char *[]){ +- "ubi32_pll_main" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &ubi32_pll_main.clkr.hw }, + .num_parents = 1, + .ops = &clk_alpha_pll_postdiv_ro_ops, + .flags = CLK_SET_RATE_PARENT, +@@ -587,8 +242,9 @@ static struct clk_alpha_pll nss_crypto_p + .enable_mask = BIT(4), + .hw.init = &(struct clk_init_data){ + .name = "nss_crypto_pll_main", +- .parent_names = (const char *[]){ +- "xo" ++ .parent_data = &(const struct clk_parent_data){ ++ .fw_name = "xo", ++ .name = "xo", + }, + .num_parents = 1, + .ops = &clk_alpha_pll_ops, +@@ -602,9 +258,8 @@ static struct clk_alpha_pll_postdiv nss_ + .width = 4, + .clkr.hw.init = &(struct clk_init_data){ + .name = "nss_crypto_pll", +- .parent_names = (const char *[]){ +- "nss_crypto_pll_main" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_crypto_pll_main.clkr.hw }, + .num_parents = 1, + .ops = &clk_alpha_pll_postdiv_ro_ops, + }, +@@ -617,6 +272,18 @@ static const struct freq_tbl ftbl_pcnoc_ + { } + }; + ++static const struct clk_parent_data gcc_xo_gpll0_gpll0_out_main_div2[] = { ++ { .fw_name = "xo", .name = "xo" }, ++ { .hw = &gpll0.clkr.hw}, ++ { .hw = &gpll0_out_main_div2.hw}, ++}; ++ ++static const struct parent_map gcc_xo_gpll0_gpll0_out_main_div2_map[] = { ++ { P_XO, 0 }, ++ { P_GPLL0, 1 }, ++ { P_GPLL0_DIV2, 4 }, ++}; ++ + static struct clk_rcg2 pcnoc_bfdcd_clk_src = { + .cmd_rcgr = 0x27000, + .freq_tbl = ftbl_pcnoc_bfdcd_clk_src, +@@ -624,8 +291,8 @@ static struct clk_rcg2 pcnoc_bfdcd_clk_s + .parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "pcnoc_bfdcd_clk_src", +- .parent_names = gcc_xo_gpll0_gpll0_out_main_div2, +- .num_parents = 3, ++ .parent_data = gcc_xo_gpll0_gpll0_out_main_div2, ++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2), + .ops = &clk_rcg2_ops, + .flags = CLK_IS_CRITICAL, + }, +@@ -636,9 +303,8 @@ static struct clk_fixed_factor pcnoc_clk + .div = 1, + .hw.init = &(struct clk_init_data){ + .name = "pcnoc_clk_src", +- .parent_names = (const char *[]){ +- "pcnoc_bfdcd_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &pcnoc_bfdcd_clk_src.clkr.hw }, + .num_parents = 1, + .ops = &clk_fixed_factor_ops, + .flags = CLK_SET_RATE_PARENT, +@@ -652,8 +318,9 @@ static struct clk_branch gcc_sleep_clk_s + .enable_mask = BIT(1), + .hw.init = &(struct clk_init_data){ + .name = "gcc_sleep_clk_src", +- .parent_names = (const char *[]){ +- "sleep_clk" ++ .parent_data = &(const struct clk_parent_data){ ++ .fw_name = "sleep_clk", ++ .name = "sleep_clk", + }, + .num_parents = 1, + .ops = &clk_branch2_ops, +@@ -676,8 +343,8 @@ static struct clk_rcg2 blsp1_qup1_i2c_ap + .parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_qup1_i2c_apps_clk_src", +- .parent_names = gcc_xo_gpll0_gpll0_out_main_div2, +- .num_parents = 3, ++ .parent_data = gcc_xo_gpll0_gpll0_out_main_div2, ++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2), + .ops = &clk_rcg2_ops, + }, + }; +@@ -702,8 +369,8 @@ static struct clk_rcg2 blsp1_qup1_spi_ap + .parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_qup1_spi_apps_clk_src", +- .parent_names = gcc_xo_gpll0_gpll0_out_main_div2, +- .num_parents = 3, ++ .parent_data = gcc_xo_gpll0_gpll0_out_main_div2, ++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2), + .ops = &clk_rcg2_ops, + }, + }; +@@ -715,8 +382,8 @@ static struct clk_rcg2 blsp1_qup2_i2c_ap + .parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_qup2_i2c_apps_clk_src", +- .parent_names = gcc_xo_gpll0_gpll0_out_main_div2, +- .num_parents = 3, ++ .parent_data = gcc_xo_gpll0_gpll0_out_main_div2, ++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2), + .ops = &clk_rcg2_ops, + }, + }; +@@ -729,8 +396,8 @@ static struct clk_rcg2 blsp1_qup2_spi_ap + .parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_qup2_spi_apps_clk_src", +- .parent_names = gcc_xo_gpll0_gpll0_out_main_div2, +- .num_parents = 3, ++ .parent_data = gcc_xo_gpll0_gpll0_out_main_div2, ++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2), + .ops = &clk_rcg2_ops, + }, + }; +@@ -742,8 +409,8 @@ static struct clk_rcg2 blsp1_qup3_i2c_ap + .parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_qup3_i2c_apps_clk_src", +- .parent_names = gcc_xo_gpll0_gpll0_out_main_div2, +- .num_parents = 3, ++ .parent_data = gcc_xo_gpll0_gpll0_out_main_div2, ++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2), + .ops = &clk_rcg2_ops, + }, + }; +@@ -756,8 +423,8 @@ static struct clk_rcg2 blsp1_qup3_spi_ap + .parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_qup3_spi_apps_clk_src", +- .parent_names = gcc_xo_gpll0_gpll0_out_main_div2, +- .num_parents = 3, ++ .parent_data = gcc_xo_gpll0_gpll0_out_main_div2, ++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2), + .ops = &clk_rcg2_ops, + }, + }; +@@ -769,8 +436,8 @@ static struct clk_rcg2 blsp1_qup4_i2c_ap + .parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_qup4_i2c_apps_clk_src", +- .parent_names = gcc_xo_gpll0_gpll0_out_main_div2, +- .num_parents = 3, ++ .parent_data = gcc_xo_gpll0_gpll0_out_main_div2, ++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2), + .ops = &clk_rcg2_ops, + }, + }; +@@ -783,8 +450,8 @@ static struct clk_rcg2 blsp1_qup4_spi_ap + .parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_qup4_spi_apps_clk_src", +- .parent_names = gcc_xo_gpll0_gpll0_out_main_div2, +- .num_parents = 3, ++ .parent_data = gcc_xo_gpll0_gpll0_out_main_div2, ++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2), + .ops = &clk_rcg2_ops, + }, + }; +@@ -796,8 +463,8 @@ static struct clk_rcg2 blsp1_qup5_i2c_ap + .parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_qup5_i2c_apps_clk_src", +- .parent_names = gcc_xo_gpll0_gpll0_out_main_div2, +- .num_parents = 3, ++ .parent_data = gcc_xo_gpll0_gpll0_out_main_div2, ++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2), + .ops = &clk_rcg2_ops, + }, + }; +@@ -810,8 +477,8 @@ static struct clk_rcg2 blsp1_qup5_spi_ap + .parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_qup5_spi_apps_clk_src", +- .parent_names = gcc_xo_gpll0_gpll0_out_main_div2, +- .num_parents = 3, ++ .parent_data = gcc_xo_gpll0_gpll0_out_main_div2, ++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2), + .ops = &clk_rcg2_ops, + }, + }; +@@ -823,8 +490,8 @@ static struct clk_rcg2 blsp1_qup6_i2c_ap + .parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_qup6_i2c_apps_clk_src", +- .parent_names = gcc_xo_gpll0_gpll0_out_main_div2, +- .num_parents = 3, ++ .parent_data = gcc_xo_gpll0_gpll0_out_main_div2, ++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2), + .ops = &clk_rcg2_ops, + }, + }; +@@ -837,8 +504,8 @@ static struct clk_rcg2 blsp1_qup6_spi_ap + .parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_qup6_spi_apps_clk_src", +- .parent_names = gcc_xo_gpll0_gpll0_out_main_div2, +- .num_parents = 3, ++ .parent_data = gcc_xo_gpll0_gpll0_out_main_div2, ++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2), + .ops = &clk_rcg2_ops, + }, + }; +@@ -871,8 +538,8 @@ static struct clk_rcg2 blsp1_uart1_apps_ + .parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_uart1_apps_clk_src", +- .parent_names = gcc_xo_gpll0_gpll0_out_main_div2, +- .num_parents = 3, ++ .parent_data = gcc_xo_gpll0_gpll0_out_main_div2, ++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2), + .ops = &clk_rcg2_ops, + }, + }; +@@ -885,8 +552,8 @@ static struct clk_rcg2 blsp1_uart2_apps_ + .parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_uart2_apps_clk_src", +- .parent_names = gcc_xo_gpll0_gpll0_out_main_div2, +- .num_parents = 3, ++ .parent_data = gcc_xo_gpll0_gpll0_out_main_div2, ++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2), + .ops = &clk_rcg2_ops, + }, + }; +@@ -899,8 +566,8 @@ static struct clk_rcg2 blsp1_uart3_apps_ + .parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_uart3_apps_clk_src", +- .parent_names = gcc_xo_gpll0_gpll0_out_main_div2, +- .num_parents = 3, ++ .parent_data = gcc_xo_gpll0_gpll0_out_main_div2, ++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2), + .ops = &clk_rcg2_ops, + }, + }; +@@ -913,8 +580,8 @@ static struct clk_rcg2 blsp1_uart4_apps_ + .parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_uart4_apps_clk_src", +- .parent_names = gcc_xo_gpll0_gpll0_out_main_div2, +- .num_parents = 3, ++ .parent_data = gcc_xo_gpll0_gpll0_out_main_div2, ++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2), + .ops = &clk_rcg2_ops, + }, + }; +@@ -927,8 +594,8 @@ static struct clk_rcg2 blsp1_uart5_apps_ + .parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_uart5_apps_clk_src", +- .parent_names = gcc_xo_gpll0_gpll0_out_main_div2, +- .num_parents = 3, ++ .parent_data = gcc_xo_gpll0_gpll0_out_main_div2, ++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2), + .ops = &clk_rcg2_ops, + }, + }; +@@ -941,8 +608,8 @@ static struct clk_rcg2 blsp1_uart6_apps_ + .parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_uart6_apps_clk_src", +- .parent_names = gcc_xo_gpll0_gpll0_out_main_div2, +- .num_parents = 3, ++ .parent_data = gcc_xo_gpll0_gpll0_out_main_div2, ++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2), + .ops = &clk_rcg2_ops, + }, + }; +@@ -952,6 +619,11 @@ static const struct clk_parent_data gcc_ + { .hw = &gpll0.clkr.hw }, + }; + ++static const struct parent_map gcc_xo_gpll0_map[] = { ++ { P_XO, 0 }, ++ { P_GPLL0, 1 }, ++}; ++ + static const struct freq_tbl ftbl_pcie_axi_clk_src[] = { + F(19200000, P_XO, 1, 0, 0), + F(200000000, P_GPLL0, 4, 0, 0), +@@ -966,7 +638,7 @@ static struct clk_rcg2 pcie0_axi_clk_src + .clkr.hw.init = &(struct clk_init_data){ + .name = "pcie0_axi_clk_src", + .parent_data = gcc_xo_gpll0, +- .num_parents = 2, ++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0), + .ops = &clk_rcg2_ops, + }, + }; +@@ -975,6 +647,18 @@ static const struct freq_tbl ftbl_pcie_a + F(19200000, P_XO, 1, 0, 0), + }; + ++static const struct clk_parent_data gcc_xo_gpll0_sleep_clk[] = { ++ { .fw_name = "xo", .name = "xo" }, ++ { .hw = &gpll0.clkr.hw }, ++ { .fw_name = "sleep_clk", .name = "sleep_clk" }, ++}; ++ ++static const struct parent_map gcc_xo_gpll0_sleep_clk_map[] = { ++ { P_XO, 0 }, ++ { P_GPLL0, 2 }, ++ { P_SLEEP_CLK, 6 }, ++}; ++ + static struct clk_rcg2 pcie0_aux_clk_src = { + .cmd_rcgr = 0x75024, + .freq_tbl = ftbl_pcie_aux_clk_src, +@@ -983,12 +667,22 @@ static struct clk_rcg2 pcie0_aux_clk_src + .parent_map = gcc_xo_gpll0_sleep_clk_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "pcie0_aux_clk_src", +- .parent_names = gcc_xo_gpll0_sleep_clk, +- .num_parents = 3, ++ .parent_data = gcc_xo_gpll0_sleep_clk, ++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_sleep_clk), + .ops = &clk_rcg2_ops, + }, + }; + ++static const struct clk_parent_data gcc_pcie20_phy0_pipe_clk_xo[] = { ++ { .name = "pcie20_phy0_pipe_clk" }, ++ { .fw_name = "xo", .name = "xo" }, ++}; ++ ++static const struct parent_map gcc_pcie20_phy0_pipe_clk_xo_map[] = { ++ { P_PCIE20_PHY0_PIPE, 0 }, ++ { P_XO, 2 }, ++}; ++ + static struct clk_regmap_mux pcie0_pipe_clk_src = { + .reg = 0x7501c, + .shift = 8, +@@ -997,8 +691,8 @@ static struct clk_regmap_mux pcie0_pipe_ + .clkr = { + .hw.init = &(struct clk_init_data){ + .name = "pcie0_pipe_clk_src", +- .parent_names = gcc_pcie20_phy0_pipe_clk_xo, +- .num_parents = 2, ++ .parent_data = gcc_pcie20_phy0_pipe_clk_xo, ++ .num_parents = ARRAY_SIZE(gcc_pcie20_phy0_pipe_clk_xo), + .ops = &clk_regmap_mux_closest_ops, + .flags = CLK_SET_RATE_PARENT, + }, +@@ -1013,7 +707,7 @@ static struct clk_rcg2 pcie1_axi_clk_src + .clkr.hw.init = &(struct clk_init_data){ + .name = "pcie1_axi_clk_src", + .parent_data = gcc_xo_gpll0, +- .num_parents = 2, ++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0), + .ops = &clk_rcg2_ops, + }, + }; +@@ -1026,12 +720,22 @@ static struct clk_rcg2 pcie1_aux_clk_src + .parent_map = gcc_xo_gpll0_sleep_clk_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "pcie1_aux_clk_src", +- .parent_names = gcc_xo_gpll0_sleep_clk, +- .num_parents = 3, ++ .parent_data = gcc_xo_gpll0_sleep_clk, ++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_sleep_clk), + .ops = &clk_rcg2_ops, + }, + }; + ++static const struct clk_parent_data gcc_pcie20_phy1_pipe_clk_xo[] = { ++ { .name = "pcie20_phy1_pipe_clk" }, ++ { .fw_name = "xo", .name = "xo" }, ++}; ++ ++static const struct parent_map gcc_pcie20_phy1_pipe_clk_xo_map[] = { ++ { P_PCIE20_PHY1_PIPE, 0 }, ++ { P_XO, 2 }, ++}; ++ + static struct clk_regmap_mux pcie1_pipe_clk_src = { + .reg = 0x7601c, + .shift = 8, +@@ -1040,8 +744,8 @@ static struct clk_regmap_mux pcie1_pipe_ + .clkr = { + .hw.init = &(struct clk_init_data){ + .name = "pcie1_pipe_clk_src", +- .parent_names = gcc_pcie20_phy1_pipe_clk_xo, +- .num_parents = 2, ++ .parent_data = gcc_pcie20_phy1_pipe_clk_xo, ++ .num_parents = ARRAY_SIZE(gcc_pcie20_phy1_pipe_clk_xo), + .ops = &clk_regmap_mux_closest_ops, + .flags = CLK_SET_RATE_PARENT, + }, +@@ -1060,6 +764,20 @@ static const struct freq_tbl ftbl_sdcc_a + { } + }; + ++static const struct clk_parent_data gcc_xo_gpll0_gpll2_gpll0_out_main_div2[] = { ++ { .fw_name = "xo", .name = "xo" }, ++ { .hw = &gpll0.clkr.hw }, ++ { .hw = &gpll2.clkr.hw }, ++ { .hw = &gpll0_out_main_div2.hw }, ++}; ++ ++static const struct parent_map gcc_xo_gpll0_gpll2_gpll0_out_main_div2_map[] = { ++ { P_XO, 0 }, ++ { P_GPLL0, 1 }, ++ { P_GPLL2, 2 }, ++ { P_GPLL0_DIV2, 4 }, ++}; ++ + static struct clk_rcg2 sdcc1_apps_clk_src = { + .cmd_rcgr = 0x42004, + .freq_tbl = ftbl_sdcc_apps_clk_src, +@@ -1068,8 +786,8 @@ static struct clk_rcg2 sdcc1_apps_clk_sr + .parent_map = gcc_xo_gpll0_gpll2_gpll0_out_main_div2_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "sdcc1_apps_clk_src", +- .parent_names = gcc_xo_gpll0_gpll2_gpll0_out_main_div2, +- .num_parents = 4, ++ .parent_data = gcc_xo_gpll0_gpll2_gpll0_out_main_div2, ++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll2_gpll0_out_main_div2), + .ops = &clk_rcg2_floor_ops, + }, + }; +@@ -1080,6 +798,20 @@ static const struct freq_tbl ftbl_sdcc_i + F(308570000, P_GPLL6, 3.5, 0, 0), + }; + ++static const struct clk_parent_data gcc_xo_gpll0_gpll6_gpll0_div2[] = { ++ { .fw_name = "xo", .name = "xo" }, ++ { .hw = &gpll0.clkr.hw }, ++ { .hw = &gpll6.clkr.hw }, ++ { .hw = &gpll0_out_main_div2.hw }, ++}; ++ ++static const struct parent_map gcc_xo_gpll0_gpll6_gpll0_div2_map[] = { ++ { P_XO, 0 }, ++ { P_GPLL0, 1 }, ++ { P_GPLL6, 2 }, ++ { P_GPLL0_DIV2, 4 }, ++}; ++ + static struct clk_rcg2 sdcc1_ice_core_clk_src = { + .cmd_rcgr = 0x5d000, + .freq_tbl = ftbl_sdcc_ice_core_clk_src, +@@ -1088,8 +820,8 @@ static struct clk_rcg2 sdcc1_ice_core_cl + .parent_map = gcc_xo_gpll0_gpll6_gpll0_div2_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "sdcc1_ice_core_clk_src", +- .parent_names = gcc_xo_gpll0_gpll6_gpll0_div2, +- .num_parents = 4, ++ .parent_data = gcc_xo_gpll0_gpll6_gpll0_div2, ++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll6_gpll0_div2), + .ops = &clk_rcg2_ops, + }, + }; +@@ -1102,8 +834,8 @@ static struct clk_rcg2 sdcc2_apps_clk_sr + .parent_map = gcc_xo_gpll0_gpll2_gpll0_out_main_div2_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "sdcc2_apps_clk_src", +- .parent_names = gcc_xo_gpll0_gpll2_gpll0_out_main_div2, +- .num_parents = 4, ++ .parent_data = gcc_xo_gpll0_gpll2_gpll0_out_main_div2, ++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll2_gpll0_out_main_div2), + .ops = &clk_rcg2_floor_ops, + }, + }; +@@ -1115,6 +847,18 @@ static const struct freq_tbl ftbl_usb_ma + { } + }; + ++static const struct clk_parent_data gcc_xo_gpll0_out_main_div2_gpll0[] = { ++ { .fw_name = "xo", .name = "xo" }, ++ { .hw = &gpll0_out_main_div2.hw }, ++ { .hw = &gpll0.clkr.hw }, ++}; ++ ++static const struct parent_map gcc_xo_gpll0_out_main_div2_gpll0_map[] = { ++ { P_XO, 0 }, ++ { P_GPLL0_DIV2, 2 }, ++ { P_GPLL0, 1 }, ++}; ++ + static struct clk_rcg2 usb0_master_clk_src = { + .cmd_rcgr = 0x3e00c, + .freq_tbl = ftbl_usb_master_clk_src, +@@ -1123,8 +867,8 @@ static struct clk_rcg2 usb0_master_clk_s + .parent_map = gcc_xo_gpll0_out_main_div2_gpll0_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "usb0_master_clk_src", +- .parent_names = gcc_xo_gpll0_out_main_div2_gpll0, +- .num_parents = 3, ++ .parent_data = gcc_xo_gpll0_out_main_div2_gpll0, ++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_out_main_div2_gpll0), + .ops = &clk_rcg2_ops, + }, + }; +@@ -1142,8 +886,8 @@ static struct clk_rcg2 usb0_aux_clk_src + .parent_map = gcc_xo_gpll0_sleep_clk_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "usb0_aux_clk_src", +- .parent_names = gcc_xo_gpll0_sleep_clk, +- .num_parents = 3, ++ .parent_data = gcc_xo_gpll0_sleep_clk, ++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_sleep_clk), + .ops = &clk_rcg2_ops, + }, + }; +@@ -1155,6 +899,20 @@ static const struct freq_tbl ftbl_usb_mo + { } + }; + ++static const struct clk_parent_data gcc_xo_gpll6_gpll0_gpll0_out_main_div2[] = { ++ { .fw_name = "xo", .name = "xo" }, ++ { .hw = &gpll6.clkr.hw }, ++ { .hw = &gpll0.clkr.hw }, ++ { .hw = &gpll0_out_main_div2.hw }, ++}; ++ ++static const struct parent_map gcc_xo_gpll6_gpll0_gpll0_out_main_div2_map[] = { ++ { P_XO, 0 }, ++ { P_GPLL6, 1 }, ++ { P_GPLL0, 3 }, ++ { P_GPLL0_DIV2, 4 }, ++}; ++ + static struct clk_rcg2 usb0_mock_utmi_clk_src = { + .cmd_rcgr = 0x3e020, + .freq_tbl = ftbl_usb_mock_utmi_clk_src, +@@ -1163,12 +921,22 @@ static struct clk_rcg2 usb0_mock_utmi_cl + .parent_map = gcc_xo_gpll6_gpll0_gpll0_out_main_div2_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "usb0_mock_utmi_clk_src", +- .parent_names = gcc_xo_gpll6_gpll0_gpll0_out_main_div2, +- .num_parents = 4, ++ .parent_data = gcc_xo_gpll6_gpll0_gpll0_out_main_div2, ++ .num_parents = ARRAY_SIZE(gcc_xo_gpll6_gpll0_gpll0_out_main_div2), + .ops = &clk_rcg2_ops, + }, + }; + ++static const struct clk_parent_data gcc_usb3phy_0_cc_pipe_clk_xo[] = { ++ { .name = "usb3phy_0_cc_pipe_clk" }, ++ { .fw_name = "xo", .name = "xo" }, ++}; ++ ++static const struct parent_map gcc_usb3phy_0_cc_pipe_clk_xo_map[] = { ++ { P_USB3PHY_0_PIPE, 0 }, ++ { P_XO, 2 }, ++}; ++ + static struct clk_regmap_mux usb0_pipe_clk_src = { + .reg = 0x3e048, + .shift = 8, +@@ -1177,8 +945,8 @@ static struct clk_regmap_mux usb0_pipe_c + .clkr = { + .hw.init = &(struct clk_init_data){ + .name = "usb0_pipe_clk_src", +- .parent_names = gcc_usb3phy_0_cc_pipe_clk_xo, +- .num_parents = 2, ++ .parent_data = gcc_usb3phy_0_cc_pipe_clk_xo, ++ .num_parents = ARRAY_SIZE(gcc_usb3phy_0_cc_pipe_clk_xo), + .ops = &clk_regmap_mux_closest_ops, + .flags = CLK_SET_RATE_PARENT, + }, +@@ -1193,8 +961,8 @@ static struct clk_rcg2 usb1_master_clk_s + .parent_map = gcc_xo_gpll0_out_main_div2_gpll0_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "usb1_master_clk_src", +- .parent_names = gcc_xo_gpll0_out_main_div2_gpll0, +- .num_parents = 3, ++ .parent_data = gcc_xo_gpll0_out_main_div2_gpll0, ++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_out_main_div2_gpll0), + .ops = &clk_rcg2_ops, + }, + }; +@@ -1207,8 +975,8 @@ static struct clk_rcg2 usb1_aux_clk_src + .parent_map = gcc_xo_gpll0_sleep_clk_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "usb1_aux_clk_src", +- .parent_names = gcc_xo_gpll0_sleep_clk, +- .num_parents = 3, ++ .parent_data = gcc_xo_gpll0_sleep_clk, ++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_sleep_clk), + .ops = &clk_rcg2_ops, + }, + }; +@@ -1221,12 +989,22 @@ static struct clk_rcg2 usb1_mock_utmi_cl + .parent_map = gcc_xo_gpll6_gpll0_gpll0_out_main_div2_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "usb1_mock_utmi_clk_src", +- .parent_names = gcc_xo_gpll6_gpll0_gpll0_out_main_div2, +- .num_parents = 4, ++ .parent_data = gcc_xo_gpll6_gpll0_gpll0_out_main_div2, ++ .num_parents = ARRAY_SIZE(gcc_xo_gpll6_gpll0_gpll0_out_main_div2), + .ops = &clk_rcg2_ops, + }, + }; + ++static const struct clk_parent_data gcc_usb3phy_1_cc_pipe_clk_xo[] = { ++ { .name = "usb3phy_1_cc_pipe_clk" }, ++ { .fw_name = "xo", .name = "xo" }, ++}; ++ ++static const struct parent_map gcc_usb3phy_1_cc_pipe_clk_xo_map[] = { ++ { P_USB3PHY_1_PIPE, 0 }, ++ { P_XO, 2 }, ++}; ++ + static struct clk_regmap_mux usb1_pipe_clk_src = { + .reg = 0x3f048, + .shift = 8, +@@ -1235,8 +1013,8 @@ static struct clk_regmap_mux usb1_pipe_c + .clkr = { + .hw.init = &(struct clk_init_data){ + .name = "usb1_pipe_clk_src", +- .parent_names = gcc_usb3phy_1_cc_pipe_clk_xo, +- .num_parents = 2, ++ .parent_data = gcc_usb3phy_1_cc_pipe_clk_xo, ++ .num_parents = ARRAY_SIZE(gcc_usb3phy_1_cc_pipe_clk_xo), + .ops = &clk_regmap_mux_closest_ops, + .flags = CLK_SET_RATE_PARENT, + }, +@@ -1250,8 +1028,9 @@ static struct clk_branch gcc_xo_clk_src + .enable_mask = BIT(1), + .hw.init = &(struct clk_init_data){ + .name = "gcc_xo_clk_src", +- .parent_names = (const char *[]){ +- "xo" ++ .parent_data = &(const struct clk_parent_data){ ++ .fw_name = "xo", ++ .name = "xo", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, +@@ -1265,9 +1044,8 @@ static struct clk_fixed_factor gcc_xo_di + .div = 4, + .hw.init = &(struct clk_init_data){ + .name = "gcc_xo_div4_clk_src", +- .parent_names = (const char *[]){ +- "gcc_xo_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &gcc_xo_clk_src.clkr.hw }, + .num_parents = 1, + .ops = &clk_fixed_factor_ops, + .flags = CLK_SET_RATE_PARENT, +@@ -1285,6 +1063,20 @@ static const struct freq_tbl ftbl_system + { } + }; + ++static const struct clk_parent_data gcc_xo_gpll0_gpll6_gpll0_out_main_div2[] = { ++ { .fw_name = "xo", .name = "xo" }, ++ { .hw = &gpll0.clkr.hw }, ++ { .hw = &gpll6.clkr.hw }, ++ { .hw = &gpll0_out_main_div2.hw }, ++}; ++ ++static const struct parent_map gcc_xo_gpll0_gpll6_gpll0_out_main_div2_map[] = { ++ { P_XO, 0 }, ++ { P_GPLL0, 1 }, ++ { P_GPLL6, 2 }, ++ { P_GPLL0_DIV2, 3 }, ++}; ++ + static struct clk_rcg2 system_noc_bfdcd_clk_src = { + .cmd_rcgr = 0x26004, + .freq_tbl = ftbl_system_noc_bfdcd_clk_src, +@@ -1292,8 +1084,8 @@ static struct clk_rcg2 system_noc_bfdcd_ + .parent_map = gcc_xo_gpll0_gpll6_gpll0_out_main_div2_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "system_noc_bfdcd_clk_src", +- .parent_names = gcc_xo_gpll0_gpll6_gpll0_out_main_div2, +- .num_parents = 4, ++ .parent_data = gcc_xo_gpll0_gpll6_gpll0_out_main_div2, ++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll6_gpll0_out_main_div2), + .ops = &clk_rcg2_ops, + .flags = CLK_IS_CRITICAL, + }, +@@ -1304,9 +1096,8 @@ static struct clk_fixed_factor system_no + .div = 1, + .hw.init = &(struct clk_init_data){ + .name = "system_noc_clk_src", +- .parent_names = (const char *[]){ +- "system_noc_bfdcd_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &system_noc_bfdcd_clk_src.clkr.hw }, + .num_parents = 1, + .ops = &clk_fixed_factor_ops, + .flags = CLK_SET_RATE_PARENT, +@@ -1327,7 +1118,7 @@ static struct clk_rcg2 nss_ce_clk_src = + .clkr.hw.init = &(struct clk_init_data){ + .name = "nss_ce_clk_src", + .parent_data = gcc_xo_gpll0, +- .num_parents = 2, ++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0), + .ops = &clk_rcg2_ops, + }, + }; +@@ -1338,6 +1129,20 @@ static const struct freq_tbl ftbl_nss_no + { } + }; + ++static const struct clk_parent_data gcc_xo_bias_pll_nss_noc_clk_gpll0_gpll2[] = { ++ { .fw_name = "xo", .name = "xo" }, ++ { .name = "bias_pll_nss_noc_clk" }, ++ { .hw = &gpll0.clkr.hw }, ++ { .hw = &gpll2.clkr.hw }, ++}; ++ ++static const struct parent_map gcc_xo_bias_pll_nss_noc_clk_gpll0_gpll2_map[] = { ++ { P_XO, 0 }, ++ { P_BIAS_PLL_NSS_NOC, 1 }, ++ { P_GPLL0, 2 }, ++ { P_GPLL2, 3 }, ++}; ++ + static struct clk_rcg2 nss_noc_bfdcd_clk_src = { + .cmd_rcgr = 0x68088, + .freq_tbl = ftbl_nss_noc_bfdcd_clk_src, +@@ -1345,8 +1150,8 @@ static struct clk_rcg2 nss_noc_bfdcd_clk + .parent_map = gcc_xo_bias_pll_nss_noc_clk_gpll0_gpll2_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "nss_noc_bfdcd_clk_src", +- .parent_names = gcc_xo_bias_pll_nss_noc_clk_gpll0_gpll2, +- .num_parents = 4, ++ .parent_data = gcc_xo_bias_pll_nss_noc_clk_gpll0_gpll2, ++ .num_parents = ARRAY_SIZE(gcc_xo_bias_pll_nss_noc_clk_gpll0_gpll2), + .ops = &clk_rcg2_ops, + }, + }; +@@ -1356,9 +1161,8 @@ static struct clk_fixed_factor nss_noc_c + .div = 1, + .hw.init = &(struct clk_init_data){ + .name = "nss_noc_clk_src", +- .parent_names = (const char *[]){ +- "nss_noc_bfdcd_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_noc_bfdcd_clk_src.clkr.hw }, + .num_parents = 1, + .ops = &clk_fixed_factor_ops, + .flags = CLK_SET_RATE_PARENT, +@@ -1371,6 +1175,18 @@ static const struct freq_tbl ftbl_nss_cr + { } + }; + ++static const struct clk_parent_data gcc_xo_nss_crypto_pll_gpll0[] = { ++ { .fw_name = "xo", .name = "xo" }, ++ { .hw = &nss_crypto_pll.clkr.hw }, ++ { .hw = &gpll0.clkr.hw }, ++}; ++ ++static const struct parent_map gcc_xo_nss_crypto_pll_gpll0_map[] = { ++ { P_XO, 0 }, ++ { P_NSS_CRYPTO_PLL, 1 }, ++ { P_GPLL0, 2 }, ++}; ++ + static struct clk_rcg2 nss_crypto_clk_src = { + .cmd_rcgr = 0x68144, + .freq_tbl = ftbl_nss_crypto_clk_src, +@@ -1379,8 +1195,8 @@ static struct clk_rcg2 nss_crypto_clk_sr + .parent_map = gcc_xo_nss_crypto_pll_gpll0_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "nss_crypto_clk_src", +- .parent_names = gcc_xo_nss_crypto_pll_gpll0, +- .num_parents = 3, ++ .parent_data = gcc_xo_nss_crypto_pll_gpll0, ++ .num_parents = ARRAY_SIZE(gcc_xo_nss_crypto_pll_gpll0), + .ops = &clk_rcg2_ops, + }, + }; +@@ -1394,6 +1210,24 @@ static const struct freq_tbl ftbl_nss_ub + { } + }; + ++static const struct clk_parent_data gcc_xo_ubi32_pll_gpll0_gpll2_gpll4_gpll6[] = { ++ { .fw_name = "xo", .name = "xo" }, ++ { .hw = &ubi32_pll.clkr.hw }, ++ { .hw = &gpll0.clkr.hw }, ++ { .hw = &gpll2.clkr.hw }, ++ { .hw = &gpll4.clkr.hw }, ++ { .hw = &gpll6.clkr.hw }, ++}; ++ ++static const struct parent_map gcc_xo_ubi32_gpll0_gpll2_gpll4_gpll6_map[] = { ++ { P_XO, 0 }, ++ { P_UBI32_PLL, 1 }, ++ { P_GPLL0, 2 }, ++ { P_GPLL2, 3 }, ++ { P_GPLL4, 4 }, ++ { P_GPLL6, 5 }, ++}; ++ + static struct clk_rcg2 nss_ubi0_clk_src = { + .cmd_rcgr = 0x68104, + .freq_tbl = ftbl_nss_ubi_clk_src, +@@ -1401,8 +1235,8 @@ static struct clk_rcg2 nss_ubi0_clk_src + .parent_map = gcc_xo_ubi32_gpll0_gpll2_gpll4_gpll6_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "nss_ubi0_clk_src", +- .parent_names = gcc_xo_ubi32_pll_gpll0_gpll2_gpll4_gpll6, +- .num_parents = 6, ++ .parent_data = gcc_xo_ubi32_pll_gpll0_gpll2_gpll4_gpll6, ++ .num_parents = ARRAY_SIZE(gcc_xo_ubi32_pll_gpll0_gpll2_gpll4_gpll6), + .ops = &clk_rcg2_ops, + .flags = CLK_SET_RATE_PARENT, + }, +@@ -1415,9 +1249,8 @@ static struct clk_regmap_div nss_ubi0_di + .clkr = { + .hw.init = &(struct clk_init_data){ + .name = "nss_ubi0_div_clk_src", +- .parent_names = (const char *[]){ +- "nss_ubi0_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_ubi0_clk_src.clkr.hw }, + .num_parents = 1, + .ops = &clk_regmap_div_ro_ops, + .flags = CLK_SET_RATE_PARENT, +@@ -1432,8 +1265,8 @@ static struct clk_rcg2 nss_ubi1_clk_src + .parent_map = gcc_xo_ubi32_gpll0_gpll2_gpll4_gpll6_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "nss_ubi1_clk_src", +- .parent_names = gcc_xo_ubi32_pll_gpll0_gpll2_gpll4_gpll6, +- .num_parents = 6, ++ .parent_data = gcc_xo_ubi32_pll_gpll0_gpll2_gpll4_gpll6, ++ .num_parents = ARRAY_SIZE(gcc_xo_ubi32_pll_gpll0_gpll2_gpll4_gpll6), + .ops = &clk_rcg2_ops, + .flags = CLK_SET_RATE_PARENT, + }, +@@ -1446,9 +1279,8 @@ static struct clk_regmap_div nss_ubi1_di + .clkr = { + .hw.init = &(struct clk_init_data){ + .name = "nss_ubi1_div_clk_src", +- .parent_names = (const char *[]){ +- "nss_ubi1_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_ubi1_clk_src.clkr.hw }, + .num_parents = 1, + .ops = &clk_regmap_div_ro_ops, + .flags = CLK_SET_RATE_PARENT, +@@ -1462,6 +1294,16 @@ static const struct freq_tbl ftbl_ubi_mp + { } + }; + ++static const struct clk_parent_data gcc_xo_gpll0_out_main_div2[] = { ++ { .fw_name = "xo", .name = "xo" }, ++ { .hw = &gpll0_out_main_div2.hw }, ++}; ++ ++static const struct parent_map gcc_xo_gpll0_out_main_div2_map[] = { ++ { P_XO, 0 }, ++ { P_GPLL0_DIV2, 1 }, ++}; ++ + static struct clk_rcg2 ubi_mpt_clk_src = { + .cmd_rcgr = 0x68090, + .freq_tbl = ftbl_ubi_mpt_clk_src, +@@ -1469,8 +1311,8 @@ static struct clk_rcg2 ubi_mpt_clk_src = + .parent_map = gcc_xo_gpll0_out_main_div2_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "ubi_mpt_clk_src", +- .parent_names = gcc_xo_gpll0_out_main_div2, +- .num_parents = 2, ++ .parent_data = gcc_xo_gpll0_out_main_div2, ++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_out_main_div2), + .ops = &clk_rcg2_ops, + }, + }; +@@ -1481,6 +1323,18 @@ static const struct freq_tbl ftbl_nss_im + { } + }; + ++static const struct clk_parent_data gcc_xo_gpll0_gpll4[] = { ++ { .fw_name = "xo", .name = "xo" }, ++ { .hw = &gpll0.clkr.hw }, ++ { .hw = &gpll4.clkr.hw }, ++}; ++ ++static const struct parent_map gcc_xo_gpll0_gpll4_map[] = { ++ { P_XO, 0 }, ++ { P_GPLL0, 1 }, ++ { P_GPLL4, 2 }, ++}; ++ + static struct clk_rcg2 nss_imem_clk_src = { + .cmd_rcgr = 0x68158, + .freq_tbl = ftbl_nss_imem_clk_src, +@@ -1488,8 +1342,8 @@ static struct clk_rcg2 nss_imem_clk_src + .parent_map = gcc_xo_gpll0_gpll4_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "nss_imem_clk_src", +- .parent_names = gcc_xo_gpll0_gpll4, +- .num_parents = 3, ++ .parent_data = gcc_xo_gpll0_gpll4, ++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll4), + .ops = &clk_rcg2_ops, + }, + }; +@@ -1500,6 +1354,24 @@ static const struct freq_tbl ftbl_nss_pp + { } + }; + ++static const struct clk_parent_data gcc_xo_bias_gpll0_gpll4_nss_ubi32[] = { ++ { .fw_name = "xo", .name = "xo" }, ++ { .name = "bias_pll_cc_clk" }, ++ { .hw = &gpll0.clkr.hw }, ++ { .hw = &gpll4.clkr.hw }, ++ { .hw = &nss_crypto_pll.clkr.hw }, ++ { .hw = &ubi32_pll.clkr.hw }, ++}; ++ ++static const struct parent_map gcc_xo_bias_gpll0_gpll4_nss_ubi32_map[] = { ++ { P_XO, 0 }, ++ { P_BIAS_PLL, 1 }, ++ { P_GPLL0, 2 }, ++ { P_GPLL4, 3 }, ++ { P_NSS_CRYPTO_PLL, 4 }, ++ { P_UBI32_PLL, 5 }, ++}; ++ + static struct clk_rcg2 nss_ppe_clk_src = { + .cmd_rcgr = 0x68080, + .freq_tbl = ftbl_nss_ppe_clk_src, +@@ -1507,8 +1379,8 @@ static struct clk_rcg2 nss_ppe_clk_src = + .parent_map = gcc_xo_bias_gpll0_gpll4_nss_ubi32_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "nss_ppe_clk_src", +- .parent_names = gcc_xo_bias_gpll0_gpll4_nss_ubi32, +- .num_parents = 6, ++ .parent_data = gcc_xo_bias_gpll0_gpll4_nss_ubi32, ++ .num_parents = ARRAY_SIZE(gcc_xo_bias_gpll0_gpll4_nss_ubi32), + .ops = &clk_rcg2_ops, + }, + }; +@@ -1518,9 +1390,8 @@ static struct clk_fixed_factor nss_ppe_c + .div = 4, + .hw.init = &(struct clk_init_data){ + .name = "nss_ppe_cdiv_clk_src", +- .parent_names = (const char *[]){ +- "nss_ppe_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_ppe_clk_src.clkr.hw }, + .num_parents = 1, + .ops = &clk_fixed_factor_ops, + .flags = CLK_SET_RATE_PARENT, +@@ -1534,6 +1405,22 @@ static const struct freq_tbl ftbl_nss_po + { } + }; + ++static const struct clk_parent_data gcc_xo_uniphy0_rx_tx_ubi32_bias[] = { ++ { .fw_name = "xo", .name = "xo" }, ++ { .name = "uniphy0_gcc_rx_clk" }, ++ { .name = "uniphy0_gcc_tx_clk" }, ++ { .hw = &ubi32_pll.clkr.hw }, ++ { .name = "bias_pll_cc_clk" }, ++}; ++ ++static const struct parent_map gcc_xo_uniphy0_rx_tx_ubi32_bias_map[] = { ++ { P_XO, 0 }, ++ { P_UNIPHY0_RX, 1 }, ++ { P_UNIPHY0_TX, 2 }, ++ { P_UBI32_PLL, 5 }, ++ { P_BIAS_PLL, 6 }, ++}; ++ + static struct clk_rcg2 nss_port1_rx_clk_src = { + .cmd_rcgr = 0x68020, + .freq_tbl = ftbl_nss_port1_rx_clk_src, +@@ -1541,8 +1428,8 @@ static struct clk_rcg2 nss_port1_rx_clk_ + .parent_map = gcc_xo_uniphy0_rx_tx_ubi32_bias_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "nss_port1_rx_clk_src", +- .parent_names = gcc_xo_uniphy0_rx_tx_ubi32_bias, +- .num_parents = 5, ++ .parent_data = gcc_xo_uniphy0_rx_tx_ubi32_bias, ++ .num_parents = ARRAY_SIZE(gcc_xo_uniphy0_rx_tx_ubi32_bias), + .ops = &clk_rcg2_ops, + }, + }; +@@ -1554,9 +1441,8 @@ static struct clk_regmap_div nss_port1_r + .clkr = { + .hw.init = &(struct clk_init_data){ + .name = "nss_port1_rx_div_clk_src", +- .parent_names = (const char *[]){ +- "nss_port1_rx_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_port1_rx_clk_src.clkr.hw }, + .num_parents = 1, + .ops = &clk_regmap_div_ops, + .flags = CLK_SET_RATE_PARENT, +@@ -1571,6 +1457,22 @@ static const struct freq_tbl ftbl_nss_po + { } + }; + ++static const struct clk_parent_data gcc_xo_uniphy0_tx_rx_ubi32_bias[] = { ++ { .fw_name = "xo", .name = "xo" }, ++ { .name = "uniphy0_gcc_tx_clk" }, ++ { .name = "uniphy0_gcc_rx_clk" }, ++ { .hw = &ubi32_pll.clkr.hw }, ++ { .name = "bias_pll_cc_clk" }, ++}; ++ ++static const struct parent_map gcc_xo_uniphy0_tx_rx_ubi32_bias_map[] = { ++ { P_XO, 0 }, ++ { P_UNIPHY0_TX, 1 }, ++ { P_UNIPHY0_RX, 2 }, ++ { P_UBI32_PLL, 5 }, ++ { P_BIAS_PLL, 6 }, ++}; ++ + static struct clk_rcg2 nss_port1_tx_clk_src = { + .cmd_rcgr = 0x68028, + .freq_tbl = ftbl_nss_port1_tx_clk_src, +@@ -1578,8 +1480,8 @@ static struct clk_rcg2 nss_port1_tx_clk_ + .parent_map = gcc_xo_uniphy0_tx_rx_ubi32_bias_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "nss_port1_tx_clk_src", +- .parent_names = gcc_xo_uniphy0_tx_rx_ubi32_bias, +- .num_parents = 5, ++ .parent_data = gcc_xo_uniphy0_tx_rx_ubi32_bias, ++ .num_parents = ARRAY_SIZE(gcc_xo_uniphy0_tx_rx_ubi32_bias), + .ops = &clk_rcg2_ops, + }, + }; +@@ -1591,9 +1493,8 @@ static struct clk_regmap_div nss_port1_t + .clkr = { + .hw.init = &(struct clk_init_data){ + .name = "nss_port1_tx_div_clk_src", +- .parent_names = (const char *[]){ +- "nss_port1_tx_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_port1_tx_clk_src.clkr.hw }, + .num_parents = 1, + .ops = &clk_regmap_div_ops, + .flags = CLK_SET_RATE_PARENT, +@@ -1608,8 +1509,8 @@ static struct clk_rcg2 nss_port2_rx_clk_ + .parent_map = gcc_xo_uniphy0_rx_tx_ubi32_bias_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "nss_port2_rx_clk_src", +- .parent_names = gcc_xo_uniphy0_rx_tx_ubi32_bias, +- .num_parents = 5, ++ .parent_data = gcc_xo_uniphy0_rx_tx_ubi32_bias, ++ .num_parents = ARRAY_SIZE(gcc_xo_uniphy0_rx_tx_ubi32_bias), + .ops = &clk_rcg2_ops, + }, + }; +@@ -1621,9 +1522,8 @@ static struct clk_regmap_div nss_port2_r + .clkr = { + .hw.init = &(struct clk_init_data){ + .name = "nss_port2_rx_div_clk_src", +- .parent_names = (const char *[]){ +- "nss_port2_rx_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_port2_rx_clk_src.clkr.hw }, + .num_parents = 1, + .ops = &clk_regmap_div_ops, + .flags = CLK_SET_RATE_PARENT, +@@ -1638,8 +1538,8 @@ static struct clk_rcg2 nss_port2_tx_clk_ + .parent_map = gcc_xo_uniphy0_tx_rx_ubi32_bias_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "nss_port2_tx_clk_src", +- .parent_names = gcc_xo_uniphy0_tx_rx_ubi32_bias, +- .num_parents = 5, ++ .parent_data = gcc_xo_uniphy0_tx_rx_ubi32_bias, ++ .num_parents = ARRAY_SIZE(gcc_xo_uniphy0_tx_rx_ubi32_bias), + .ops = &clk_rcg2_ops, + }, + }; +@@ -1651,9 +1551,8 @@ static struct clk_regmap_div nss_port2_t + .clkr = { + .hw.init = &(struct clk_init_data){ + .name = "nss_port2_tx_div_clk_src", +- .parent_names = (const char *[]){ +- "nss_port2_tx_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_port2_tx_clk_src.clkr.hw }, + .num_parents = 1, + .ops = &clk_regmap_div_ops, + .flags = CLK_SET_RATE_PARENT, +@@ -1668,8 +1567,8 @@ static struct clk_rcg2 nss_port3_rx_clk_ + .parent_map = gcc_xo_uniphy0_rx_tx_ubi32_bias_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "nss_port3_rx_clk_src", +- .parent_names = gcc_xo_uniphy0_rx_tx_ubi32_bias, +- .num_parents = 5, ++ .parent_data = gcc_xo_uniphy0_rx_tx_ubi32_bias, ++ .num_parents = ARRAY_SIZE(gcc_xo_uniphy0_rx_tx_ubi32_bias), + .ops = &clk_rcg2_ops, + }, + }; +@@ -1681,9 +1580,8 @@ static struct clk_regmap_div nss_port3_r + .clkr = { + .hw.init = &(struct clk_init_data){ + .name = "nss_port3_rx_div_clk_src", +- .parent_names = (const char *[]){ +- "nss_port3_rx_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_port3_rx_clk_src.clkr.hw }, + .num_parents = 1, + .ops = &clk_regmap_div_ops, + .flags = CLK_SET_RATE_PARENT, +@@ -1698,8 +1596,8 @@ static struct clk_rcg2 nss_port3_tx_clk_ + .parent_map = gcc_xo_uniphy0_tx_rx_ubi32_bias_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "nss_port3_tx_clk_src", +- .parent_names = gcc_xo_uniphy0_tx_rx_ubi32_bias, +- .num_parents = 5, ++ .parent_data = gcc_xo_uniphy0_tx_rx_ubi32_bias, ++ .num_parents = ARRAY_SIZE(gcc_xo_uniphy0_tx_rx_ubi32_bias), + .ops = &clk_rcg2_ops, + }, + }; +@@ -1711,9 +1609,8 @@ static struct clk_regmap_div nss_port3_t + .clkr = { + .hw.init = &(struct clk_init_data){ + .name = "nss_port3_tx_div_clk_src", +- .parent_names = (const char *[]){ +- "nss_port3_tx_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_port3_tx_clk_src.clkr.hw }, + .num_parents = 1, + .ops = &clk_regmap_div_ops, + .flags = CLK_SET_RATE_PARENT, +@@ -1728,8 +1625,8 @@ static struct clk_rcg2 nss_port4_rx_clk_ + .parent_map = gcc_xo_uniphy0_rx_tx_ubi32_bias_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "nss_port4_rx_clk_src", +- .parent_names = gcc_xo_uniphy0_rx_tx_ubi32_bias, +- .num_parents = 5, ++ .parent_data = gcc_xo_uniphy0_rx_tx_ubi32_bias, ++ .num_parents = ARRAY_SIZE(gcc_xo_uniphy0_rx_tx_ubi32_bias), + .ops = &clk_rcg2_ops, + }, + }; +@@ -1741,9 +1638,8 @@ static struct clk_regmap_div nss_port4_r + .clkr = { + .hw.init = &(struct clk_init_data){ + .name = "nss_port4_rx_div_clk_src", +- .parent_names = (const char *[]){ +- "nss_port4_rx_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_port4_rx_clk_src.clkr.hw }, + .num_parents = 1, + .ops = &clk_regmap_div_ops, + .flags = CLK_SET_RATE_PARENT, +@@ -1758,8 +1654,8 @@ static struct clk_rcg2 nss_port4_tx_clk_ + .parent_map = gcc_xo_uniphy0_tx_rx_ubi32_bias_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "nss_port4_tx_clk_src", +- .parent_names = gcc_xo_uniphy0_tx_rx_ubi32_bias, +- .num_parents = 5, ++ .parent_data = gcc_xo_uniphy0_tx_rx_ubi32_bias, ++ .num_parents = ARRAY_SIZE(gcc_xo_uniphy0_tx_rx_ubi32_bias), + .ops = &clk_rcg2_ops, + }, + }; +@@ -1771,9 +1667,8 @@ static struct clk_regmap_div nss_port4_t + .clkr = { + .hw.init = &(struct clk_init_data){ + .name = "nss_port4_tx_div_clk_src", +- .parent_names = (const char *[]){ +- "nss_port4_tx_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_port4_tx_clk_src.clkr.hw }, + .num_parents = 1, + .ops = &clk_regmap_div_ops, + .flags = CLK_SET_RATE_PARENT, +@@ -1793,6 +1688,27 @@ 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", .name = "xo" }, ++ { .name = "uniphy0_gcc_rx_clk" }, ++ { .name = "uniphy0_gcc_tx_clk" }, ++ { .name = "uniphy1_gcc_rx_clk" }, ++ { .name = "uniphy1_gcc_tx_clk" }, ++ { .hw = &ubi32_pll.clkr.hw }, ++ { .name = "bias_pll_cc_clk" }, ++}; ++ ++static const struct parent_map ++gcc_xo_uniphy0_rx_tx_uniphy1_rx_tx_ubi32_bias_map[] = { ++ { P_XO, 0 }, ++ { P_UNIPHY0_RX, 1 }, ++ { P_UNIPHY0_TX, 2 }, ++ { P_UNIPHY1_RX, 3 }, ++ { P_UNIPHY1_TX, 4 }, ++ { P_UBI32_PLL, 5 }, ++ { P_BIAS_PLL, 6 }, ++}; ++ + static struct clk_rcg2 nss_port5_rx_clk_src = { + .cmd_rcgr = 0x68060, + .freq_tbl = ftbl_nss_port5_rx_clk_src, +@@ -1800,8 +1716,8 @@ static struct clk_rcg2 nss_port5_rx_clk_ + .parent_map = gcc_xo_uniphy0_rx_tx_uniphy1_rx_tx_ubi32_bias_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "nss_port5_rx_clk_src", +- .parent_names = gcc_xo_uniphy0_rx_tx_uniphy1_rx_tx_ubi32_bias, +- .num_parents = 7, ++ .parent_data = gcc_xo_uniphy0_rx_tx_uniphy1_rx_tx_ubi32_bias, ++ .num_parents = ARRAY_SIZE(gcc_xo_uniphy0_rx_tx_uniphy1_rx_tx_ubi32_bias), + .ops = &clk_rcg2_ops, + }, + }; +@@ -1813,9 +1729,8 @@ static struct clk_regmap_div nss_port5_r + .clkr = { + .hw.init = &(struct clk_init_data){ + .name = "nss_port5_rx_div_clk_src", +- .parent_names = (const char *[]){ +- "nss_port5_rx_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_port5_rx_clk_src.clkr.hw }, + .num_parents = 1, + .ops = &clk_regmap_div_ops, + .flags = CLK_SET_RATE_PARENT, +@@ -1835,6 +1750,27 @@ 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", .name = "xo" }, ++ { .name = "uniphy0_gcc_tx_clk" }, ++ { .name = "uniphy0_gcc_rx_clk" }, ++ { .name = "uniphy1_gcc_tx_clk" }, ++ { .name = "uniphy1_gcc_rx_clk" }, ++ { .hw = &ubi32_pll.clkr.hw }, ++ { .name = "bias_pll_cc_clk" }, ++}; ++ ++static const struct parent_map ++gcc_xo_uniphy0_tx_rx_uniphy1_tx_rx_ubi32_bias_map[] = { ++ { P_XO, 0 }, ++ { P_UNIPHY0_TX, 1 }, ++ { P_UNIPHY0_RX, 2 }, ++ { P_UNIPHY1_TX, 3 }, ++ { P_UNIPHY1_RX, 4 }, ++ { P_UBI32_PLL, 5 }, ++ { P_BIAS_PLL, 6 }, ++}; ++ + static struct clk_rcg2 nss_port5_tx_clk_src = { + .cmd_rcgr = 0x68068, + .freq_tbl = ftbl_nss_port5_tx_clk_src, +@@ -1842,8 +1778,8 @@ static struct clk_rcg2 nss_port5_tx_clk_ + .parent_map = gcc_xo_uniphy0_tx_rx_uniphy1_tx_rx_ubi32_bias_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "nss_port5_tx_clk_src", +- .parent_names = gcc_xo_uniphy0_tx_rx_uniphy1_tx_rx_ubi32_bias, +- .num_parents = 7, ++ .parent_data = gcc_xo_uniphy0_tx_rx_uniphy1_tx_rx_ubi32_bias, ++ .num_parents = ARRAY_SIZE(gcc_xo_uniphy0_tx_rx_uniphy1_tx_rx_ubi32_bias), + .ops = &clk_rcg2_ops, + }, + }; +@@ -1855,9 +1791,8 @@ static struct clk_regmap_div nss_port5_t + .clkr = { + .hw.init = &(struct clk_init_data){ + .name = "nss_port5_tx_div_clk_src", +- .parent_names = (const char *[]){ +- "nss_port5_tx_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_port5_tx_clk_src.clkr.hw }, + .num_parents = 1, + .ops = &clk_regmap_div_ops, + .flags = CLK_SET_RATE_PARENT, +@@ -1877,6 +1812,22 @@ static const struct freq_tbl ftbl_nss_po + { } + }; + ++static const struct clk_parent_data gcc_xo_uniphy2_rx_tx_ubi32_bias[] = { ++ { .fw_name = "xo", .name = "xo" }, ++ { .name = "uniphy2_gcc_rx_clk" }, ++ { .name = "uniphy2_gcc_tx_clk" }, ++ { .hw = &ubi32_pll.clkr.hw }, ++ { .name = "bias_pll_cc_clk" }, ++}; ++ ++static const struct parent_map gcc_xo_uniphy2_rx_tx_ubi32_bias_map[] = { ++ { P_XO, 0 }, ++ { P_UNIPHY2_RX, 1 }, ++ { P_UNIPHY2_TX, 2 }, ++ { P_UBI32_PLL, 5 }, ++ { P_BIAS_PLL, 6 }, ++}; ++ + static struct clk_rcg2 nss_port6_rx_clk_src = { + .cmd_rcgr = 0x68070, + .freq_tbl = ftbl_nss_port6_rx_clk_src, +@@ -1884,8 +1835,8 @@ static struct clk_rcg2 nss_port6_rx_clk_ + .parent_map = gcc_xo_uniphy2_rx_tx_ubi32_bias_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "nss_port6_rx_clk_src", +- .parent_names = gcc_xo_uniphy2_rx_tx_ubi32_bias, +- .num_parents = 5, ++ .parent_data = gcc_xo_uniphy2_rx_tx_ubi32_bias, ++ .num_parents = ARRAY_SIZE(gcc_xo_uniphy2_rx_tx_ubi32_bias), + .ops = &clk_rcg2_ops, + }, + }; +@@ -1897,9 +1848,8 @@ static struct clk_regmap_div nss_port6_r + .clkr = { + .hw.init = &(struct clk_init_data){ + .name = "nss_port6_rx_div_clk_src", +- .parent_names = (const char *[]){ +- "nss_port6_rx_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_port6_rx_clk_src.clkr.hw }, + .num_parents = 1, + .ops = &clk_regmap_div_ops, + .flags = CLK_SET_RATE_PARENT, +@@ -1919,6 +1869,22 @@ static const struct freq_tbl ftbl_nss_po + { } + }; + ++static const struct clk_parent_data gcc_xo_uniphy2_tx_rx_ubi32_bias[] = { ++ { .fw_name = "xo", .name = "xo" }, ++ { .name = "uniphy2_gcc_tx_clk" }, ++ { .name = "uniphy2_gcc_rx_clk" }, ++ { .hw = &ubi32_pll.clkr.hw }, ++ { .name = "bias_pll_cc_clk" }, ++}; ++ ++static const struct parent_map gcc_xo_uniphy2_tx_rx_ubi32_bias_map[] = { ++ { P_XO, 0 }, ++ { P_UNIPHY2_TX, 1 }, ++ { P_UNIPHY2_RX, 2 }, ++ { P_UBI32_PLL, 5 }, ++ { P_BIAS_PLL, 6 }, ++}; ++ + static struct clk_rcg2 nss_port6_tx_clk_src = { + .cmd_rcgr = 0x68078, + .freq_tbl = ftbl_nss_port6_tx_clk_src, +@@ -1926,8 +1892,8 @@ static struct clk_rcg2 nss_port6_tx_clk_ + .parent_map = gcc_xo_uniphy2_tx_rx_ubi32_bias_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "nss_port6_tx_clk_src", +- .parent_names = gcc_xo_uniphy2_tx_rx_ubi32_bias, +- .num_parents = 5, ++ .parent_data = gcc_xo_uniphy2_tx_rx_ubi32_bias, ++ .num_parents = ARRAY_SIZE(gcc_xo_uniphy2_tx_rx_ubi32_bias), + .ops = &clk_rcg2_ops, + }, + }; +@@ -1939,9 +1905,8 @@ static struct clk_regmap_div nss_port6_t + .clkr = { + .hw.init = &(struct clk_init_data){ + .name = "nss_port6_tx_div_clk_src", +- .parent_names = (const char *[]){ +- "nss_port6_tx_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_port6_tx_clk_src.clkr.hw }, + .num_parents = 1, + .ops = &clk_regmap_div_ops, + .flags = CLK_SET_RATE_PARENT, +@@ -1964,8 +1929,8 @@ static struct clk_rcg2 crypto_clk_src = + .parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "crypto_clk_src", +- .parent_names = gcc_xo_gpll0_gpll0_out_main_div2, +- .num_parents = 3, ++ .parent_data = gcc_xo_gpll0_gpll0_out_main_div2, ++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2), + .ops = &clk_rcg2_ops, + }, + }; +@@ -1975,6 +1940,22 @@ static struct freq_tbl ftbl_gp_clk_src[] + { } + }; + ++static const struct clk_parent_data gcc_xo_gpll0_gpll6_gpll0_sleep_clk[] = { ++ { .fw_name = "xo", .name = "xo" }, ++ { .hw = &gpll0.clkr.hw }, ++ { .hw = &gpll6.clkr.hw }, ++ { .hw = &gpll0_out_main_div2.hw }, ++ { .fw_name = "sleep_clk", .name = "sleep_clk" }, ++}; ++ ++static const struct parent_map gcc_xo_gpll0_gpll6_gpll0_sleep_clk_map[] = { ++ { P_XO, 0 }, ++ { P_GPLL0, 1 }, ++ { P_GPLL6, 2 }, ++ { P_GPLL0_DIV2, 4 }, ++ { P_SLEEP_CLK, 6 }, ++}; ++ + static struct clk_rcg2 gp1_clk_src = { + .cmd_rcgr = 0x08004, + .freq_tbl = ftbl_gp_clk_src, +@@ -1983,8 +1964,8 @@ static struct clk_rcg2 gp1_clk_src = { + .parent_map = gcc_xo_gpll0_gpll6_gpll0_sleep_clk_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gp1_clk_src", +- .parent_names = gcc_xo_gpll0_gpll6_gpll0_sleep_clk, +- .num_parents = 5, ++ .parent_data = gcc_xo_gpll0_gpll6_gpll0_sleep_clk, ++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll6_gpll0_sleep_clk), + .ops = &clk_rcg2_ops, + }, + }; +@@ -1997,8 +1978,8 @@ static struct clk_rcg2 gp2_clk_src = { + .parent_map = gcc_xo_gpll0_gpll6_gpll0_sleep_clk_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gp2_clk_src", +- .parent_names = gcc_xo_gpll0_gpll6_gpll0_sleep_clk, +- .num_parents = 5, ++ .parent_data = gcc_xo_gpll0_gpll6_gpll0_sleep_clk, ++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll6_gpll0_sleep_clk), + .ops = &clk_rcg2_ops, + }, + }; +@@ -2011,8 +1992,8 @@ static struct clk_rcg2 gp3_clk_src = { + .parent_map = gcc_xo_gpll0_gpll6_gpll0_sleep_clk_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gp3_clk_src", +- .parent_names = gcc_xo_gpll0_gpll6_gpll0_sleep_clk, +- .num_parents = 5, ++ .parent_data = gcc_xo_gpll0_gpll6_gpll0_sleep_clk, ++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll6_gpll0_sleep_clk), + .ops = &clk_rcg2_ops, + }, + }; +@@ -2024,9 +2005,8 @@ static struct clk_branch gcc_blsp1_ahb_c + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_ahb_clk", +- .parent_names = (const char *[]){ +- "pcnoc_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &pcnoc_clk_src.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -2041,9 +2021,8 @@ static struct clk_branch gcc_blsp1_qup1_ + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_qup1_i2c_apps_clk", +- .parent_names = (const char *[]){ +- "blsp1_qup1_i2c_apps_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &blsp1_qup1_i2c_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -2058,9 +2037,8 @@ static struct clk_branch gcc_blsp1_qup1_ + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_qup1_spi_apps_clk", +- .parent_names = (const char *[]){ +- "blsp1_qup1_spi_apps_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &blsp1_qup1_spi_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -2075,9 +2053,8 @@ static struct clk_branch gcc_blsp1_qup2_ + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_qup2_i2c_apps_clk", +- .parent_names = (const char *[]){ +- "blsp1_qup2_i2c_apps_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &blsp1_qup2_i2c_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -2092,9 +2069,8 @@ static struct clk_branch gcc_blsp1_qup2_ + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_qup2_spi_apps_clk", +- .parent_names = (const char *[]){ +- "blsp1_qup2_spi_apps_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &blsp1_qup2_spi_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -2109,9 +2085,8 @@ static struct clk_branch gcc_blsp1_qup3_ + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_qup3_i2c_apps_clk", +- .parent_names = (const char *[]){ +- "blsp1_qup3_i2c_apps_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &blsp1_qup3_i2c_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -2126,9 +2101,8 @@ static struct clk_branch gcc_blsp1_qup3_ + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_qup3_spi_apps_clk", +- .parent_names = (const char *[]){ +- "blsp1_qup3_spi_apps_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &blsp1_qup3_spi_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -2143,9 +2117,8 @@ static struct clk_branch gcc_blsp1_qup4_ + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_qup4_i2c_apps_clk", +- .parent_names = (const char *[]){ +- "blsp1_qup4_i2c_apps_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &blsp1_qup4_i2c_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -2160,9 +2133,8 @@ static struct clk_branch gcc_blsp1_qup4_ + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_qup4_spi_apps_clk", +- .parent_names = (const char *[]){ +- "blsp1_qup4_spi_apps_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &blsp1_qup4_spi_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -2177,9 +2149,8 @@ static struct clk_branch gcc_blsp1_qup5_ + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_qup5_i2c_apps_clk", +- .parent_names = (const char *[]){ +- "blsp1_qup5_i2c_apps_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &blsp1_qup5_i2c_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -2194,9 +2165,8 @@ static struct clk_branch gcc_blsp1_qup5_ + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_qup5_spi_apps_clk", +- .parent_names = (const char *[]){ +- "blsp1_qup5_spi_apps_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &blsp1_qup5_spi_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -2211,9 +2181,8 @@ static struct clk_branch gcc_blsp1_qup6_ + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_qup6_i2c_apps_clk", +- .parent_names = (const char *[]){ +- "blsp1_qup6_i2c_apps_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &blsp1_qup6_i2c_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -2228,9 +2197,8 @@ static struct clk_branch gcc_blsp1_qup6_ + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_qup6_spi_apps_clk", +- .parent_names = (const char *[]){ +- "blsp1_qup6_spi_apps_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &blsp1_qup6_spi_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -2245,9 +2213,8 @@ static struct clk_branch gcc_blsp1_uart1 + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_uart1_apps_clk", +- .parent_names = (const char *[]){ +- "blsp1_uart1_apps_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &blsp1_uart1_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -2262,9 +2229,8 @@ static struct clk_branch gcc_blsp1_uart2 + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_uart2_apps_clk", +- .parent_names = (const char *[]){ +- "blsp1_uart2_apps_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &blsp1_uart2_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -2279,9 +2245,8 @@ static struct clk_branch gcc_blsp1_uart3 + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_uart3_apps_clk", +- .parent_names = (const char *[]){ +- "blsp1_uart3_apps_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &blsp1_uart3_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -2296,9 +2261,8 @@ static struct clk_branch gcc_blsp1_uart4 + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_uart4_apps_clk", +- .parent_names = (const char *[]){ +- "blsp1_uart4_apps_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &blsp1_uart4_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -2313,9 +2277,8 @@ static struct clk_branch gcc_blsp1_uart5 + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_uart5_apps_clk", +- .parent_names = (const char *[]){ +- "blsp1_uart5_apps_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &blsp1_uart5_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -2330,9 +2293,8 @@ static struct clk_branch gcc_blsp1_uart6 + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_uart6_apps_clk", +- .parent_names = (const char *[]){ +- "blsp1_uart6_apps_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &blsp1_uart6_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -2348,9 +2310,8 @@ static struct clk_branch gcc_prng_ahb_cl + .enable_mask = BIT(8), + .hw.init = &(struct clk_init_data){ + .name = "gcc_prng_ahb_clk", +- .parent_names = (const char *[]){ +- "pcnoc_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &pcnoc_clk_src.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -2365,9 +2326,8 @@ static struct clk_branch gcc_qpic_ahb_cl + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qpic_ahb_clk", +- .parent_names = (const char *[]){ +- "pcnoc_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &pcnoc_clk_src.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -2382,9 +2342,8 @@ static struct clk_branch gcc_qpic_clk = + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qpic_clk", +- .parent_names = (const char *[]){ +- "pcnoc_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &pcnoc_clk_src.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -2399,9 +2358,8 @@ static struct clk_branch gcc_pcie0_ahb_c + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie0_ahb_clk", +- .parent_names = (const char *[]){ +- "pcnoc_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &pcnoc_clk_src.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -2416,9 +2374,8 @@ static struct clk_branch gcc_pcie0_aux_c + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie0_aux_clk", +- .parent_names = (const char *[]){ +- "pcie0_aux_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &pcie0_aux_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -2433,9 +2390,8 @@ static struct clk_branch gcc_pcie0_axi_m + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie0_axi_m_clk", +- .parent_names = (const char *[]){ +- "pcie0_axi_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &pcie0_axi_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -2450,9 +2406,8 @@ static struct clk_branch gcc_pcie0_axi_s + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie0_axi_s_clk", +- .parent_names = (const char *[]){ +- "pcie0_axi_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &pcie0_axi_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -2468,9 +2423,8 @@ static struct clk_branch gcc_pcie0_pipe_ + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie0_pipe_clk", +- .parent_names = (const char *[]){ +- "pcie0_pipe_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &pcie0_pipe_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -2485,9 +2439,8 @@ static struct clk_branch gcc_sys_noc_pci + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_sys_noc_pcie0_axi_clk", +- .parent_names = (const char *[]){ +- "pcie0_axi_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &pcie0_axi_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -2502,9 +2455,8 @@ static struct clk_branch gcc_pcie1_ahb_c + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie1_ahb_clk", +- .parent_names = (const char *[]){ +- "pcnoc_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &pcnoc_clk_src.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -2519,9 +2471,8 @@ static struct clk_branch gcc_pcie1_aux_c + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie1_aux_clk", +- .parent_names = (const char *[]){ +- "pcie1_aux_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &pcie1_aux_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -2536,9 +2487,8 @@ static struct clk_branch gcc_pcie1_axi_m + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie1_axi_m_clk", +- .parent_names = (const char *[]){ +- "pcie1_axi_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &pcie1_axi_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -2553,9 +2503,8 @@ static struct clk_branch gcc_pcie1_axi_s + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie1_axi_s_clk", +- .parent_names = (const char *[]){ +- "pcie1_axi_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &pcie1_axi_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -2571,9 +2520,8 @@ static struct clk_branch gcc_pcie1_pipe_ + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie1_pipe_clk", +- .parent_names = (const char *[]){ +- "pcie1_pipe_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &pcie1_pipe_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -2588,9 +2536,8 @@ static struct clk_branch gcc_sys_noc_pci + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_sys_noc_pcie1_axi_clk", +- .parent_names = (const char *[]){ +- "pcie1_axi_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &pcie1_axi_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -2605,9 +2552,8 @@ static struct clk_branch gcc_usb0_aux_cl + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb0_aux_clk", +- .parent_names = (const char *[]){ +- "usb0_aux_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &usb0_aux_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -2622,9 +2568,8 @@ static struct clk_branch gcc_sys_noc_usb + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_sys_noc_usb0_axi_clk", +- .parent_names = (const char *[]){ +- "usb0_master_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &usb0_master_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -2639,9 +2584,8 @@ static struct clk_branch gcc_usb0_master + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb0_master_clk", +- .parent_names = (const char *[]){ +- "usb0_master_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &usb0_master_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -2656,9 +2600,8 @@ static struct clk_branch gcc_usb0_mock_u + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb0_mock_utmi_clk", +- .parent_names = (const char *[]){ +- "usb0_mock_utmi_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &usb0_mock_utmi_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -2673,9 +2616,8 @@ static struct clk_branch gcc_usb0_phy_cf + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb0_phy_cfg_ahb_clk", +- .parent_names = (const char *[]){ +- "pcnoc_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &pcnoc_clk_src.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -2691,9 +2633,8 @@ static struct clk_branch gcc_usb0_pipe_c + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb0_pipe_clk", +- .parent_names = (const char *[]){ +- "usb0_pipe_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &usb0_pipe_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -2708,9 +2649,8 @@ static struct clk_branch gcc_usb0_sleep_ + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb0_sleep_clk", +- .parent_names = (const char *[]){ +- "gcc_sleep_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &gcc_sleep_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -2725,9 +2665,8 @@ static struct clk_branch gcc_usb1_aux_cl + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb1_aux_clk", +- .parent_names = (const char *[]){ +- "usb1_aux_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &usb1_aux_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -2742,9 +2681,8 @@ static struct clk_branch gcc_sys_noc_usb + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_sys_noc_usb1_axi_clk", +- .parent_names = (const char *[]){ +- "usb1_master_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &usb1_master_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -2759,9 +2697,8 @@ static struct clk_branch gcc_usb1_master + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb1_master_clk", +- .parent_names = (const char *[]){ +- "usb1_master_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &usb1_master_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -2776,9 +2713,8 @@ static struct clk_branch gcc_usb1_mock_u + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb1_mock_utmi_clk", +- .parent_names = (const char *[]){ +- "usb1_mock_utmi_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &usb1_mock_utmi_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -2793,9 +2729,8 @@ static struct clk_branch gcc_usb1_phy_cf + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb1_phy_cfg_ahb_clk", +- .parent_names = (const char *[]){ +- "pcnoc_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &pcnoc_clk_src.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -2811,9 +2746,8 @@ static struct clk_branch gcc_usb1_pipe_c + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb1_pipe_clk", +- .parent_names = (const char *[]){ +- "usb1_pipe_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &usb1_pipe_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -2828,9 +2762,8 @@ static struct clk_branch gcc_usb1_sleep_ + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb1_sleep_clk", +- .parent_names = (const char *[]){ +- "gcc_sleep_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &gcc_sleep_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -2845,9 +2778,8 @@ static struct clk_branch gcc_sdcc1_ahb_c + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_sdcc1_ahb_clk", +- .parent_names = (const char *[]){ +- "pcnoc_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &pcnoc_clk_src.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -2862,9 +2794,8 @@ static struct clk_branch gcc_sdcc1_apps_ + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_sdcc1_apps_clk", +- .parent_names = (const char *[]){ +- "sdcc1_apps_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &sdcc1_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -2879,9 +2810,8 @@ static struct clk_branch gcc_sdcc1_ice_c + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_sdcc1_ice_core_clk", +- .parent_names = (const char *[]){ +- "sdcc1_ice_core_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &sdcc1_ice_core_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -2896,9 +2826,8 @@ static struct clk_branch gcc_sdcc2_ahb_c + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_sdcc2_ahb_clk", +- .parent_names = (const char *[]){ +- "pcnoc_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &pcnoc_clk_src.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -2913,9 +2842,8 @@ static struct clk_branch gcc_sdcc2_apps_ + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_sdcc2_apps_clk", +- .parent_names = (const char *[]){ +- "sdcc2_apps_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &sdcc2_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -2930,9 +2858,8 @@ static struct clk_branch gcc_mem_noc_nss + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_mem_noc_nss_axi_clk", +- .parent_names = (const char *[]){ +- "nss_noc_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_noc_clk_src.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -2947,9 +2874,8 @@ static struct clk_branch gcc_nss_ce_apb_ + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_nss_ce_apb_clk", +- .parent_names = (const char *[]){ +- "nss_ce_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_ce_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -2964,9 +2890,8 @@ static struct clk_branch gcc_nss_ce_axi_ + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_nss_ce_axi_clk", +- .parent_names = (const char *[]){ +- "nss_ce_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_ce_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -2981,9 +2906,8 @@ static struct clk_branch gcc_nss_cfg_clk + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_nss_cfg_clk", +- .parent_names = (const char *[]){ +- "pcnoc_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &pcnoc_clk_src.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -2998,9 +2922,8 @@ static struct clk_branch gcc_nss_crypto_ + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_nss_crypto_clk", +- .parent_names = (const char *[]){ +- "nss_crypto_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_crypto_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -3015,9 +2938,8 @@ static struct clk_branch gcc_nss_csr_clk + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_nss_csr_clk", +- .parent_names = (const char *[]){ +- "nss_ce_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_ce_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -3032,9 +2954,8 @@ static struct clk_branch gcc_nss_edma_cf + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_nss_edma_cfg_clk", +- .parent_names = (const char *[]){ +- "nss_ppe_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_ppe_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -3049,9 +2970,8 @@ static struct clk_branch gcc_nss_edma_cl + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_nss_edma_clk", +- .parent_names = (const char *[]){ +- "nss_ppe_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_ppe_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -3066,9 +2986,8 @@ static struct clk_branch gcc_nss_imem_cl + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_nss_imem_clk", +- .parent_names = (const char *[]){ +- "nss_imem_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_imem_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -3083,9 +3002,8 @@ static struct clk_branch gcc_nss_noc_clk + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_nss_noc_clk", +- .parent_names = (const char *[]){ +- "nss_noc_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_noc_clk_src.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -3100,9 +3018,8 @@ static struct clk_branch gcc_nss_ppe_btq + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_nss_ppe_btq_clk", +- .parent_names = (const char *[]){ +- "nss_ppe_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_ppe_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -3117,9 +3034,8 @@ static struct clk_branch gcc_nss_ppe_cfg + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_nss_ppe_cfg_clk", +- .parent_names = (const char *[]){ +- "nss_ppe_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_ppe_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -3134,9 +3050,8 @@ static struct clk_branch gcc_nss_ppe_clk + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_nss_ppe_clk", +- .parent_names = (const char *[]){ +- "nss_ppe_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_ppe_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -3151,9 +3066,8 @@ static struct clk_branch gcc_nss_ppe_ipe + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_nss_ppe_ipe_clk", +- .parent_names = (const char *[]){ +- "nss_ppe_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_ppe_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -3168,9 +3082,8 @@ static struct clk_branch gcc_nss_ptp_ref + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_nss_ptp_ref_clk", +- .parent_names = (const char *[]){ +- "nss_ppe_cdiv_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_ppe_cdiv_clk_src.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -3186,9 +3099,8 @@ static struct clk_branch gcc_crypto_ppe_ + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_crypto_ppe_clk", +- .parent_names = (const char *[]){ +- "nss_ppe_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_ppe_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -3203,9 +3115,8 @@ static struct clk_branch gcc_nssnoc_ce_a + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_nssnoc_ce_apb_clk", +- .parent_names = (const char *[]){ +- "nss_ce_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_ce_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -3220,9 +3131,8 @@ static struct clk_branch gcc_nssnoc_ce_a + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_nssnoc_ce_axi_clk", +- .parent_names = (const char *[]){ +- "nss_ce_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_ce_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -3237,9 +3147,8 @@ static struct clk_branch gcc_nssnoc_cryp + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_nssnoc_crypto_clk", +- .parent_names = (const char *[]){ +- "nss_crypto_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_crypto_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -3254,9 +3163,8 @@ static struct clk_branch gcc_nssnoc_ppe_ + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_nssnoc_ppe_cfg_clk", +- .parent_names = (const char *[]){ +- "nss_ppe_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_ppe_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -3271,9 +3179,8 @@ static struct clk_branch gcc_nssnoc_ppe_ + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_nssnoc_ppe_clk", +- .parent_names = (const char *[]){ +- "nss_ppe_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_ppe_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -3288,9 +3195,8 @@ static struct clk_branch gcc_nssnoc_qosg + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_nssnoc_qosgen_ref_clk", +- .parent_names = (const char *[]){ +- "gcc_xo_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &gcc_xo_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -3305,9 +3211,8 @@ static struct clk_branch gcc_nssnoc_snoc + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_nssnoc_snoc_clk", +- .parent_names = (const char *[]){ +- "system_noc_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &system_noc_clk_src.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -3322,9 +3227,8 @@ static struct clk_branch gcc_nssnoc_time + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_nssnoc_timeout_ref_clk", +- .parent_names = (const char *[]){ +- "gcc_xo_div4_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &gcc_xo_div4_clk_src.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -3339,9 +3243,8 @@ static struct clk_branch gcc_nssnoc_ubi0 + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_nssnoc_ubi0_ahb_clk", +- .parent_names = (const char *[]){ +- "nss_ce_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_ce_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -3356,9 +3259,8 @@ static struct clk_branch gcc_nssnoc_ubi1 + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_nssnoc_ubi1_ahb_clk", +- .parent_names = (const char *[]){ +- "nss_ce_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_ce_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -3374,9 +3276,8 @@ static struct clk_branch gcc_ubi0_ahb_cl + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ubi0_ahb_clk", +- .parent_names = (const char *[]){ +- "nss_ce_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_ce_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -3392,9 +3293,8 @@ static struct clk_branch gcc_ubi0_axi_cl + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ubi0_axi_clk", +- .parent_names = (const char *[]){ +- "nss_noc_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_noc_clk_src.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -3410,9 +3310,8 @@ static struct clk_branch gcc_ubi0_nc_axi + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ubi0_nc_axi_clk", +- .parent_names = (const char *[]){ +- "nss_noc_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_noc_clk_src.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -3428,9 +3327,8 @@ static struct clk_branch gcc_ubi0_core_c + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ubi0_core_clk", +- .parent_names = (const char *[]){ +- "nss_ubi0_div_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_ubi0_div_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -3446,9 +3344,8 @@ static struct clk_branch gcc_ubi0_mpt_cl + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ubi0_mpt_clk", +- .parent_names = (const char *[]){ +- "ubi_mpt_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &ubi_mpt_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -3464,9 +3361,8 @@ static struct clk_branch gcc_ubi1_ahb_cl + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ubi1_ahb_clk", +- .parent_names = (const char *[]){ +- "nss_ce_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_ce_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -3482,9 +3378,8 @@ static struct clk_branch gcc_ubi1_axi_cl + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ubi1_axi_clk", +- .parent_names = (const char *[]){ +- "nss_noc_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_noc_clk_src.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -3500,9 +3395,8 @@ static struct clk_branch gcc_ubi1_nc_axi + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ubi1_nc_axi_clk", +- .parent_names = (const char *[]){ +- "nss_noc_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_noc_clk_src.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -3518,9 +3412,8 @@ static struct clk_branch gcc_ubi1_core_c + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ubi1_core_clk", +- .parent_names = (const char *[]){ +- "nss_ubi1_div_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_ubi1_div_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -3536,9 +3429,8 @@ static struct clk_branch gcc_ubi1_mpt_cl + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ubi1_mpt_clk", +- .parent_names = (const char *[]){ +- "ubi_mpt_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &ubi_mpt_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -3553,9 +3445,8 @@ static struct clk_branch gcc_cmn_12gpll_ + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_cmn_12gpll_ahb_clk", +- .parent_names = (const char *[]){ +- "pcnoc_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &pcnoc_clk_src.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -3570,9 +3461,8 @@ static struct clk_branch gcc_cmn_12gpll_ + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_cmn_12gpll_sys_clk", +- .parent_names = (const char *[]){ +- "gcc_xo_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &gcc_xo_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -3587,9 +3477,8 @@ static struct clk_branch gcc_mdio_ahb_cl + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_mdio_ahb_clk", +- .parent_names = (const char *[]){ +- "pcnoc_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &pcnoc_clk_src.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -3604,9 +3493,8 @@ static struct clk_branch gcc_uniphy0_ahb + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_uniphy0_ahb_clk", +- .parent_names = (const char *[]){ +- "pcnoc_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &pcnoc_clk_src.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -3621,9 +3509,8 @@ static struct clk_branch gcc_uniphy0_sys + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_uniphy0_sys_clk", +- .parent_names = (const char *[]){ +- "gcc_xo_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &gcc_xo_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -3638,9 +3525,8 @@ static struct clk_branch gcc_uniphy1_ahb + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_uniphy1_ahb_clk", +- .parent_names = (const char *[]){ +- "pcnoc_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &pcnoc_clk_src.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -3655,9 +3541,8 @@ static struct clk_branch gcc_uniphy1_sys + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_uniphy1_sys_clk", +- .parent_names = (const char *[]){ +- "gcc_xo_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &gcc_xo_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -3672,9 +3557,8 @@ static struct clk_branch gcc_uniphy2_ahb + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_uniphy2_ahb_clk", +- .parent_names = (const char *[]){ +- "pcnoc_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &pcnoc_clk_src.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -3689,9 +3573,8 @@ static struct clk_branch gcc_uniphy2_sys + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_uniphy2_sys_clk", +- .parent_names = (const char *[]){ +- "gcc_xo_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &gcc_xo_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -3706,9 +3589,8 @@ static struct clk_branch gcc_nss_port1_r + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_nss_port1_rx_clk", +- .parent_names = (const char *[]){ +- "nss_port1_rx_div_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_port1_rx_div_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -3723,9 +3605,8 @@ static struct clk_branch gcc_nss_port1_t + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_nss_port1_tx_clk", +- .parent_names = (const char *[]){ +- "nss_port1_tx_div_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_port1_tx_div_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -3740,9 +3621,8 @@ static struct clk_branch gcc_nss_port2_r + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_nss_port2_rx_clk", +- .parent_names = (const char *[]){ +- "nss_port2_rx_div_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_port2_rx_div_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -3757,9 +3637,8 @@ static struct clk_branch gcc_nss_port2_t + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_nss_port2_tx_clk", +- .parent_names = (const char *[]){ +- "nss_port2_tx_div_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_port2_tx_div_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -3774,9 +3653,8 @@ static struct clk_branch gcc_nss_port3_r + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_nss_port3_rx_clk", +- .parent_names = (const char *[]){ +- "nss_port3_rx_div_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_port3_rx_div_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -3791,9 +3669,8 @@ static struct clk_branch gcc_nss_port3_t + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_nss_port3_tx_clk", +- .parent_names = (const char *[]){ +- "nss_port3_tx_div_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_port3_tx_div_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -3808,9 +3685,8 @@ static struct clk_branch gcc_nss_port4_r + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_nss_port4_rx_clk", +- .parent_names = (const char *[]){ +- "nss_port4_rx_div_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_port4_rx_div_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -3825,9 +3701,8 @@ static struct clk_branch gcc_nss_port4_t + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_nss_port4_tx_clk", +- .parent_names = (const char *[]){ +- "nss_port4_tx_div_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_port4_tx_div_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -3842,9 +3717,8 @@ static struct clk_branch gcc_nss_port5_r + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_nss_port5_rx_clk", +- .parent_names = (const char *[]){ +- "nss_port5_rx_div_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_port5_rx_div_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -3859,9 +3733,8 @@ static struct clk_branch gcc_nss_port5_t + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_nss_port5_tx_clk", +- .parent_names = (const char *[]){ +- "nss_port5_tx_div_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_port5_tx_div_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -3876,9 +3749,8 @@ static struct clk_branch gcc_nss_port6_r + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_nss_port6_rx_clk", +- .parent_names = (const char *[]){ +- "nss_port6_rx_div_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_port6_rx_div_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -3893,9 +3765,8 @@ static struct clk_branch gcc_nss_port6_t + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_nss_port6_tx_clk", +- .parent_names = (const char *[]){ +- "nss_port6_tx_div_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_port6_tx_div_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -3910,9 +3781,8 @@ static struct clk_branch gcc_port1_mac_c + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_port1_mac_clk", +- .parent_names = (const char *[]){ +- "nss_ppe_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_ppe_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -3927,9 +3797,8 @@ static struct clk_branch gcc_port2_mac_c + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_port2_mac_clk", +- .parent_names = (const char *[]){ +- "nss_ppe_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_ppe_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -3944,9 +3813,8 @@ static struct clk_branch gcc_port3_mac_c + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_port3_mac_clk", +- .parent_names = (const char *[]){ +- "nss_ppe_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_ppe_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -3961,9 +3829,8 @@ static struct clk_branch gcc_port4_mac_c + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_port4_mac_clk", +- .parent_names = (const char *[]){ +- "nss_ppe_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_ppe_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -3978,9 +3845,8 @@ static struct clk_branch gcc_port5_mac_c + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_port5_mac_clk", +- .parent_names = (const char *[]){ +- "nss_ppe_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_ppe_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -3995,9 +3861,8 @@ static struct clk_branch gcc_port6_mac_c + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_port6_mac_clk", +- .parent_names = (const char *[]){ +- "nss_ppe_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_ppe_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -4012,9 +3877,8 @@ static struct clk_branch gcc_uniphy0_por + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_uniphy0_port1_rx_clk", +- .parent_names = (const char *[]){ +- "nss_port1_rx_div_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_port1_rx_div_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -4029,9 +3893,8 @@ static struct clk_branch gcc_uniphy0_por + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_uniphy0_port1_tx_clk", +- .parent_names = (const char *[]){ +- "nss_port1_tx_div_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_port1_tx_div_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -4046,9 +3909,8 @@ static struct clk_branch gcc_uniphy0_por + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_uniphy0_port2_rx_clk", +- .parent_names = (const char *[]){ +- "nss_port2_rx_div_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_port2_rx_div_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -4063,9 +3925,8 @@ static struct clk_branch gcc_uniphy0_por + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_uniphy0_port2_tx_clk", +- .parent_names = (const char *[]){ +- "nss_port2_tx_div_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_port2_tx_div_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -4080,9 +3941,8 @@ static struct clk_branch gcc_uniphy0_por + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_uniphy0_port3_rx_clk", +- .parent_names = (const char *[]){ +- "nss_port3_rx_div_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_port3_rx_div_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -4097,9 +3957,8 @@ static struct clk_branch gcc_uniphy0_por + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_uniphy0_port3_tx_clk", +- .parent_names = (const char *[]){ +- "nss_port3_tx_div_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_port3_tx_div_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -4114,9 +3973,8 @@ static struct clk_branch gcc_uniphy0_por + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_uniphy0_port4_rx_clk", +- .parent_names = (const char *[]){ +- "nss_port4_rx_div_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_port4_rx_div_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -4131,9 +3989,8 @@ static struct clk_branch gcc_uniphy0_por + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_uniphy0_port4_tx_clk", +- .parent_names = (const char *[]){ +- "nss_port4_tx_div_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_port4_tx_div_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -4148,9 +4005,8 @@ static struct clk_branch gcc_uniphy0_por + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_uniphy0_port5_rx_clk", +- .parent_names = (const char *[]){ +- "nss_port5_rx_div_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_port5_rx_div_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -4165,9 +4021,8 @@ static struct clk_branch gcc_uniphy0_por + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_uniphy0_port5_tx_clk", +- .parent_names = (const char *[]){ +- "nss_port5_tx_div_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_port5_tx_div_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -4182,9 +4037,8 @@ static struct clk_branch gcc_uniphy1_por + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_uniphy1_port5_rx_clk", +- .parent_names = (const char *[]){ +- "nss_port5_rx_div_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_port5_rx_div_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -4199,9 +4053,8 @@ static struct clk_branch gcc_uniphy1_por + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_uniphy1_port5_tx_clk", +- .parent_names = (const char *[]){ +- "nss_port5_tx_div_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_port5_tx_div_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -4216,9 +4069,8 @@ static struct clk_branch gcc_uniphy2_por + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_uniphy2_port6_rx_clk", +- .parent_names = (const char *[]){ +- "nss_port6_rx_div_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_port6_rx_div_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -4233,9 +4085,8 @@ static struct clk_branch gcc_uniphy2_por + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_uniphy2_port6_tx_clk", +- .parent_names = (const char *[]){ +- "nss_port6_tx_div_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &nss_port6_tx_div_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -4251,9 +4102,8 @@ static struct clk_branch gcc_crypto_ahb_ + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_crypto_ahb_clk", +- .parent_names = (const char *[]){ +- "pcnoc_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &pcnoc_clk_src.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -4269,9 +4119,8 @@ static struct clk_branch gcc_crypto_axi_ + .enable_mask = BIT(1), + .hw.init = &(struct clk_init_data){ + .name = "gcc_crypto_axi_clk", +- .parent_names = (const char *[]){ +- "pcnoc_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &pcnoc_clk_src.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -4287,9 +4136,8 @@ static struct clk_branch gcc_crypto_clk + .enable_mask = BIT(2), + .hw.init = &(struct clk_init_data){ + .name = "gcc_crypto_clk", +- .parent_names = (const char *[]){ +- "crypto_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &crypto_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -4304,9 +4152,8 @@ static struct clk_branch gcc_gp1_clk = { + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_gp1_clk", +- .parent_names = (const char *[]){ +- "gp1_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &gp1_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -4321,9 +4168,8 @@ static struct clk_branch gcc_gp2_clk = { + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_gp2_clk", +- .parent_names = (const char *[]){ +- "gp2_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &gp2_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -4338,9 +4184,8 @@ static struct clk_branch gcc_gp3_clk = { + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_gp3_clk", +- .parent_names = (const char *[]){ +- "gp3_clk_src" +- }, ++ .parent_hws = (const struct clk_hw *[]){ ++ &gp3_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, +@@ -4362,7 +4207,7 @@ static struct clk_rcg2 pcie0_rchng_clk_s + .clkr.hw.init = &(struct clk_init_data){ + .name = "pcie0_rchng_clk_src", + .parent_data = gcc_xo_gpll0, +- .num_parents = 2, ++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0), + .ops = &clk_rcg2_ops, + }, + }; diff --git a/target/linux/qualcommax/patches-6.1/0009-v6.2-dt-bindings-clock-qcom-ipq8074-add-missing-networkin.patch b/target/linux/qualcommax/patches-6.1/0009-v6.2-dt-bindings-clock-qcom-ipq8074-add-missing-networkin.patch new file mode 100644 index 000000000..75f16a167 --- /dev/null +++ b/target/linux/qualcommax/patches-6.1/0009-v6.2-dt-bindings-clock-qcom-ipq8074-add-missing-networkin.patch @@ -0,0 +1,39 @@ +From e78a40eb24187a8b4f9b89e2181f674df39c2013 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Mon, 7 Nov 2022 14:29:00 +0100 +Subject: [PATCH] dt-bindings: clock: qcom: ipq8074: add missing networking + resets + +Add bindings for the missing networking resets found in IPQ8074 GCC. + +Signed-off-by: Robert Marko +Acked-by: Krzysztof Kozlowski +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20221107132901.489240-2-robimarko@gmail.com +--- + include/dt-bindings/clock/qcom,gcc-ipq8074.h | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +--- a/include/dt-bindings/clock/qcom,gcc-ipq8074.h ++++ b/include/dt-bindings/clock/qcom,gcc-ipq8074.h +@@ -367,6 +367,20 @@ + #define GCC_PCIE1_AHB_ARES 129 + #define GCC_PCIE1_AXI_MASTER_STICKY_ARES 130 + #define GCC_PCIE0_AXI_SLAVE_STICKY_ARES 131 ++#define GCC_PPE_FULL_RESET 132 ++#define GCC_UNIPHY0_SOFT_RESET 133 ++#define GCC_UNIPHY0_XPCS_RESET 134 ++#define GCC_UNIPHY1_SOFT_RESET 135 ++#define GCC_UNIPHY1_XPCS_RESET 136 ++#define GCC_UNIPHY2_SOFT_RESET 137 ++#define GCC_UNIPHY2_XPCS_RESET 138 ++#define GCC_EDMA_HW_RESET 139 ++#define GCC_NSSPORT1_RESET 140 ++#define GCC_NSSPORT2_RESET 141 ++#define GCC_NSSPORT3_RESET 142 ++#define GCC_NSSPORT4_RESET 143 ++#define GCC_NSSPORT5_RESET 144 ++#define GCC_NSSPORT6_RESET 145 + + #define USB0_GDSC 0 + #define USB1_GDSC 1 diff --git a/target/linux/qualcommax/patches-6.1/0010-v6.2-clk-qcom-ipq8074-add-missing-networking-resets.patch b/target/linux/qualcommax/patches-6.1/0010-v6.2-clk-qcom-ipq8074-add-missing-networking-resets.patch new file mode 100644 index 000000000..81014ab24 --- /dev/null +++ b/target/linux/qualcommax/patches-6.1/0010-v6.2-clk-qcom-ipq8074-add-missing-networking-resets.patch @@ -0,0 +1,41 @@ +From da76cb63d04dc22ed32123b8c1d084c006d67bfb Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Mon, 7 Nov 2022 14:29:01 +0100 +Subject: [PATCH] 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 +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20221107132901.489240-3-robimarko@gmail.com +--- + drivers/clk/qcom/gcc-ipq8074.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +--- a/drivers/clk/qcom/gcc-ipq8074.c ++++ b/drivers/clk/qcom/gcc-ipq8074.c +@@ -4665,6 +4665,20 @@ 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_PPE_FULL_RESET] = { .reg = 0x68014, .bitmask = GENMASK(19, 16) }, ++ [GCC_UNIPHY0_SOFT_RESET] = { .reg = 0x56004, .bitmask = GENMASK(13, 4) | BIT(1) }, ++ [GCC_UNIPHY0_XPCS_RESET] = { 0x56004, 2 }, ++ [GCC_UNIPHY1_SOFT_RESET] = { .reg = 0x56104, .bitmask = GENMASK(5, 4) | BIT(1) }, ++ [GCC_UNIPHY1_XPCS_RESET] = { 0x56104, 2 }, ++ [GCC_UNIPHY2_SOFT_RESET] = { .reg = 0x56204, .bitmask = GENMASK(5, 4) | BIT(1) }, ++ [GCC_UNIPHY2_XPCS_RESET] = { 0x56204, 2 }, ++ [GCC_EDMA_HW_RESET] = { .reg = 0x68014, .bitmask = GENMASK(21, 20) }, ++ [GCC_NSSPORT1_RESET] = { .reg = 0x68014, .bitmask = BIT(24) | GENMASK(1, 0) }, ++ [GCC_NSSPORT2_RESET] = { .reg = 0x68014, .bitmask = BIT(25) | GENMASK(3, 2) }, ++ [GCC_NSSPORT3_RESET] = { .reg = 0x68014, .bitmask = BIT(26) | GENMASK(5, 4) }, ++ [GCC_NSSPORT4_RESET] = { .reg = 0x68014, .bitmask = BIT(27) | GENMASK(9, 8) }, ++ [GCC_NSSPORT5_RESET] = { .reg = 0x68014, .bitmask = BIT(28) | GENMASK(11, 10) }, ++ [GCC_NSSPORT6_RESET] = { .reg = 0x68014, .bitmask = BIT(29) | GENMASK(13, 12) }, + }; + + static struct gdsc *gcc_ipq8074_gdscs[] = { diff --git a/target/linux/qualcommax/patches-6.1/0011-v6.2-clk-qcom-ipq8074-populate-fw_name-for-all-parents.patch b/target/linux/qualcommax/patches-6.1/0011-v6.2-clk-qcom-ipq8074-populate-fw_name-for-all-parents.patch new file mode 100644 index 000000000..35a0a07c7 --- /dev/null +++ b/target/linux/qualcommax/patches-6.1/0011-v6.2-clk-qcom-ipq8074-populate-fw_name-for-all-parents.patch @@ -0,0 +1,152 @@ +From 78936d46470938caa9a7ea529deeb36777b4f98e Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Wed, 16 Nov 2022 22:46:55 +0100 +Subject: [PATCH] clk: qcom: ipq8074: populate fw_name for all parents + +It appears that having only .name populated in parent_data for clocks +which are only globally searchable currently will not work as the clk core +won't copy that name if there is no .fw_name present as well. + +So, populate .fw_name for all parent clocks in parent_data. + +Fixes: ae55ad32e273 ("clk: qcom: ipq8074: convert to parent data") + +Co-developed-by: Christian Marangi +Signed-off-by: Christian Marangi +Signed-off-by: Robert Marko +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20221116214655.1116467-1-robimarko@gmail.com +--- + drivers/clk/qcom/gcc-ipq8074.c | 52 +++++++++++++++++----------------- + 1 file changed, 26 insertions(+), 26 deletions(-) + +--- a/drivers/clk/qcom/gcc-ipq8074.c ++++ b/drivers/clk/qcom/gcc-ipq8074.c +@@ -674,7 +674,7 @@ static struct clk_rcg2 pcie0_aux_clk_src + }; + + static const struct clk_parent_data gcc_pcie20_phy0_pipe_clk_xo[] = { +- { .name = "pcie20_phy0_pipe_clk" }, ++ { .fw_name = "pcie0_pipe", .name = "pcie20_phy0_pipe_clk" }, + { .fw_name = "xo", .name = "xo" }, + }; + +@@ -727,7 +727,7 @@ static struct clk_rcg2 pcie1_aux_clk_src + }; + + static const struct clk_parent_data gcc_pcie20_phy1_pipe_clk_xo[] = { +- { .name = "pcie20_phy1_pipe_clk" }, ++ { .fw_name = "pcie1_pipe", .name = "pcie20_phy1_pipe_clk" }, + { .fw_name = "xo", .name = "xo" }, + }; + +@@ -1131,7 +1131,7 @@ static const struct freq_tbl ftbl_nss_no + + static const struct clk_parent_data gcc_xo_bias_pll_nss_noc_clk_gpll0_gpll2[] = { + { .fw_name = "xo", .name = "xo" }, +- { .name = "bias_pll_nss_noc_clk" }, ++ { .fw_name = "bias_pll_nss_noc_clk", .name = "bias_pll_nss_noc_clk" }, + { .hw = &gpll0.clkr.hw }, + { .hw = &gpll2.clkr.hw }, + }; +@@ -1356,7 +1356,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", .name = "xo" }, +- { .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 }, +@@ -1407,10 +1407,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", .name = "xo" }, +- { .name = "uniphy0_gcc_rx_clk" }, +- { .name = "uniphy0_gcc_tx_clk" }, ++ { .fw_name = "uniphy0_gcc_rx_clk", .name = "uniphy0_gcc_rx_clk" }, ++ { .fw_name = "uniphy0_gcc_tx_clk", .name = "uniphy0_gcc_tx_clk" }, + { .hw = &ubi32_pll.clkr.hw }, +- { .name = "bias_pll_cc_clk" }, ++ { .fw_name = "bias_pll_cc_clk", .name = "bias_pll_cc_clk" }, + }; + + static const struct parent_map gcc_xo_uniphy0_rx_tx_ubi32_bias_map[] = { +@@ -1459,10 +1459,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", .name = "xo" }, +- { .name = "uniphy0_gcc_tx_clk" }, +- { .name = "uniphy0_gcc_rx_clk" }, ++ { .fw_name = "uniphy0_gcc_tx_clk", .name = "uniphy0_gcc_tx_clk" }, ++ { .fw_name = "uniphy0_gcc_rx_clk", .name = "uniphy0_gcc_rx_clk" }, + { .hw = &ubi32_pll.clkr.hw }, +- { .name = "bias_pll_cc_clk" }, ++ { .fw_name = "bias_pll_cc_clk", .name = "bias_pll_cc_clk" }, + }; + + static const struct parent_map gcc_xo_uniphy0_tx_rx_ubi32_bias_map[] = { +@@ -1690,12 +1690,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", .name = "xo" }, +- { .name = "uniphy0_gcc_rx_clk" }, +- { .name = "uniphy0_gcc_tx_clk" }, +- { .name = "uniphy1_gcc_rx_clk" }, +- { .name = "uniphy1_gcc_tx_clk" }, ++ { .fw_name = "uniphy0_gcc_rx_clk", .name = "uniphy0_gcc_rx_clk" }, ++ { .fw_name = "uniphy0_gcc_tx_clk", .name = "uniphy0_gcc_tx_clk" }, ++ { .fw_name = "uniphy1_gcc_rx_clk", .name = "uniphy1_gcc_rx_clk" }, ++ { .fw_name = "uniphy1_gcc_tx_clk", .name = "uniphy1_gcc_tx_clk" }, + { .hw = &ubi32_pll.clkr.hw }, +- { .name = "bias_pll_cc_clk" }, ++ { .fw_name = "bias_pll_cc_clk", .name = "bias_pll_cc_clk" }, + }; + + static const struct parent_map +@@ -1752,12 +1752,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", .name = "xo" }, +- { .name = "uniphy0_gcc_tx_clk" }, +- { .name = "uniphy0_gcc_rx_clk" }, +- { .name = "uniphy1_gcc_tx_clk" }, +- { .name = "uniphy1_gcc_rx_clk" }, ++ { .fw_name = "uniphy0_gcc_tx_clk", .name = "uniphy0_gcc_tx_clk" }, ++ { .fw_name = "uniphy0_gcc_rx_clk", .name = "uniphy0_gcc_rx_clk" }, ++ { .fw_name = "uniphy1_gcc_tx_clk", .name = "uniphy1_gcc_tx_clk" }, ++ { .fw_name = "uniphy1_gcc_rx_clk", .name = "uniphy1_gcc_rx_clk" }, + { .hw = &ubi32_pll.clkr.hw }, +- { .name = "bias_pll_cc_clk" }, ++ { .fw_name = "bias_pll_cc_clk", .name = "bias_pll_cc_clk" }, + }; + + static const struct parent_map +@@ -1814,10 +1814,10 @@ static const struct freq_tbl ftbl_nss_po + + static const struct clk_parent_data gcc_xo_uniphy2_rx_tx_ubi32_bias[] = { + { .fw_name = "xo", .name = "xo" }, +- { .name = "uniphy2_gcc_rx_clk" }, +- { .name = "uniphy2_gcc_tx_clk" }, ++ { .fw_name = "uniphy2_gcc_rx_clk", .name = "uniphy2_gcc_rx_clk" }, ++ { .fw_name = "uniphy2_gcc_tx_clk", .name = "uniphy2_gcc_tx_clk" }, + { .hw = &ubi32_pll.clkr.hw }, +- { .name = "bias_pll_cc_clk" }, ++ { .fw_name = "bias_pll_cc_clk", .name = "bias_pll_cc_clk" }, + }; + + static const struct parent_map gcc_xo_uniphy2_rx_tx_ubi32_bias_map[] = { +@@ -1871,10 +1871,10 @@ static const struct freq_tbl ftbl_nss_po + + static const struct clk_parent_data gcc_xo_uniphy2_tx_rx_ubi32_bias[] = { + { .fw_name = "xo", .name = "xo" }, +- { .name = "uniphy2_gcc_tx_clk" }, +- { .name = "uniphy2_gcc_rx_clk" }, ++ { .fw_name = "uniphy2_gcc_tx_clk", .name = "uniphy2_gcc_tx_clk" }, ++ { .fw_name = "uniphy2_gcc_rx_clk", .name = "uniphy2_gcc_rx_clk" }, + { .hw = &ubi32_pll.clkr.hw }, +- { .name = "bias_pll_cc_clk" }, ++ { .fw_name = "bias_pll_cc_clk", .name = "bias_pll_cc_clk" }, + }; + + static const struct parent_map gcc_xo_uniphy2_tx_rx_ubi32_bias_map[] = { diff --git a/target/linux/qualcommax/patches-6.1/0012-v6.2-arm64-dts-qcom-ipq8074-pass-XO-and-sleep-clocks-to-G.patch b/target/linux/qualcommax/patches-6.1/0012-v6.2-arm64-dts-qcom-ipq8074-pass-XO-and-sleep-clocks-to-G.patch new file mode 100644 index 000000000..1f99de002 --- /dev/null +++ b/target/linux/qualcommax/patches-6.1/0012-v6.2-arm64-dts-qcom-ipq8074-pass-XO-and-sleep-clocks-to-G.patch @@ -0,0 +1,36 @@ +From 9033c3c86ea0dd35bd2ab957317573b755967298 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Sun, 30 Oct 2022 18:57:03 +0100 +Subject: [PATCH] arm64: dts: qcom: ipq8074: pass XO and sleep clocks to GCC + +Pass XO and sleep clocks to the GCC controller so it does not have to +find them by matching globaly by name. + +If not passed directly, driver maintains backwards compatibility by then +falling back to global lookup. + +Since we are here, set cell numbers in decimal instead of hex. + +Signed-off-by: Robert Marko +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20221030175703.1103224-3-robimarko@gmail.com +--- + arch/arm64/boot/dts/qcom/ipq8074.dtsi | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi ++++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi +@@ -361,9 +361,11 @@ + gcc: gcc@1800000 { + compatible = "qcom,gcc-ipq8074"; + reg = <0x01800000 0x80000>; +- #clock-cells = <0x1>; ++ clocks = <&xo>, <&sleep_clk>; ++ clock-names = "xo", "sleep_clk"; ++ #clock-cells = <1>; + #power-domain-cells = <1>; +- #reset-cells = <0x1>; ++ #reset-cells = <1>; + }; + + tcsr_mutex: hwlock@1905000 { diff --git a/target/linux/qualcommax/patches-6.1/0013-v6.2-arm64-dts-qcom-add-PMP8074-DTSI.patch b/target/linux/qualcommax/patches-6.1/0013-v6.2-arm64-dts-qcom-add-PMP8074-DTSI.patch new file mode 100644 index 000000000..cd146420c --- /dev/null +++ b/target/linux/qualcommax/patches-6.1/0013-v6.2-arm64-dts-qcom-add-PMP8074-DTSI.patch @@ -0,0 +1,149 @@ +From fb76b808f8628215afebaf0f8af0bde635302590 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Fri, 19 Aug 2022 00:18:14 +0200 +Subject: [PATCH] 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 +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20220818221815.346233-4-robimarko@gmail.com +--- + 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/qualcommax/patches-6.1/0014-v6.2-arm64-dts-qcom-ipq8074-hk01-add-VQMMC-supply.patch b/target/linux/qualcommax/patches-6.1/0014-v6.2-arm64-dts-qcom-ipq8074-hk01-add-VQMMC-supply.patch new file mode 100644 index 000000000..ebd3763a5 --- /dev/null +++ b/target/linux/qualcommax/patches-6.1/0014-v6.2-arm64-dts-qcom-ipq8074-hk01-add-VQMMC-supply.patch @@ -0,0 +1,37 @@ +From 2c394cfc1779886048feca7dc7f4075da5f6328c Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Fri, 19 Aug 2022 00:18:15 +0200 +Subject: [PATCH] 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 +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20220818221815.346233-5-robimarko@gmail.com +--- + 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"; +@@ -84,6 +85,7 @@ + + &sdhc_1 { + status = "okay"; ++ vqmmc-supply = <&l11>; + }; + + &qusb_phy_0 { diff --git a/target/linux/qualcommax/patches-6.1/0015-v6.2-arm64-dts-qcom-hk01-use-GPIO-flags-for-tlmm.patch b/target/linux/qualcommax/patches-6.1/0015-v6.2-arm64-dts-qcom-hk01-use-GPIO-flags-for-tlmm.patch new file mode 100644 index 000000000..e08f6d1f3 --- /dev/null +++ b/target/linux/qualcommax/patches-6.1/0015-v6.2-arm64-dts-qcom-hk01-use-GPIO-flags-for-tlmm.patch @@ -0,0 +1,42 @@ +From 82ceb86227b1fc15c76d5fc691b2bf425f1a63b3 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Mon, 7 Nov 2022 10:29:30 +0100 +Subject: [PATCH] arm64: dts: qcom: hk01: use GPIO flags for tlmm + +Use respective GPIO_ACTIVE_LOW/HIGH flags for tlmm GPIOs instead of +harcoding the cell value. + +Signed-off-by: Robert Marko +Reviewed-by: Krzysztof Kozlowski +Reviewed-by: Konrad Dybcio +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20221107092930.33325-3-robimarko@gmail.com +--- + arch/arm64/boot/dts/qcom/ipq8074-hk01.dts | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +--- a/arch/arm64/boot/dts/qcom/ipq8074-hk01.dts ++++ b/arch/arm64/boot/dts/qcom/ipq8074-hk01.dts +@@ -4,6 +4,7 @@ + */ + #include "ipq8074.dtsi" + #include "pmp8074.dtsi" ++#include + + / { + model = "Qualcomm Technologies, Inc. IPQ8074-HK01"; +@@ -52,12 +53,12 @@ + + &pcie0 { + status = "okay"; +- perst-gpios = <&tlmm 61 0x1>; ++ perst-gpios = <&tlmm 61 GPIO_ACTIVE_LOW>; + }; + + &pcie1 { + status = "okay"; +- perst-gpios = <&tlmm 58 0x1>; ++ perst-gpios = <&tlmm 58 GPIO_ACTIVE_LOW>; + }; + + &pcie_qmp0 { diff --git a/target/linux/qualcommax/patches-6.1/0016-v6.2-arm64-dts-qcom-ipq8074-Fix-up-comments.patch b/target/linux/qualcommax/patches-6.1/0016-v6.2-arm64-dts-qcom-ipq8074-Fix-up-comments.patch new file mode 100644 index 000000000..a8bf2492f --- /dev/null +++ b/target/linux/qualcommax/patches-6.1/0016-v6.2-arm64-dts-qcom-ipq8074-Fix-up-comments.patch @@ -0,0 +1,82 @@ +From 1b1c1423ca3e740984aa883512a72c4ea08fbe28 Mon Sep 17 00:00:00 2001 +From: Konrad Dybcio +Date: Mon, 7 Nov 2022 15:55:17 +0100 +Subject: [PATCH] arm64: dts: qcom: ipq8074-*: Fix up comments + +Make sure all multiline C-style commends begin with just '/*' with +the comment text starting on a new line. + +Also, fix up some whitespace within comments. + +Signed-off-by: Konrad Dybcio +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20221107145522.6706-8-konrad.dybcio@linaro.org +--- + arch/arm64/boot/dts/qcom/ipq8074-hk01.dts | 3 ++- + arch/arm64/boot/dts/qcom/ipq8074-hk10-c1.dts | 3 ++- + arch/arm64/boot/dts/qcom/ipq8074-hk10-c2.dts | 3 ++- + arch/arm64/boot/dts/qcom/ipq8074.dtsi | 12 ++++++------ + 4 files changed, 12 insertions(+), 9 deletions(-) + +--- a/arch/arm64/boot/dts/qcom/ipq8074-hk01.dts ++++ b/arch/arm64/boot/dts/qcom/ipq8074-hk01.dts +@@ -1,6 +1,7 @@ + // SPDX-License-Identifier: GPL-2.0-only + /dts-v1/; +-/* Copyright (c) 2017, The Linux Foundation. All rights reserved. ++/* ++ * Copyright (c) 2017, The Linux Foundation. All rights reserved. + */ + #include "ipq8074.dtsi" + #include "pmp8074.dtsi" +--- a/arch/arm64/boot/dts/qcom/ipq8074-hk10-c1.dts ++++ b/arch/arm64/boot/dts/qcom/ipq8074-hk10-c1.dts +@@ -1,5 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0-only +-/* Copyright (c) 2020 The Linux Foundation. All rights reserved. ++/* ++ * Copyright (c) 2020 The Linux Foundation. All rights reserved. + */ + /dts-v1/; + +--- a/arch/arm64/boot/dts/qcom/ipq8074-hk10-c2.dts ++++ b/arch/arm64/boot/dts/qcom/ipq8074-hk10-c2.dts +@@ -1,6 +1,7 @@ + // SPDX-License-Identifier: GPL-2.0-only + /dts-v1/; +-/* Copyright (c) 2020 The Linux Foundation. All rights reserved. ++/* ++ * Copyright (c) 2020 The Linux Foundation. All rights reserved. + */ + #include "ipq8074-hk10.dtsi" + +--- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi ++++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi +@@ -129,10 +129,10 @@ + status = "disabled"; + + usb1_ssphy: phy@58200 { +- reg = <0x00058200 0x130>, /* Tx */ ++ reg = <0x00058200 0x130>, /* Tx */ + <0x00058400 0x200>, /* Rx */ +- <0x00058800 0x1f8>, /* PCS */ +- <0x00058600 0x044>; /* PCS misc*/ ++ <0x00058800 0x1f8>, /* PCS */ ++ <0x00058600 0x044>; /* PCS misc */ + #phy-cells = <0>; + #clock-cells = <0>; + clocks = <&gcc GCC_USB1_PIPE_CLK>; +@@ -172,10 +172,10 @@ + status = "disabled"; + + usb0_ssphy: phy@78200 { +- reg = <0x00078200 0x130>, /* Tx */ ++ reg = <0x00078200 0x130>, /* Tx */ + <0x00078400 0x200>, /* Rx */ +- <0x00078800 0x1f8>, /* PCS */ +- <0x00078600 0x044>; /* PCS misc*/ ++ <0x00078800 0x1f8>, /* PCS */ ++ <0x00078600 0x044>; /* PCS misc */ + #phy-cells = <0>; + #clock-cells = <0>; + clocks = <&gcc GCC_USB0_PIPE_CLK>; diff --git a/target/linux/qualcommax/patches-6.1/0017-v6.2-arm64-dts-qcom-ipq8074-align-TLMM-pin-configuration-.patch b/target/linux/qualcommax/patches-6.1/0017-v6.2-arm64-dts-qcom-ipq8074-align-TLMM-pin-configuration-.patch new file mode 100644 index 000000000..1ce114068 --- /dev/null +++ b/target/linux/qualcommax/patches-6.1/0017-v6.2-arm64-dts-qcom-ipq8074-align-TLMM-pin-configuration-.patch @@ -0,0 +1,60 @@ +From 5f20690f77878b1ba24ec88df01b92d5131a6780 Mon Sep 17 00:00:00 2001 +From: Krzysztof Kozlowski +Date: Tue, 8 Nov 2022 15:23:57 +0100 +Subject: [PATCH] arm64: dts: qcom: ipq8074: align TLMM pin configuration with + DT schema + +DT schema expects TLMM pin configuration nodes to be named with +'-state' suffix and their optional children with '-pins' suffix. + +Signed-off-by: Krzysztof Kozlowski +Reviewed-by: Konrad Dybcio +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20221108142357.67202-2-krzysztof.kozlowski@linaro.org +--- + arch/arm64/boot/dts/qcom/ipq8074.dtsi | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +--- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi ++++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi +@@ -318,35 +318,35 @@ + interrupt-controller; + #interrupt-cells = <0x2>; + +- serial_4_pins: serial4-pinmux { ++ serial_4_pins: serial4-state { + pins = "gpio23", "gpio24"; + function = "blsp4_uart1"; + drive-strength = <8>; + bias-disable; + }; + +- i2c_0_pins: i2c-0-pinmux { ++ i2c_0_pins: i2c-0-state { + pins = "gpio42", "gpio43"; + function = "blsp1_i2c"; + drive-strength = <8>; + bias-disable; + }; + +- spi_0_pins: spi-0-pins { ++ spi_0_pins: spi-0-state { + pins = "gpio38", "gpio39", "gpio40", "gpio41"; + function = "blsp0_spi"; + drive-strength = <8>; + bias-disable; + }; + +- hsuart_pins: hsuart-pins { ++ hsuart_pins: hsuart-state { + pins = "gpio46", "gpio47", "gpio48", "gpio49"; + function = "blsp2_uart"; + drive-strength = <8>; + bias-disable; + }; + +- qpic_pins: qpic-pins { ++ qpic_pins: qpic-state { + pins = "gpio1", "gpio3", "gpio4", + "gpio5", "gpio6", "gpio7", + "gpio8", "gpio10", "gpio11", diff --git a/target/linux/qualcommax/patches-6.1/0019-v6.3-arm64-dts-qcom-ipq8074-set-Gen2-PCIe-pcie-max-link-s.patch b/target/linux/qualcommax/patches-6.1/0019-v6.3-arm64-dts-qcom-ipq8074-set-Gen2-PCIe-pcie-max-link-s.patch new file mode 100644 index 000000000..8719bf74c --- /dev/null +++ b/target/linux/qualcommax/patches-6.1/0019-v6.3-arm64-dts-qcom-ipq8074-set-Gen2-PCIe-pcie-max-link-s.patch @@ -0,0 +1,24 @@ +From a4748d2850783d36f77ccf2b5fcc86ccf1800ef1 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Wed, 16 Nov 2022 22:48:36 +0100 +Subject: [PATCH] arm64: dts: qcom: ipq8074: set Gen2 PCIe pcie max-link-speed + +Add the generic 'max-link-speed' property to describe the Gen2 PCIe link +generation limit. +This allows the generic DWC code to configure the link speed correctly. + +Signed-off-by: Robert Marko +--- + 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 +@@ -766,6 +766,7 @@ + linux,pci-domain = <1>; + bus-range = <0x00 0xff>; + num-lanes = <1>; ++ max-link-speed = <2>; + #address-cells = <3>; + #size-cells = <2>; + diff --git a/target/linux/qualcommax/patches-6.1/0020-v6.3-PCI-qcom-Add-support-for-IPQ8074-Gen3-port.patch b/target/linux/qualcommax/patches-6.1/0020-v6.3-PCI-qcom-Add-support-for-IPQ8074-Gen3-port.patch new file mode 100644 index 000000000..3d5c2182e --- /dev/null +++ b/target/linux/qualcommax/patches-6.1/0020-v6.3-PCI-qcom-Add-support-for-IPQ8074-Gen3-port.patch @@ -0,0 +1,26 @@ +From f356132229b18ceef5d5ef9103bbaa9bdeb84c8d Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Fri, 13 Jan 2023 17:44:47 +0100 +Subject: [PATCH] PCI: qcom: Add IPQ8074 Gen3 port support + +IPQ8074 has one Gen2 and one Gen3 port, with Gen2 port already supported. +Add compatible for Gen3 port which uses the same controller as IPQ6018. + +Link: https://lore.kernel.org/r/20230113164449.906002-7-robimarko@gmail.com +Signed-off-by: Robert Marko +Signed-off-by: Lorenzo Pieralisi +Signed-off-by: Bjorn Helgaas +--- + drivers/pci/controller/dwc/pcie-qcom.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/pci/controller/dwc/pcie-qcom.c ++++ b/drivers/pci/controller/dwc/pcie-qcom.c +@@ -1762,6 +1762,7 @@ static const struct of_device_id qcom_pc + { .compatible = "qcom,pcie-ipq8064", .data = &cfg_2_1_0 }, + { .compatible = "qcom,pcie-ipq8064-v2", .data = &cfg_2_1_0 }, + { .compatible = "qcom,pcie-ipq8074", .data = &cfg_2_3_3 }, ++ { .compatible = "qcom,pcie-ipq8074-gen3", .data = &cfg_2_9_0 }, + { .compatible = "qcom,pcie-msm8996", .data = &cfg_2_3_2 }, + { .compatible = "qcom,pcie-qcs404", .data = &cfg_2_4_0 }, + { .compatible = "qcom,pcie-sa8540p", .data = &cfg_1_9_0 }, diff --git a/target/linux/qualcommax/patches-6.1/0021-v6.3-clk-qcom-ipq8074-populate-fw_name-for-usb3phy-s.patch b/target/linux/qualcommax/patches-6.1/0021-v6.3-clk-qcom-ipq8074-populate-fw_name-for-usb3phy-s.patch new file mode 100644 index 000000000..e0e8125ba --- /dev/null +++ b/target/linux/qualcommax/patches-6.1/0021-v6.3-clk-qcom-ipq8074-populate-fw_name-for-usb3phy-s.patch @@ -0,0 +1,38 @@ +From 614d31c231c7707322b643f409eeb7e28adc7f8c Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Sun, 8 Jan 2023 13:36:28 +0100 +Subject: [PATCH] clk: qcom: ipq8074: populate fw_name for usb3phy-s + +Having only .name populated in parent_data for clocks which are only +globally searchable currently will not work as the clk core won't copy +that name if there is no .fw_name present as well. + +So, populate .fw_name for usb3phy clocks in parent_data as they were +missed by me in ("clk: qcom: ipq8074: populate fw_name for all parents"). + +Fixes: ae55ad32e273 ("clk: qcom: ipq8074: convert to parent data") +Signed-off-by: Robert Marko +--- + drivers/clk/qcom/gcc-ipq8074.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/clk/qcom/gcc-ipq8074.c ++++ b/drivers/clk/qcom/gcc-ipq8074.c +@@ -928,7 +928,7 @@ static struct clk_rcg2 usb0_mock_utmi_cl + }; + + static const struct clk_parent_data gcc_usb3phy_0_cc_pipe_clk_xo[] = { +- { .name = "usb3phy_0_cc_pipe_clk" }, ++ { .fw_name = "usb3phy_0_cc_pipe_clk", .name = "usb3phy_0_cc_pipe_clk" }, + { .fw_name = "xo", .name = "xo" }, + }; + +@@ -996,7 +996,7 @@ static struct clk_rcg2 usb1_mock_utmi_cl + }; + + static const struct clk_parent_data gcc_usb3phy_1_cc_pipe_clk_xo[] = { +- { .name = "usb3phy_1_cc_pipe_clk" }, ++ { .fw_name = "usb3phy_1_cc_pipe_clk", .name = "usb3phy_1_cc_pipe_clk" }, + { .fw_name = "xo", .name = "xo" }, + }; + diff --git a/target/linux/qualcommax/patches-6.1/0023-v6.5-arm64-dts-qcom-ipq8074-add-critical-thermal-trips.patch b/target/linux/qualcommax/patches-6.1/0023-v6.5-arm64-dts-qcom-ipq8074-add-critical-thermal-trips.patch new file mode 100644 index 000000000..e2b4d73e3 --- /dev/null +++ b/target/linux/qualcommax/patches-6.1/0023-v6.5-arm64-dts-qcom-ipq8074-add-critical-thermal-trips.patch @@ -0,0 +1,199 @@ +From 56d3067cb694ba60d654e7f5ef231b6fabc4697f Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Wed, 7 Jun 2023 20:44:48 +0200 +Subject: [PATCH] arm64: dts: qcom: ipq8074: add critical thermal trips + +According to bindings, thermal zones must have associated trips as well. +Since we currently dont have CPUFreq support and thus no passive cooling +lets start by defining critical trips to protect the devices against +severe overheating. + +Signed-off-by: Robert Marko +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20230607184448.2512179-1-robimarko@gmail.com +--- + 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 +@@ -897,6 +897,14 @@ + polling-delay = <1000>; + + thermal-sensors = <&tsens 4>; ++ ++ trips { ++ nss-top-crit { ++ temperature = <110000>; ++ hysteresis = <1000>; ++ type = "critical"; ++ }; ++ }; + }; + + nss0-thermal { +@@ -904,6 +912,14 @@ + polling-delay = <1000>; + + thermal-sensors = <&tsens 5>; ++ ++ trips { ++ nss-0-crit { ++ temperature = <110000>; ++ hysteresis = <1000>; ++ type = "critical"; ++ }; ++ }; + }; + + nss1-thermal { +@@ -911,6 +927,14 @@ + polling-delay = <1000>; + + thermal-sensors = <&tsens 6>; ++ ++ trips { ++ nss-1-crit { ++ temperature = <110000>; ++ hysteresis = <1000>; ++ type = "critical"; ++ }; ++ }; + }; + + wcss-phya0-thermal { +@@ -918,6 +942,14 @@ + polling-delay = <1000>; + + thermal-sensors = <&tsens 7>; ++ ++ trips { ++ wcss-phya0-crit { ++ temperature = <110000>; ++ hysteresis = <1000>; ++ type = "critical"; ++ }; ++ }; + }; + + wcss-phya1-thermal { +@@ -925,6 +957,14 @@ + polling-delay = <1000>; + + thermal-sensors = <&tsens 8>; ++ ++ trips { ++ wcss-phya1-crit { ++ temperature = <110000>; ++ hysteresis = <1000>; ++ type = "critical"; ++ }; ++ }; + }; + + cpu0_thermal: cpu0-thermal { +@@ -932,6 +972,14 @@ + polling-delay = <1000>; + + thermal-sensors = <&tsens 9>; ++ ++ trips { ++ cpu0-crit { ++ temperature = <110000>; ++ hysteresis = <1000>; ++ type = "critical"; ++ }; ++ }; + }; + + cpu1_thermal: cpu1-thermal { +@@ -939,6 +987,14 @@ + polling-delay = <1000>; + + thermal-sensors = <&tsens 10>; ++ ++ trips { ++ cpu1-crit { ++ temperature = <110000>; ++ hysteresis = <1000>; ++ type = "critical"; ++ }; ++ }; + }; + + cpu2_thermal: cpu2-thermal { +@@ -946,6 +1002,14 @@ + polling-delay = <1000>; + + thermal-sensors = <&tsens 11>; ++ ++ trips { ++ cpu2-crit { ++ temperature = <110000>; ++ hysteresis = <1000>; ++ type = "critical"; ++ }; ++ }; + }; + + cpu3_thermal: cpu3-thermal { +@@ -953,6 +1017,14 @@ + polling-delay = <1000>; + + thermal-sensors = <&tsens 12>; ++ ++ trips { ++ cpu3-crit { ++ temperature = <110000>; ++ hysteresis = <1000>; ++ type = "critical"; ++ }; ++ }; + }; + + cluster_thermal: cluster-thermal { +@@ -960,6 +1032,14 @@ + polling-delay = <1000>; + + thermal-sensors = <&tsens 13>; ++ ++ trips { ++ cluster-crit { ++ temperature = <110000>; ++ hysteresis = <1000>; ++ type = "critical"; ++ }; ++ }; + }; + + wcss-phyb0-thermal { +@@ -967,6 +1047,14 @@ + polling-delay = <1000>; + + thermal-sensors = <&tsens 14>; ++ ++ trips { ++ wcss-phyb0-crit { ++ temperature = <110000>; ++ hysteresis = <1000>; ++ type = "critical"; ++ }; ++ }; + }; + + wcss-phyb1-thermal { +@@ -974,6 +1062,14 @@ + polling-delay = <1000>; + + thermal-sensors = <&tsens 15>; ++ ++ trips { ++ wcss-phyb1-crit { ++ temperature = <110000>; ++ hysteresis = <1000>; ++ type = "critical"; ++ }; ++ }; + }; + }; + }; diff --git a/target/linux/qualcommax/patches-6.1/0024-v6.7-dt-bindings-arm-qcom-ids-Add-IDs-for-IPQ8174-family.patch b/target/linux/qualcommax/patches-6.1/0024-v6.7-dt-bindings-arm-qcom-ids-Add-IDs-for-IPQ8174-family.patch new file mode 100644 index 000000000..4eb0f097c --- /dev/null +++ b/target/linux/qualcommax/patches-6.1/0024-v6.7-dt-bindings-arm-qcom-ids-Add-IDs-for-IPQ8174-family.patch @@ -0,0 +1,29 @@ +From 93e161c8f4b9b051e5e746814138cb5520b4b897 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Fri, 1 Sep 2023 20:10:04 +0200 +Subject: [PATCH] dt-bindings: arm: qcom,ids: Add IDs for IPQ8174 family + +IPQ8174 (Oak) family is part of the IPQ8074 family, but the ID-s for it +are missing so lets add them. + +Signed-off-by: Robert Marko +Reviewed-by: Kathiravan T +Acked-by: Conor Dooley +Link: https://lore.kernel.org/r/20230901181041.1538999-1-robimarko@gmail.com +Signed-off-by: Bjorn Andersson +--- + include/dt-bindings/arm/qcom,ids.h | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/include/dt-bindings/arm/qcom,ids.h ++++ b/include/dt-bindings/arm/qcom,ids.h +@@ -121,6 +121,9 @@ + #define QCOM_ID_SM6125 394 + #define QCOM_ID_IPQ8070A 395 + #define QCOM_ID_IPQ8071A 396 ++#define QCOM_ID_IPQ8172 397 ++#define QCOM_ID_IPQ8173 398 ++#define QCOM_ID_IPQ8174 399 + #define QCOM_ID_IPQ6018 402 + #define QCOM_ID_IPQ6028 403 + #define QCOM_ID_IPQ6000 421 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/0025-v6.7-cpufreq-qcom-nvmem-add-support-for-IPQ8074.patch new file mode 100644 index 000000000..61cc2a459 --- /dev/null +++ b/target/linux/qualcommax/patches-6.1/0025-v6.7-cpufreq-qcom-nvmem-add-support-for-IPQ8074.patch @@ -0,0 +1,112 @@ +From df75a00c60c6e58bc36e4c63e9d7f1910412b132 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 + +IPQ8074 comes in 3 families: +* IPQ8070A/IPQ8071A (Acorn) up to 1.4GHz +* IPQ8172/IPQ8173/IPQ8174 (Oak) up to 1.4GHz +* IPQ8072A/IPQ8074A/IPQ8076A/IPQ8078A (Hawkeye) up to 2.2GHz + +So, in order to be able to share one OPP table lets add support for IPQ8074 +family based of SMEM SoC ID-s as speedbin fuse is always 0 on IPQ8074. + +IPQ8074 compatible is blacklisted from DT platdev as the cpufreq device +will get created by NVMEM CPUFreq driver. + +Signed-off-by: Robert Marko +Acked-by: Konrad Dybcio +Signed-off-by: Viresh Kumar +--- + drivers/cpufreq/cpufreq-dt-platdev.c | 1 + + drivers/cpufreq/qcom-cpufreq-nvmem.c | 48 ++++++++++++++++++++++++++++ + 2 files changed, 49 insertions(+) + +--- 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", }, + + { .compatible = "qcom,ipq8064", }, ++ { .compatible = "qcom,ipq8074", }, + { .compatible = "qcom,apq8064", }, + { .compatible = "qcom,msm8974", }, + { .compatible = "qcom,msm8960", }, +--- a/drivers/cpufreq/qcom-cpufreq-nvmem.c ++++ b/drivers/cpufreq/qcom-cpufreq-nvmem.c +@@ -31,6 +31,11 @@ + + #include + ++enum ipq8074_versions { ++ IPQ8074_HAWKEYE_VERSION = 0, ++ IPQ8074_ACORN_VERSION, ++}; ++ + struct qcom_cpufreq_drv; + + struct qcom_cpufreq_match_data { +@@ -204,6 +209,44 @@ len_error: + return ret; + } + ++static int qcom_cpufreq_ipq8074_name_version(struct device *cpu_dev, ++ struct nvmem_cell *speedbin_nvmem, ++ char **pvs_name, ++ struct qcom_cpufreq_drv *drv) ++{ ++ u32 msm_id; ++ int ret; ++ *pvs_name = NULL; ++ ++ ret = qcom_smem_get_soc_id(&msm_id); ++ if (ret) ++ return ret; ++ ++ switch (msm_id) { ++ case QCOM_ID_IPQ8070A: ++ case QCOM_ID_IPQ8071A: ++ case QCOM_ID_IPQ8172: ++ case QCOM_ID_IPQ8173: ++ case QCOM_ID_IPQ8174: ++ drv->versions = BIT(IPQ8074_ACORN_VERSION); ++ break; ++ case QCOM_ID_IPQ8072A: ++ case QCOM_ID_IPQ8074A: ++ case QCOM_ID_IPQ8076A: ++ case QCOM_ID_IPQ8078A: ++ drv->versions = BIT(IPQ8074_HAWKEYE_VERSION); ++ break; ++ default: ++ dev_err(cpu_dev, ++ "SoC ID %u is not part of IPQ8074 family, limiting to 1.4GHz!\n", ++ msm_id); ++ drv->versions = BIT(IPQ8074_ACORN_VERSION); ++ break; ++ } ++ ++ return 0; ++} ++ + 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, + }; + ++static const struct qcom_cpufreq_match_data match_data_ipq8074 = { ++ .get_version = qcom_cpufreq_ipq8074_name_version, ++}; ++ + 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 }, + { .compatible = "qcom,qcs404", .data = &match_data_qcs404 }, + { .compatible = "qcom,ipq8064", .data = &match_data_krait }, ++ { .compatible = "qcom,ipq8074", .data = &match_data_ipq8074 }, + { .compatible = "qcom,apq8064", .data = &match_data_krait }, + { .compatible = "qcom,msm8974", .data = &match_data_krait }, + { .compatible = "qcom,msm8960", .data = &match_data_krait }, diff --git a/target/linux/qualcommax/patches-6.1/0027-v6.7-clk-qcom-apss-ipq6018-add-the-GPLL0-clock-also-as-cl.patch b/target/linux/qualcommax/patches-6.1/0027-v6.7-clk-qcom-apss-ipq6018-add-the-GPLL0-clock-also-as-cl.patch new file mode 100644 index 000000000..ddd53f9d4 --- /dev/null +++ b/target/linux/qualcommax/patches-6.1/0027-v6.7-clk-qcom-apss-ipq6018-add-the-GPLL0-clock-also-as-cl.patch @@ -0,0 +1,43 @@ +From c917237a7cb17b97cc48e073881a9873f3caeaa2 Mon Sep 17 00:00:00 2001 +From: Kathiravan Thirumoorthy +Date: Thu, 14 Sep 2023 12:29:57 +0530 +Subject: [PATCH] clk: qcom: apss-ipq6018: add the GPLL0 clock also as clock + provider + +While the kernel is booting up, APSS PLL will be running at 800MHz with +GPLL0 as source. Once the cpufreq driver is available, APSS PLL will be +configured and select the rate based on the opp table and the source will +be changed to APSS_PLL_EARLY. + +Without this patch, CPU Freq driver reports that CPU is running at 24MHz +instead of the 800MHz. + +Reviewed-by: Konrad Dybcio +Tested-by: Robert Marko +Signed-off-by: Kathiravan Thirumoorthy +--- + drivers/clk/qcom/apss-ipq6018.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/clk/qcom/apss-ipq6018.c ++++ b/drivers/clk/qcom/apss-ipq6018.c +@@ -20,16 +20,19 @@ + + enum { + P_XO, ++ P_GPLL0, + P_APSS_PLL_EARLY, + }; + + static const struct clk_parent_data parents_apcs_alias0_clk_src[] = { + { .fw_name = "xo" }, ++ { .fw_name = "gpll0" }, + { .fw_name = "pll" }, + }; + + static const struct parent_map parents_apcs_alias0_clk_src_map[] = { + { P_XO, 0 }, ++ { P_GPLL0, 4 }, + { P_APSS_PLL_EARLY, 5 }, + }; + 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 new file mode 100644 index 000000000..5ae4fb567 --- /dev/null +++ b/target/linux/qualcommax/patches-6.1/0028-v6.7-arm64-dts-qcom-ipq8074-include-the-GPLL0-as-clock-pr.patch @@ -0,0 +1,32 @@ +From 3b48a7d925a757b3fa53c04baaf68bb8313c3ffb Mon Sep 17 00:00:00 2001 +From: Kathiravan Thirumoorthy +Date: Thu, 14 Sep 2023 12:29:58 +0530 +Subject: [PATCH] arm64: dts: qcom: ipq8074: include the GPLL0 as clock + provider for mailbox + +While the kernel is booting up, APSS PLL 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 +--- + 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 +@@ -682,8 +682,8 @@ + apcs_glb: mailbox@b111000 { + compatible = "qcom,ipq8074-apcs-apps-global"; + reg = <0x0b111000 0x1000>; +- clocks = <&a53pll>, <&xo>; +- clock-names = "pll", "xo"; ++ clocks = <&a53pll>, <&xo>, <&gcc GPLL0>; ++ clock-names = "pll", "xo", "gpll0"; + + #clock-cells = <1>; + #mbox-cells = <1>; diff --git a/target/linux/qualcommax/patches-6.1/0100-clk-qcom-clk-rcg2-introduce-support-for-multiple-con.patch b/target/linux/qualcommax/patches-6.1/0100-clk-qcom-clk-rcg2-introduce-support-for-multiple-con.patch new file mode 100644 index 000000000..9aa0a7952 --- /dev/null +++ b/target/linux/qualcommax/patches-6.1/0100-clk-qcom-clk-rcg2-introduce-support-for-multiple-con.patch @@ -0,0 +1,203 @@ +From 032be4f49dda786fea9e1501212f6cd09a7ded96 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Thu, 3 Nov 2022 14:49:43 +0100 +Subject: [PATCH] clk: qcom: clk-rcg2: introduce support for multiple conf for + same freq + +Some RCG frequency can be reached by multiple configuration. + +We currently declare multiple configuration for the same frequency but +that is not supported and always the first configuration will be taken. + +These multiple configuration are needed as based on the current parent +configuration, it may be needed to use a different configuration to +reach the same frequency. + +To handle this introduce 2 new macro, FM and C. + +- FM is used to declare an empty freq_tbl with just the frequency and an + array of confs to insert all the config for the provided frequency. + +- C is used to declare a fre_conf where src, pre_div, m and n are + provided. + +The driver is changed to handle this special freq_tbl and select the +correct config by calculating the final rate and deciding based on the +one that is less different than the requested one. + +Tested-by: Robert Marko +Signed-off-by: Christian Marangi +--- + drivers/clk/qcom/clk-rcg.h | 14 ++++++- + drivers/clk/qcom/clk-rcg2.c | 84 +++++++++++++++++++++++++++++++++---- + 2 files changed, 88 insertions(+), 10 deletions(-) + +--- a/drivers/clk/qcom/clk-rcg.h ++++ b/drivers/clk/qcom/clk-rcg.h +@@ -7,7 +7,17 @@ + #include + #include "clk-regmap.h" + +-#define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) } ++#define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n), 0, NULL } ++ ++#define FM(_f, _confs) { .freq = (_f), .confs_num = ARRAY_SIZE(_confs), .confs = (_confs) } ++#define C(s, h, m, n) { (s), (2 * (h) - 1), (m), (n) } ++ ++struct freq_conf { ++ u8 src; ++ u8 pre_div; ++ u16 m; ++ u16 n; ++}; + + struct freq_tbl { + unsigned long freq; +@@ -15,6 +25,8 @@ struct freq_tbl { + u8 pre_div; + u16 m; + u16 n; ++ int confs_num; ++ const struct freq_conf *confs; + }; + + /** +--- a/drivers/clk/qcom/clk-rcg2.c ++++ b/drivers/clk/qcom/clk-rcg2.c +@@ -203,11 +203,60 @@ clk_rcg2_recalc_rate(struct clk_hw *hw, + return __clk_rcg2_recalc_rate(hw, parent_rate, cfg); + } + ++static void ++clk_rcg2_select_conf(struct clk_hw *hw, struct freq_tbl *f_tbl, ++ const struct freq_tbl *f, unsigned long req_rate) ++{ ++ unsigned long best_rate = 0, parent_rate, rate; ++ const struct freq_conf *conf, *best_conf; ++ struct clk_rcg2 *rcg = to_clk_rcg2(hw); ++ struct clk_hw *p; ++ int index, i; ++ ++ /* Search in each provided config the one that is near the wanted rate */ ++ for (i = 0, conf = f->confs; i < f->confs_num; i++, conf++) { ++ index = qcom_find_src_index(hw, rcg->parent_map, conf->src); ++ if (index < 0) ++ continue; ++ ++ p = clk_hw_get_parent_by_index(hw, index); ++ if (!p) ++ continue; ++ ++ parent_rate = clk_hw_get_rate(p); ++ rate = calc_rate(parent_rate, conf->n, conf->m, conf->n, conf->pre_div); ++ ++ if (rate == req_rate) { ++ best_conf = conf; ++ break; ++ } ++ ++ if (abs(req_rate - rate) < abs(best_rate - rate)) { ++ best_rate = rate; ++ best_conf = conf; ++ } ++ } ++ ++ /* ++ * Very unlikely. ++ * Force the first conf if we can't find a correct config. ++ */ ++ if (unlikely(i == f->confs_num)) ++ best_conf = f->confs; ++ ++ /* Apply the config */ ++ f_tbl->src = best_conf->src; ++ f_tbl->pre_div = best_conf->pre_div; ++ f_tbl->m = best_conf->m; ++ f_tbl->n = best_conf->n; ++} ++ + static int _freq_tbl_determine_rate(struct clk_hw *hw, const struct freq_tbl *f, + struct clk_rate_request *req, + enum freq_policy policy) + { + unsigned long clk_flags, rate = req->rate; ++ struct freq_tbl f_tbl; + struct clk_hw *p; + struct clk_rcg2 *rcg = to_clk_rcg2(hw); + int index; +@@ -226,7 +275,15 @@ static int _freq_tbl_determine_rate(stru + if (!f) + return -EINVAL; + +- index = qcom_find_src_index(hw, rcg->parent_map, f->src); ++ f_tbl = *f; ++ /* ++ * A single freq may be reached by multiple configuration. ++ * Try to find the bast one if we have this kind of freq_table. ++ */ ++ if (f->confs) ++ clk_rcg2_select_conf(hw, &f_tbl, f, rate); ++ ++ index = qcom_find_src_index(hw, rcg->parent_map, f_tbl.src); + if (index < 0) + return index; + +@@ -236,18 +293,18 @@ static int _freq_tbl_determine_rate(stru + return -EINVAL; + + if (clk_flags & CLK_SET_RATE_PARENT) { +- rate = f->freq; +- if (f->pre_div) { ++ rate = f_tbl.freq; ++ if (f_tbl.pre_div) { + if (!rate) + rate = req->rate; + rate /= 2; +- rate *= f->pre_div + 1; ++ rate *= f_tbl.pre_div + 1; + } + +- if (f->n) { ++ if (f_tbl.n) { + u64 tmp = rate; +- tmp = tmp * f->n; +- do_div(tmp, f->m); ++ tmp = tmp * f_tbl.n; ++ do_div(tmp, f_tbl.m); + rate = tmp; + } + } else { +@@ -255,7 +312,7 @@ static int _freq_tbl_determine_rate(stru + } + req->best_parent_hw = p; + req->best_parent_rate = rate; +- req->rate = f->freq; ++ req->rate = f_tbl.freq; + + return 0; + } +@@ -351,6 +408,7 @@ static int __clk_rcg2_set_rate(struct cl + { + struct clk_rcg2 *rcg = to_clk_rcg2(hw); + const struct freq_tbl *f; ++ struct freq_tbl f_tbl; + + switch (policy) { + case FLOOR: +@@ -366,7 +424,15 @@ static int __clk_rcg2_set_rate(struct cl + if (!f) + return -EINVAL; + +- return clk_rcg2_configure(rcg, f); ++ f_tbl = *f; ++ /* ++ * A single freq may be reached by multiple configuration. ++ * Try to find the best one if we have this kind of freq_table. ++ */ ++ if (f->confs) ++ clk_rcg2_select_conf(hw, &f_tbl, f, rate); ++ ++ return clk_rcg2_configure(rcg, &f_tbl); + } + + static int clk_rcg2_set_rate(struct clk_hw *hw, unsigned long rate, diff --git a/target/linux/qualcommax/patches-6.1/0101-clk-qcom-gcc-ipq8074-rework-nss_port5-6-clock-to-mul.patch b/target/linux/qualcommax/patches-6.1/0101-clk-qcom-gcc-ipq8074-rework-nss_port5-6-clock-to-mul.patch new file mode 100644 index 000000000..62a30bbb2 --- /dev/null +++ b/target/linux/qualcommax/patches-6.1/0101-clk-qcom-gcc-ipq8074-rework-nss_port5-6-clock-to-mul.patch @@ -0,0 +1,129 @@ +From f778553f296792f4d1e8b3552603ad6116ea3eb3 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Thu, 3 Nov 2022 14:49:44 +0100 +Subject: [PATCH] clk: qcom: gcc-ipq8074: rework nss_port5/6 clock to multiple + conf + +Rework nss_port5/6 to use the new multiple configuration implementation +and correctly fix the clocks for these port under some corner case. + +This is particularly relevant for device that have 2.5G or 10G port +connected to port5 or port 6 on ipq8074. As the parent are shared +across multiple port it may be required to select the correct +configuration to accomplish the desired clock. Without this patch such +port doesn't work in some specific ethernet speed as the clock will be +set to the wrong frequency as we just select the first configuration for +the related frequency instead of selecting the best one. + +Tested-by: Robert Marko # ipq8074 Qnap QHora-301W +Signed-off-by: Christian Marangi +--- + drivers/clk/qcom/gcc-ipq8074.c | 64 +++++++++++++++++++++++++--------- + 1 file changed, 48 insertions(+), 16 deletions(-) + +--- a/drivers/clk/qcom/gcc-ipq8074.c ++++ b/drivers/clk/qcom/gcc-ipq8074.c +@@ -1676,13 +1676,21 @@ static struct clk_regmap_div nss_port4_t + }, + }; + ++static const struct freq_conf ftbl_nss_port5_rx_clk_src_25[] = { ++ C(P_UNIPHY1_RX, 12.5, 0, 0), ++ C(P_UNIPHY0_RX, 5, 0, 0), ++}; ++ ++static const struct freq_conf ftbl_nss_port5_rx_clk_src_125[] = { ++ C(P_UNIPHY1_RX, 2.5, 0, 0), ++ C(P_UNIPHY0_RX, 1, 0, 0), ++}; ++ + static const struct freq_tbl ftbl_nss_port5_rx_clk_src[] = { + F(19200000, P_XO, 1, 0, 0), +- F(25000000, P_UNIPHY1_RX, 12.5, 0, 0), +- F(25000000, P_UNIPHY0_RX, 5, 0, 0), ++ FM(25000000, ftbl_nss_port5_rx_clk_src_25), + F(78125000, P_UNIPHY1_RX, 4, 0, 0), +- F(125000000, P_UNIPHY1_RX, 2.5, 0, 0), +- F(125000000, P_UNIPHY0_RX, 1, 0, 0), ++ FM(125000000, ftbl_nss_port5_rx_clk_src_125), + F(156250000, P_UNIPHY1_RX, 2, 0, 0), + F(312500000, P_UNIPHY1_RX, 1, 0, 0), + { } +@@ -1738,13 +1746,21 @@ static struct clk_regmap_div nss_port5_r + }, + }; + ++static struct freq_conf ftbl_nss_port5_tx_clk_src_25[] = { ++ C(P_UNIPHY1_TX, 12.5, 0, 0), ++ C(P_UNIPHY0_TX, 5, 0, 0), ++}; ++ ++static struct freq_conf ftbl_nss_port5_tx_clk_src_125[] = { ++ C(P_UNIPHY1_TX, 2.5, 0, 0), ++ C(P_UNIPHY0_TX, 1, 0, 0), ++}; ++ + static const struct freq_tbl ftbl_nss_port5_tx_clk_src[] = { + F(19200000, P_XO, 1, 0, 0), +- F(25000000, P_UNIPHY1_TX, 12.5, 0, 0), +- F(25000000, P_UNIPHY0_TX, 5, 0, 0), ++ FM(25000000, ftbl_nss_port5_tx_clk_src_25), + F(78125000, P_UNIPHY1_TX, 4, 0, 0), +- F(125000000, P_UNIPHY1_TX, 2.5, 0, 0), +- F(125000000, P_UNIPHY0_TX, 1, 0, 0), ++ FM(125000000, ftbl_nss_port5_tx_clk_src_125), + F(156250000, P_UNIPHY1_TX, 2, 0, 0), + F(312500000, P_UNIPHY1_TX, 1, 0, 0), + { } +@@ -1800,13 +1816,21 @@ static struct clk_regmap_div nss_port5_t + }, + }; + ++static struct freq_conf ftbl_nss_port6_rx_clk_src_25[] = { ++ C(P_UNIPHY2_RX, 5, 0, 0), ++ C(P_UNIPHY2_RX, 12.5, 0, 0), ++}; ++ ++static struct freq_conf ftbl_nss_port6_rx_clk_src_125[] = { ++ C(P_UNIPHY2_RX, 1, 0, 0), ++ C(P_UNIPHY2_RX, 2.5, 0, 0), ++}; ++ + static const struct freq_tbl ftbl_nss_port6_rx_clk_src[] = { + F(19200000, P_XO, 1, 0, 0), +- F(25000000, P_UNIPHY2_RX, 5, 0, 0), +- F(25000000, P_UNIPHY2_RX, 12.5, 0, 0), ++ FM(25000000, ftbl_nss_port6_rx_clk_src_25), + F(78125000, P_UNIPHY2_RX, 4, 0, 0), +- F(125000000, P_UNIPHY2_RX, 1, 0, 0), +- F(125000000, P_UNIPHY2_RX, 2.5, 0, 0), ++ FM(125000000, ftbl_nss_port6_rx_clk_src_125), + F(156250000, P_UNIPHY2_RX, 2, 0, 0), + F(312500000, P_UNIPHY2_RX, 1, 0, 0), + { } +@@ -1857,13 +1881,21 @@ static struct clk_regmap_div nss_port6_r + }, + }; + ++static struct freq_conf ftbl_nss_port6_tx_clk_src_25[] = { ++ C(P_UNIPHY2_TX, 5, 0, 0), ++ C(P_UNIPHY2_TX, 12.5, 0, 0), ++}; ++ ++static struct freq_conf ftbl_nss_port6_tx_clk_src_125[] = { ++ C(P_UNIPHY2_TX, 1, 0, 0), ++ C(P_UNIPHY2_TX, 2.5, 0, 0), ++}; ++ + static const struct freq_tbl ftbl_nss_port6_tx_clk_src[] = { + F(19200000, P_XO, 1, 0, 0), +- F(25000000, P_UNIPHY2_TX, 5, 0, 0), +- F(25000000, P_UNIPHY2_TX, 12.5, 0, 0), ++ FM(25000000, ftbl_nss_port6_tx_clk_src_25), + F(78125000, P_UNIPHY2_TX, 4, 0, 0), +- F(125000000, P_UNIPHY2_TX, 1, 0, 0), +- F(125000000, P_UNIPHY2_TX, 2.5, 0, 0), ++ FM(125000000, ftbl_nss_port6_tx_clk_src_125), + F(156250000, P_UNIPHY2_TX, 2, 0, 0), + F(312500000, P_UNIPHY2_TX, 1, 0, 0), + { } diff --git a/target/linux/ipq807x/patches-5.15/0101-arm64-dts-ipq8074-add-reserved-memory-nodes.patch b/target/linux/qualcommax/patches-6.1/0102-arm64-dts-ipq8074-add-reserved-memory-nodes.patch similarity index 82% rename from target/linux/ipq807x/patches-5.15/0101-arm64-dts-ipq8074-add-reserved-memory-nodes.patch rename to target/linux/qualcommax/patches-6.1/0102-arm64-dts-ipq8074-add-reserved-memory-nodes.patch index cba302095..af53c077f 100644 --- a/target/linux/ipq807x/patches-5.15/0101-arm64-dts-ipq8074-add-reserved-memory-nodes.patch +++ b/target/linux/qualcommax/patches-6.1/0102-arm64-dts-ipq8074-add-reserved-memory-nodes.patch @@ -1,4 +1,4 @@ -From 4b6d5caa1747bbe0eca15d4d20f028748c544cd0 Mon Sep 17 00:00:00 2001 +From ad2d07f71739351eeea1d8a120c0918e2c4b265f Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Wed, 22 Dec 2021 12:23:34 +0100 Subject: [PATCH] arm64: dts: ipq8074: add reserved memory nodes @@ -14,12 +14,12 @@ devices with lower ammounts can override the Q6 node. Signed-off-by: Robert Marko --- - arch/arm64/boot/dts/qcom/ipq8074.dtsi | 40 +++++++++++++++++++++++++++ - 1 file changed, 40 insertions(+) + 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 -@@ -81,6 +81,31 @@ +@@ -85,6 +85,26 @@ #size-cells = <2>; ranges; @@ -42,18 +42,13 @@ Signed-off-by: Robert Marko + no-map; + reg = <0x0 0x4aa00000 0x0 0x00100000>; + }; -+ -+ tz@4ac00000 { -+ no-map; -+ reg = <0x0 0x4ac00000 0x0 0x00400000>; -+ }; + smem@4ab00000 { compatible = "qcom,smem"; reg = <0x0 0x4ab00000 0x0 0x00100000>; -@@ -88,6 +113,21 @@ - - hwlocks = <&tcsr_mutex 0>; +@@ -97,6 +117,21 @@ + no-map; + reg = <0x0 0x4ac00000 0x0 0x00400000>; }; + + q6_region: wcnss@4b000000 { diff --git a/target/linux/qualcommax/patches-6.1/0110-arm64-dts-qcom-ipq8074-pass-QMP-PCI-PHY-PIPE-clocks-.patch b/target/linux/qualcommax/patches-6.1/0110-arm64-dts-qcom-ipq8074-pass-QMP-PCI-PHY-PIPE-clocks-.patch new file mode 100644 index 000000000..bb3bd13eb --- /dev/null +++ b/target/linux/qualcommax/patches-6.1/0110-arm64-dts-qcom-ipq8074-pass-QMP-PCI-PHY-PIPE-clocks-.patch @@ -0,0 +1,30 @@ +From 8a576b5bc9f0555d1d970cacabcaa24a3b74fa57 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Wed, 16 Nov 2022 22:15:01 +0100 +Subject: [PATCH] arm64: dts: qcom: ipq8074: pass QMP PCI PHY PIPE clocks to + GCC + +Pass QMP PCI PHY PIPE clocks to the GCC controller so it does not have to +find them by matching globaly by name. + +If not passed directly, driver maintains backwards compatibility by then +falling back to global lookup. + +Signed-off-by: Robert Marko +--- + 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 +@@ -397,8 +397,8 @@ + gcc: gcc@1800000 { + compatible = "qcom,gcc-ipq8074"; + reg = <0x01800000 0x80000>; +- clocks = <&xo>, <&sleep_clk>; +- clock-names = "xo", "sleep_clk"; ++ clocks = <&xo>, <&sleep_clk>, <&pcie_phy0>, <&pcie_phy1>; ++ clock-names = "xo", "sleep_clk", "pcie0_pipe", "pcie1_pipe"; + #clock-cells = <1>; + #power-domain-cells = <1>; + #reset-cells = <1>; diff --git a/target/linux/qualcommax/patches-6.1/0111-arm64-dts-qcom-ipq8074-use-msi-parent-for-PCIe.patch b/target/linux/qualcommax/patches-6.1/0111-arm64-dts-qcom-ipq8074-use-msi-parent-for-PCIe.patch new file mode 100644 index 000000000..b0730dfa0 --- /dev/null +++ b/target/linux/qualcommax/patches-6.1/0111-arm64-dts-qcom-ipq8074-use-msi-parent-for-PCIe.patch @@ -0,0 +1,43 @@ +From fb1f6850be00d8dd8a54017be4c1336e224069ac Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Wed, 16 Nov 2022 22:26:25 +0100 +Subject: [PATCH] arm64: dts: qcom: ipq8074: use msi-parent for PCIe + +Instead of hardcoding the IRQ, simply use msi-parent instead. + +Signed-off-by: Robert Marko +--- + arch/arm64/boot/dts/qcom/ipq8074.dtsi | 8 +++----- + 1 file changed, 3 insertions(+), 5 deletions(-) + +--- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi ++++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi +@@ -704,7 +704,7 @@ + reg = <0x0b000000 0x1000>, <0x0b002000 0x1000>; + ranges = <0 0xb00a000 0xffd>; + +- v2m@0 { ++ gic_v2m0: v2m@0 { + compatible = "arm,gic-v2m-frame"; + msi-controller; + reg = <0x0 0xffd>; +@@ -817,8 +817,7 @@ + ranges = <0x81000000 0x0 0x00000000 0x10200000 0x0 0x10000>, /* I/O */ + <0x82000000 0x0 0x10220000 0x10220000 0x0 0xfde0000>; /* MEM */ + +- interrupts = ; +- interrupt-names = "msi"; ++ msi-parent = <&gic_v2m0>; + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 0x7>; + interrupt-map = <0 0 0 1 &intc 0 142 +@@ -879,8 +878,7 @@ + ranges = <0x81000000 0x0 0x00000000 0x20200000 0x0 0x10000>, /* I/O */ + <0x82000000 0x0 0x20220000 0x20220000 0x0 0xfde0000>; /* MEM */ + +- interrupts = ; +- interrupt-names = "msi"; ++ msi-parent = <&gic_v2m0>; + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 0x7>; + interrupt-map = <0 0 0 1 &intc 0 75 diff --git a/target/linux/ipq807x/patches-5.15/0111-remoteproc-qcom-Add-PRNG-proxy-clock.patch b/target/linux/qualcommax/patches-6.1/0112-remoteproc-qcom-Add-PRNG-proxy-clock.patch similarity index 95% rename from target/linux/ipq807x/patches-5.15/0111-remoteproc-qcom-Add-PRNG-proxy-clock.patch rename to target/linux/qualcommax/patches-6.1/0112-remoteproc-qcom-Add-PRNG-proxy-clock.patch index a5887464a..0a984948b 100644 --- a/target/linux/ipq807x/patches-5.15/0111-remoteproc-qcom-Add-PRNG-proxy-clock.patch +++ b/target/linux/qualcommax/patches-6.1/0112-remoteproc-qcom-Add-PRNG-proxy-clock.patch @@ -1,4 +1,4 @@ -From ddc957c5eee78cf41d04040b6de3e3437830b473 Mon Sep 17 00:00:00 2001 +From 125681433c8e526356947acf572fe8ca8ad32291 Mon Sep 17 00:00:00 2001 From: Gokul Sriram Palanisamy Date: Sat, 30 Jan 2021 10:50:05 +0530 Subject: [PATCH] remoteproc: qcom: Add PRNG proxy clock @@ -136,7 +136,7 @@ Signed-off-by: Nikhil Prakash V if (ret) goto free_rproc; } -@@ -1086,6 +1112,7 @@ static int q6v5_wcss_remove(struct platf +@@ -1087,6 +1113,7 @@ static int q6v5_wcss_remove(struct platf } static const struct wcss_data wcss_ipq8074_res_init = { @@ -144,7 +144,7 @@ Signed-off-by: Nikhil Prakash V .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 +@@ -1096,6 +1123,8 @@ static const struct wcss_data wcss_ipq80 }; static const struct wcss_data wcss_qcs404_res_init = { diff --git a/target/linux/ipq807x/patches-5.15/0112-remoteproc-qcom-Add-secure-PIL-support.patch b/target/linux/qualcommax/patches-6.1/0113-remoteproc-qcom-Add-secure-PIL-support.patch similarity index 96% rename from target/linux/ipq807x/patches-5.15/0112-remoteproc-qcom-Add-secure-PIL-support.patch rename to target/linux/qualcommax/patches-6.1/0113-remoteproc-qcom-Add-secure-PIL-support.patch index 067ac20aa..0328efc04 100644 --- a/target/linux/ipq807x/patches-5.15/0112-remoteproc-qcom-Add-secure-PIL-support.patch +++ b/target/linux/qualcommax/patches-6.1/0113-remoteproc-qcom-Add-secure-PIL-support.patch @@ -1,4 +1,4 @@ -From 3151bf7eb1350e3dd8a51424942d7365673a6e25 Mon Sep 17 00:00:00 2001 +From 7358d42dfbdfdb5d4f1d0d4c2e5c2bb4143a29b0 Mon Sep 17 00:00:00 2001 From: Gokul Sriram Palanisamy Date: Sat, 30 Jan 2021 10:50:06 +0530 Subject: [PATCH] remoteproc: qcom: Add secure PIL support @@ -133,7 +133,7 @@ Signed-off-by: Nikhil Prakash V ret = q6v5_wcss_init_mmio(wcss, pdev); if (ret) -@@ -1119,6 +1155,7 @@ static const struct wcss_data wcss_ipq80 +@@ -1120,6 +1156,7 @@ static const struct wcss_data wcss_ipq80 .wcss_q6_reset_required = true, .ops = &q6v5_wcss_ipq8074_ops, .requires_force_stop = true, diff --git a/target/linux/ipq807x/patches-5.15/0113-remoteproc-qcom-Add-support-for-split-q6-m3-wlan-fir.patch b/target/linux/qualcommax/patches-6.1/0114-remoteproc-qcom-Add-support-for-split-q6-m3-wlan-fir.patch similarity index 94% rename from target/linux/ipq807x/patches-5.15/0113-remoteproc-qcom-Add-support-for-split-q6-m3-wlan-fir.patch rename to target/linux/qualcommax/patches-6.1/0114-remoteproc-qcom-Add-support-for-split-q6-m3-wlan-fir.patch index 7cb8c1dcf..e5c9506c8 100644 --- a/target/linux/ipq807x/patches-5.15/0113-remoteproc-qcom-Add-support-for-split-q6-m3-wlan-fir.patch +++ b/target/linux/qualcommax/patches-6.1/0114-remoteproc-qcom-Add-support-for-split-q6-m3-wlan-fir.patch @@ -1,4 +1,4 @@ -From 0915eaecd5e06227c9e4e3a4a931c45942e7b4ed Mon Sep 17 00:00:00 2001 +From b422c9d4f048b086ce83f44a7cfcddcce162897f Mon Sep 17 00:00:00 2001 From: Gokul Sriram Palanisamy Date: Sat, 30 Jan 2021 10:50:07 +0530 Subject: [PATCH] remoteproc: qcom: Add support for split q6 + m3 wlan firmware @@ -82,7 +82,7 @@ Signed-off-by: Nikhil Prakash V ret = q6v5_wcss_init_mmio(wcss, pdev); if (ret) -@@ -1149,7 +1173,8 @@ static int q6v5_wcss_remove(struct platf +@@ -1150,7 +1174,8 @@ static int q6v5_wcss_remove(struct platf static const struct wcss_data wcss_ipq8074_res_init = { .init_clock = ipq8074_init_clock, @@ -92,7 +92,7 @@ Signed-off-by: Nikhil Prakash V .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 +@@ -1163,7 +1188,7 @@ static const struct wcss_data wcss_qcs40 .init_clock = qcs404_init_clock, .init_regulator = qcs404_init_regulator, .crash_reason_smem = WCSS_CRASH_REASON, diff --git a/target/linux/ipq807x/patches-5.15/0114-remoteproc-qcom-Add-ssr-subdevice-identifier.patch b/target/linux/qualcommax/patches-6.1/0115-remoteproc-qcom-Add-ssr-subdevice-identifier.patch similarity index 85% rename from target/linux/ipq807x/patches-5.15/0114-remoteproc-qcom-Add-ssr-subdevice-identifier.patch rename to target/linux/qualcommax/patches-6.1/0115-remoteproc-qcom-Add-ssr-subdevice-identifier.patch index 46d93d6b4..be63d46e8 100644 --- a/target/linux/ipq807x/patches-5.15/0114-remoteproc-qcom-Add-ssr-subdevice-identifier.patch +++ b/target/linux/qualcommax/patches-6.1/0115-remoteproc-qcom-Add-ssr-subdevice-identifier.patch @@ -1,4 +1,4 @@ -From a0774816e1e76c47fe47a4e0fa7e0a84811dd62f Mon Sep 17 00:00:00 2001 +From 3a8f67b4770c817b04794c9a02e3f88f85d86280 Mon Sep 17 00:00:00 2001 From: Gokul Sriram Palanisamy Date: Sat, 30 Jan 2021 10:50:08 +0530 Subject: [PATCH] remoteproc: qcom: Add ssr subdevice identifier @@ -14,7 +14,7 @@ Signed-off-by: Nikhil Prakash V --- 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 +@@ -1179,6 +1179,7 @@ static const struct wcss_data wcss_ipq80 .crash_reason_smem = WCSS_CRASH_REASON, .aon_reset_required = true, .wcss_q6_reset_required = true, diff --git a/target/linux/ipq807x/patches-5.15/0115-remoteproc-qcom-Update-regmap-offsets-for-halt-regis.patch b/target/linux/qualcommax/patches-6.1/0116-remoteproc-qcom-Update-regmap-offsets-for-halt-regis.patch similarity index 92% rename from target/linux/ipq807x/patches-5.15/0115-remoteproc-qcom-Update-regmap-offsets-for-halt-regis.patch rename to target/linux/qualcommax/patches-6.1/0116-remoteproc-qcom-Update-regmap-offsets-for-halt-regis.patch index faed4d9ce..f0b717210 100644 --- a/target/linux/ipq807x/patches-5.15/0115-remoteproc-qcom-Update-regmap-offsets-for-halt-regis.patch +++ b/target/linux/qualcommax/patches-6.1/0116-remoteproc-qcom-Update-regmap-offsets-for-halt-regis.patch @@ -1,4 +1,4 @@ -From e99af92362058cfec70569057c1b15da9a1acb5f Mon Sep 17 00:00:00 2001 +From 8c73af6e8d78c66cfef0f551b00d375ec0b67ff3 Mon Sep 17 00:00:00 2001 From: Gokul Sriram Palanisamy Date: Sat, 30 Jan 2021 10:50:09 +0530 Subject: [PATCH] remoteproc: qcom: Update regmap offsets for halt register @@ -61,7 +61,7 @@ Signed-off-by: Sricharan R return 0; } -@@ -1178,6 +1182,7 @@ static const struct wcss_data wcss_ipq80 +@@ -1179,6 +1183,7 @@ static const struct wcss_data wcss_ipq80 .crash_reason_smem = WCSS_CRASH_REASON, .aon_reset_required = true, .wcss_q6_reset_required = true, @@ -69,7 +69,7 @@ Signed-off-by: Sricharan R .ssr_name = "q6wcss", .ops = &q6v5_wcss_ipq8074_ops, .requires_force_stop = true, -@@ -1192,6 +1197,7 @@ static const struct wcss_data wcss_qcs40 +@@ -1193,6 +1198,7 @@ static const struct wcss_data wcss_qcs40 .version = WCSS_QCS404, .aon_reset_required = false, .wcss_q6_reset_required = false, diff --git a/target/linux/ipq807x/patches-5.15/0116-dt-bindings-clock-qcom-Add-reset-for-WCSSAON.patch b/target/linux/qualcommax/patches-6.1/0117-dt-bindings-clock-qcom-Add-reset-for-WCSSAON.patch similarity index 72% rename from target/linux/ipq807x/patches-5.15/0116-dt-bindings-clock-qcom-Add-reset-for-WCSSAON.patch rename to target/linux/qualcommax/patches-6.1/0117-dt-bindings-clock-qcom-Add-reset-for-WCSSAON.patch index 8e1dbc033..fe0e0f9e0 100644 --- a/target/linux/ipq807x/patches-5.15/0116-dt-bindings-clock-qcom-Add-reset-for-WCSSAON.patch +++ b/target/linux/qualcommax/patches-6.1/0117-dt-bindings-clock-qcom-Add-reset-for-WCSSAON.patch @@ -1,4 +1,4 @@ -From 25e8ae5b960f45e9e19aa24cc023603375f44db0 Mon Sep 17 00:00:00 2001 +From ff7c6533ed8c4de58ed6c8aab03ea59c03eb4f31 Mon Sep 17 00:00:00 2001 From: Gokul Sriram Palanisamy Date: Sat, 30 Jan 2021 10:50:10 +0530 Subject: [PATCH] dt-bindings: clock: qcom: Add reset for WCSSAON @@ -16,10 +16,11 @@ Acked-by: Stephen Boyd --- a/include/dt-bindings/clock/qcom,gcc-ipq8074.h +++ b/include/dt-bindings/clock/qcom,gcc-ipq8074.h -@@ -366,5 +366,6 @@ - #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 +@@ -381,6 +381,7 @@ + #define GCC_NSSPORT4_RESET 143 + #define GCC_NSSPORT5_RESET 144 + #define GCC_NSSPORT6_RESET 145 ++#define GCC_WCSSAON_RESET 146 - #endif + #define USB0_GDSC 0 + #define USB1_GDSC 1 diff --git a/target/linux/ipq807x/patches-5.15/0117-clk-qcom-Add-WCSSAON-reset.patch b/target/linux/qualcommax/patches-6.1/0118-clk-qcom-Add-WCSSAON-reset.patch similarity index 59% rename from target/linux/ipq807x/patches-5.15/0117-clk-qcom-Add-WCSSAON-reset.patch rename to target/linux/qualcommax/patches-6.1/0118-clk-qcom-Add-WCSSAON-reset.patch index 00aeecd5f..be0524338 100644 --- a/target/linux/ipq807x/patches-5.15/0117-clk-qcom-Add-WCSSAON-reset.patch +++ b/target/linux/qualcommax/patches-6.1/0118-clk-qcom-Add-WCSSAON-reset.patch @@ -1,4 +1,4 @@ -From 1a279695f52e8ab438fde5dbfbb762da8980e037 Mon Sep 17 00:00:00 2001 +From 43d9788f546d24df22d8ba3fcc2497d7ccc198f3 Mon Sep 17 00:00:00 2001 From: Gokul Sriram Palanisamy Date: Sat, 30 Jan 2021 10:50:11 +0530 Subject: [PATCH] clk: qcom: Add WCSSAON reset @@ -15,11 +15,11 @@ Acked-by: Stephen Boyd --- a/drivers/clk/qcom/gcc-ipq8074.c +++ b/drivers/clk/qcom/gcc-ipq8074.c -@@ -4784,6 +4784,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 }, +@@ -4711,6 +4711,7 @@ static const struct qcom_reset_map gcc_i + [GCC_NSSPORT4_RESET] = { .reg = 0x68014, .bitmask = BIT(27) | GENMASK(9, 8) }, + [GCC_NSSPORT5_RESET] = { .reg = 0x68014, .bitmask = BIT(28) | GENMASK(11, 10) }, + [GCC_NSSPORT6_RESET] = { .reg = 0x68014, .bitmask = BIT(29) | GENMASK(13, 12) }, + [GCC_WCSSAON_RESET] = { 0x59010, 0 }, }; - static const struct of_device_id gcc_ipq8074_match_table[] = { + static struct gdsc *gcc_ipq8074_gdscs[] = { diff --git a/target/linux/ipq807x/patches-5.15/0118-remoteproc-wcss-disable-auto-boot-for-IPQ8074.patch b/target/linux/qualcommax/patches-6.1/0119-remoteproc-wcss-disable-auto-boot-for-IPQ8074.patch similarity index 73% rename from target/linux/ipq807x/patches-5.15/0118-remoteproc-wcss-disable-auto-boot-for-IPQ8074.patch rename to target/linux/qualcommax/patches-6.1/0119-remoteproc-wcss-disable-auto-boot-for-IPQ8074.patch index 4903b0ab1..8674522a1 100644 --- a/target/linux/ipq807x/patches-5.15/0118-remoteproc-wcss-disable-auto-boot-for-IPQ8074.patch +++ b/target/linux/qualcommax/patches-6.1/0119-remoteproc-wcss-disable-auto-boot-for-IPQ8074.patch @@ -1,12 +1,13 @@ -From 76126149a2a76a0cf9895224dbb4dacf69ebb06a Mon Sep 17 00:00:00 2001 +From 406a332fd1bcc4e18d73cce390f56272fe9111d7 Mon Sep 17 00:00:00 2001 From: Sivaprakash Murugesan Date: Fri, 17 Apr 2020 16:37:10 +0530 Subject: [PATCH] remoteproc: wcss: disable auto boot for IPQ8074 -auto boot is disabled for IPQ8074 the wifi driver brings up the wcss. +There is no need for remoteproc to boot automatically, ath11k will trigger +booting when its probing. Signed-off-by: Sivaprakash Murugesan -Change-Id: Ia82edb7ee52f2bd010c099f151179d69a953ac88 +Signed-off-by: Robert Marko --- drivers/remoteproc/qcom_q6v5_wcss.c | 4 ++++ 1 file changed, 4 insertions(+) @@ -21,7 +22,7 @@ Change-Id: Ia82edb7ee52f2bd010c099f151179d69a953ac88 }; static int q6v5_wcss_reset(struct q6v5_wcss *wcss) -@@ -1151,6 +1152,7 @@ static int q6v5_wcss_probe(struct platfo +@@ -1150,6 +1151,7 @@ static int q6v5_wcss_probe(struct platfo desc->sysmon_name, desc->ssctl_id); @@ -29,7 +30,7 @@ Change-Id: Ia82edb7ee52f2bd010c099f151179d69a953ac88 ret = rproc_add(rproc); if (ret) goto free_rproc; -@@ -1187,6 +1189,7 @@ static const struct wcss_data wcss_ipq80 +@@ -1188,6 +1190,7 @@ static const struct wcss_data wcss_ipq80 .ops = &q6v5_wcss_ipq8074_ops, .requires_force_stop = true, .need_mem_protection = true, @@ -37,7 +38,7 @@ Change-Id: Ia82edb7ee52f2bd010c099f151179d69a953ac88 }; static const struct wcss_data wcss_qcs404_res_init = { -@@ -1203,6 +1206,7 @@ static const struct wcss_data wcss_qcs40 +@@ -1204,6 +1207,7 @@ static const struct wcss_data wcss_qcs40 .ssctl_id = 0x12, .ops = &q6v5_wcss_qcs404_ops, .requires_force_stop = false, diff --git a/target/linux/ipq807x/patches-5.15/0119-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 similarity index 87% rename from target/linux/ipq807x/patches-5.15/0119-arm64-dts-qcom-Enable-Q6v5-WCSS-for-ipq8074-SoC.patch rename to target/linux/qualcommax/patches-6.1/0120-arm64-dts-qcom-Enable-Q6v5-WCSS-for-ipq8074-SoC.patch index 1965ccf0f..e37ba37e9 100644 --- a/target/linux/ipq807x/patches-5.15/0119-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 @@ -1,4 +1,4 @@ -From 1078ef8be64de03a2dbd78d17c87af0472748079 Mon Sep 17 00:00:00 2001 +From 7388400b8bd42f71d040dbf2fdbdcb834fcc0ede Mon Sep 17 00:00:00 2001 From: Gokul Sriram Palanisamy Date: Sat, 30 Jan 2021 10:50:13 +0530 Subject: [PATCH] arm64: dts: qcom: Enable Q6v5 WCSS for ipq8074 SoC @@ -11,12 +11,12 @@ Signed-off-by: Sricharan R Signed-off-by: Nikhil Prakash V Signed-off-by: Robert Marko --- - arch/arm64/boot/dts/qcom/ipq8074.dtsi | 88 +++++++++++++++++++++++++++ - 1 file changed, 88 insertions(+) + 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 -@@ -136,6 +136,32 @@ +@@ -140,6 +140,32 @@ }; }; @@ -49,7 +49,7 @@ Signed-off-by: Robert Marko soc: soc { #address-cells = <0x1>; #size-cells = <0x1>; -@@ -392,6 +418,11 @@ +@@ -409,6 +435,11 @@ #hwlock-cells = <1>; }; @@ -61,18 +61,11 @@ Signed-off-by: Robert Marko spmi_bus: spmi@200f000 { compatible = "qcom,spmi-pmic-arb"; reg = <0x0200f000 0x001000>, -@@ -883,5 +914,62 @@ +@@ -913,6 +944,56 @@ "axi_s_sticky"; status = "disabled"; }; + -+ apcs_glb: mailbox@b111000 { -+ compatible = "qcom,ipq8074-apcs-apps-global"; -+ reg = <0x0b111000 0x1000>; -+ -+ #mbox-cells = <1>; -+ }; -+ + q6v5_wcss: q6v5_wcss@cd00000 { + compatible = "qcom,ipq8074-wcss-pil"; + reg = <0x0cd00000 0x4040>, @@ -123,4 +116,5 @@ Signed-off-by: Robert Marko + }; + }; }; - }; + + timer { diff --git a/target/linux/ipq807x/patches-5.15/0120-arm64-dts-ipq8074-Add-WLAN-node.patch b/target/linux/qualcommax/patches-6.1/0121-arm64-dts-ipq8074-Add-WLAN-node.patch similarity index 97% rename from target/linux/ipq807x/patches-5.15/0120-arm64-dts-ipq8074-Add-WLAN-node.patch rename to target/linux/qualcommax/patches-6.1/0121-arm64-dts-ipq8074-Add-WLAN-node.patch index 43dddb3fe..f9a32f93c 100644 --- a/target/linux/ipq807x/patches-5.15/0120-arm64-dts-ipq8074-Add-WLAN-node.patch +++ b/target/linux/qualcommax/patches-6.1/0121-arm64-dts-ipq8074-Add-WLAN-node.patch @@ -1,4 +1,4 @@ -From 4645129811d46fbd18100e0b76fffe88795a54da Mon Sep 17 00:00:00 2001 +From a67d1901741c162645eda0dbdc3a2c0c2aff5cf4 Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Tue, 21 Dec 2021 14:49:36 +0100 Subject: [PATCH] arm64: dts: ipq8074: Add WLAN node @@ -15,7 +15,7 @@ Signed-off-by: Robert Marko --- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi +++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -971,5 +971,116 @@ +@@ -1000,6 +1000,117 @@ }; }; }; @@ -131,4 +131,5 @@ Signed-off-by: Robert Marko + status = "disabled"; + }; }; - }; + + timer { diff --git a/target/linux/ipq807x/patches-5.15/0135-arm64-dts-ipq8074-add-CPU-clock-and-regulator.patch b/target/linux/qualcommax/patches-6.1/0122-arm64-dts-ipq8074-add-CPU-clock.patch similarity index 59% rename from target/linux/ipq807x/patches-5.15/0135-arm64-dts-ipq8074-add-CPU-clock-and-regulator.patch rename to target/linux/qualcommax/patches-6.1/0122-arm64-dts-ipq8074-add-CPU-clock.patch index e0525cc8c..a3c5f344a 100644 --- a/target/linux/ipq807x/patches-5.15/0135-arm64-dts-ipq8074-add-CPU-clock-and-regulator.patch +++ b/target/linux/qualcommax/patches-6.1/0122-arm64-dts-ipq8074-add-CPU-clock.patch @@ -1,66 +1,59 @@ -From c8cda381dfd1fd083d6d2f56f71d33144c042a43 Mon Sep 17 00:00:00 2001 +From cb3ef99c1553565e1dc0301ccd5c1c0fa2d15c15 Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Fri, 31 Dec 2021 17:56:14 +0100 -Subject: [PATCH] arm64: dts: ipq8074: add CPU clock and regulator +Subject: [PATCH] arm64: dts: ipq8074: add CPU clock -Now that we have drivers for both the CPU voltage regulator and clock -controller, add the required DT properties to CPU cores. - -OPP tables are not added as they are different for the IPQ8072/4/6/8 and -IPQ8070/1 SoC-s +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 | 13 +++++++++++++ - 1 file changed, 13 insertions(+) + 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 -@@ -4,6 +4,7 @@ - */ +@@ -5,6 +5,7 @@ #include -+#include #include - #include ++#include -@@ -35,6 +36,9 @@ + / { + #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"; -+ cpu-supply = <&s3>; }; CPU1: cpu@1 { -@@ -43,6 +47,9 @@ +@@ -46,6 +49,8 @@ enable-method = "psci"; reg = <0x1>; next-level-cache = <&L2_0>; + clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>; + clock-names = "cpu"; -+ cpu-supply = <&s3>; }; CPU2: cpu@2 { -@@ -51,6 +58,9 @@ +@@ -54,6 +59,8 @@ enable-method = "psci"; reg = <0x2>; next-level-cache = <&L2_0>; + clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>; + clock-names = "cpu"; -+ cpu-supply = <&s3>; }; CPU3: cpu@3 { -@@ -59,6 +69,9 @@ +@@ -62,6 +69,8 @@ enable-method = "psci"; reg = <0x3>; next-level-cache = <&L2_0>; + clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>; + clock-names = "cpu"; -+ cpu-supply = <&s3>; }; L2_0: l2-cache { diff --git a/target/linux/ipq807x/patches-5.15/0137-arm64-dts-ipq8074-add-cooling-cells-to-CPU-nodes.patch b/target/linux/qualcommax/patches-6.1/0123-arm64-dts-ipq8074-add-cooling-cells-to-CPU-nodes.patch similarity index 81% rename from target/linux/ipq807x/patches-5.15/0137-arm64-dts-ipq8074-add-cooling-cells-to-CPU-nodes.patch rename to target/linux/qualcommax/patches-6.1/0123-arm64-dts-ipq8074-add-cooling-cells-to-CPU-nodes.patch index 8bea2155d..3520b3813 100644 --- a/target/linux/ipq807x/patches-5.15/0137-arm64-dts-ipq8074-add-cooling-cells-to-CPU-nodes.patch +++ b/target/linux/qualcommax/patches-6.1/0123-arm64-dts-ipq8074-add-cooling-cells-to-CPU-nodes.patch @@ -1,4 +1,4 @@ -From 26fe80d67ab1351faa2e745a20152de71d38124f Mon Sep 17 00:00:00 2001 +From 347ca56e86c99021fad059b9a8ef101245b8507e Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Fri, 31 Dec 2021 20:38:06 +0100 Subject: [PATCH] arm64: dts: ipq8074: add cooling cells to CPU nodes @@ -14,34 +14,34 @@ Signed-off-by: Robert Marko --- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi +++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -39,6 +39,7 @@ +@@ -41,6 +41,7 @@ + enable-method = "psci"; clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>; clock-names = "cpu"; - cpu-supply = <&s3>; + #cooling-cells = <2>; }; CPU1: cpu@1 { -@@ -50,6 +51,7 @@ +@@ -51,6 +52,7 @@ + next-level-cache = <&L2_0>; clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>; clock-names = "cpu"; - cpu-supply = <&s3>; + #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"; - cpu-supply = <&s3>; + #cooling-cells = <2>; }; CPU3: cpu@3 { -@@ -72,6 +75,7 @@ +@@ -71,6 +74,7 @@ + next-level-cache = <&L2_0>; clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>; clock-names = "cpu"; - cpu-supply = <&s3>; + #cooling-cells = <2>; }; diff --git a/target/linux/qualcommax/patches-6.1/0129-arm64-dts-qcom-ipq8074-add-QFPROM-fuses.patch b/target/linux/qualcommax/patches-6.1/0129-arm64-dts-qcom-ipq8074-add-QFPROM-fuses.patch new file mode 100644 index 000000000..ff5f86c19 --- /dev/null +++ b/target/linux/qualcommax/patches-6.1/0129-arm64-dts-qcom-ipq8074-add-QFPROM-fuses.patch @@ -0,0 +1,128 @@ +From 04d2fc6a551bbd972a6428059b45ce79cb9de9d7 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Fri, 6 May 2022 22:38:24 +0200 +Subject: [PATCH] arm64: dts: qcom: ipq8074: add QFPROM fuses + +Add the QFPROM node and CPR fuses. + +Signed-off-by: Robert Marko +--- + arch/arm64/boot/dts/qcom/ipq8074.dtsi | 107 ++++++++++++++++++++++++++ + 1 file changed, 107 insertions(+) + +--- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi ++++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi +@@ -341,6 +341,113 @@ + status = "disabled"; + }; + ++ qfprom: efuse@a4000 { ++ compatible = "qcom,ipq8074-qfprom", "qcom,qfprom"; ++ reg = <0x000a4000 0x1000>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ cpr_efuse_speedbin: speedbin@125 { ++ reg = <0x125 0x1>; ++ bits = <0 3>; ++ }; ++ ++ cpr_efuse_boost_cfg: boost_cfg@125 { ++ reg = <0x125 0x1>; ++ bits = <3 3>; ++ }; ++ ++ cpr_efuse_misc_volt_adj: misc_volt_adj@125 { ++ reg = <0x125 0x1>; ++ bits = <3 3>; ++ }; ++ ++ cpr_efuse_boost_volt: boost_volt@126 { ++ reg = <0x126 0x1>; ++ bits = <6 1>; ++ }; ++ ++ cpr_efuse_revision: revision@23e { ++ reg = <0x23e 0x1>; ++ bits = <5 3>; ++ }; ++ ++ cpr_efuse_ro_sel0: rosel0@249 { ++ reg = <0x249 0x1>; ++ bits = <0 4>; ++ }; ++ ++ cpr_efuse_ro_sel1: rosel1@248 { ++ reg = <0x248 0x1>; ++ bits = <4 4>; ++ }; ++ ++ cpr_efuse_ro_sel2: rosel2@248 { ++ reg = <0x248 0x2>; ++ bits = <0 4>; ++ }; ++ ++ cpr_efuse_ro_sel3: rosel3@249 { ++ reg = <0x249 0x1>; ++ bits = <4 4>; ++ }; ++ ++ cpr_efuse_init_voltage0: ivoltage0@23a { ++ reg = <0x23a 0x1>; ++ bits = <2 6>; ++ }; ++ ++ cpr_efuse_init_voltage1: ivoltage1@239 { ++ reg = <0x239 0x2>; ++ bits = <4 6>; ++ }; ++ ++ cpr_efuse_init_voltage2: ivoltage2@238 { ++ reg = <0x238 0x2>; ++ bits = <6 6>; ++ }; ++ ++ cpr_efuse_init_voltage3: ivoltage3@238 { ++ reg = <0x238 0x1>; ++ bits = <0 6>; ++ }; ++ ++ cpr_efuse_quot0: quot0@244 { ++ reg = <0x244 0x2>; ++ bits = <0 12>; ++ }; ++ ++ cpr_efuse_quot1: quot1@242 { ++ reg = <0x242 0x2>; ++ bits = <4 12>; ++ }; ++ ++ cpr_efuse_quot2: quot2@241 { ++ reg = <0x241 0x2>; ++ bits = <0 12>; ++ }; ++ ++ cpr_efuse_quot3: quot3@245 { ++ reg = <0x245 0x2>; ++ bits = <4 12>; ++ }; ++ ++ cpr_efuse_quot0_offset: quot0_offset@23d { ++ reg = <0x23d 0x2>; ++ bits = <6 7>; ++ }; ++ ++ cpr_efuse_quot1_offset: quot1_offset@23c { ++ reg = <0x23c 0x2>; ++ bits = <7 7>; ++ }; ++ ++ cpr_efuse_quot2_offset: quot2_offset@23c { ++ reg = <0x23c 0x1>; ++ bits = <0 7>; ++ }; ++ }; ++ + prng: rng@e3000 { + compatible = "qcom,prng-ee"; + reg = <0x000e3000 0x1000>; diff --git a/target/linux/qualcommax/patches-6.1/0130-arm64-dts-qcom-ipq8074-add-CPU-OPP-table.patch b/target/linux/qualcommax/patches-6.1/0130-arm64-dts-qcom-ipq8074-add-CPU-OPP-table.patch new file mode 100644 index 000000000..9c1e7b9d2 --- /dev/null +++ b/target/linux/qualcommax/patches-6.1/0130-arm64-dts-qcom-ipq8074-add-CPU-OPP-table.patch @@ -0,0 +1,102 @@ +From a20c4e8738a00087aa5d53fe5148ed484e23d229 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Sat, 31 Dec 2022 13:56:26 +0100 +Subject: [PATCH] arm64: dts: qcom: ipq8074: add CPU OPP table + +Now that there is NVMEM CPUFreq support for IPQ8074, we can add the OPP +table for SoC. + +Signed-off-by: Robert Marko +--- + arch/arm64/boot/dts/qcom/ipq8074.dtsi | 52 +++++++++++++++++++++++++++ + 1 file changed, 52 insertions(+) + +--- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi ++++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi +@@ -42,6 +42,7 @@ + clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>; + clock-names = "cpu"; + #cooling-cells = <2>; ++ operating-points-v2 = <&cpu_opp_table>; + }; + + CPU1: cpu@1 { +@@ -53,6 +54,7 @@ + clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>; + clock-names = "cpu"; + #cooling-cells = <2>; ++ operating-points-v2 = <&cpu_opp_table>; + }; + + CPU2: cpu@2 { +@@ -64,6 +66,7 @@ + clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>; + clock-names = "cpu"; + #cooling-cells = <2>; ++ operating-points-v2 = <&cpu_opp_table>; + }; + + CPU3: cpu@3 { +@@ -75,6 +78,7 @@ + clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>; + clock-names = "cpu"; + #cooling-cells = <2>; ++ operating-points-v2 = <&cpu_opp_table>; + }; + + L2_0: l2-cache { +@@ -83,6 +87,54 @@ + }; + }; + ++ cpu_opp_table: opp-table { ++ compatible = "operating-points-v2-kryo-cpu"; ++ nvmem-cells = <&cpr_efuse_speedbin>; ++ opp-shared; ++ ++ opp-1017600000 { ++ opp-hz = /bits/ 64 <1017600000>; ++ opp-microvolt = <1>; ++ opp-supported-hw = <0xf>; ++ clock-latency-ns = <200000>; ++ }; ++ ++ opp-1382400000 { ++ opp-hz = /bits/ 64 <1382400000>; ++ opp-microvolt = <2>; ++ opp-supported-hw = <0xf>; ++ clock-latency-ns = <200000>; ++ }; ++ ++ opp-1651200000 { ++ opp-hz = /bits/ 64 <1651200000>; ++ opp-microvolt = <3>; ++ opp-supported-hw = <0x1>; ++ clock-latency-ns = <200000>; ++ }; ++ ++ opp-1843200000 { ++ opp-hz = /bits/ 64 <1843200000>; ++ opp-microvolt = <4>; ++ opp-supported-hw = <0x1>; ++ clock-latency-ns = <200000>; ++ }; ++ ++ opp-1920000000 { ++ opp-hz = /bits/ 64 <1920000000>; ++ opp-microvolt = <5>; ++ opp-supported-hw = <0x1>; ++ clock-latency-ns = <200000>; ++ }; ++ ++ opp-2208000000 { ++ opp-hz = /bits/ 64 <2208000000>; ++ opp-microvolt = <6>; ++ opp-supported-hw = <0x1>; ++ clock-latency-ns = <200000>; ++ }; ++ }; ++ + pmu { + compatible = "arm,cortex-a53-pmu"; + interrupts = ; diff --git a/target/linux/qualcommax/patches-6.1/0900-power-Add-Qualcomm-APM.patch b/target/linux/qualcommax/patches-6.1/0900-power-Add-Qualcomm-APM.patch new file mode 100644 index 000000000..2e5c72b7d --- /dev/null +++ b/target/linux/qualcommax/patches-6.1/0900-power-Add-Qualcomm-APM.patch @@ -0,0 +1,1047 @@ +From 6c98adf98236b8644b8f5e1aa7af9f1a88ea2766 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Mon, 11 Apr 2022 14:38:08 +0200 +Subject: [PATCH] power: Add Qualcomm APM + +Add Qualcomm APM driver, which allows scaling cache and memory fabrics. + +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/qualcommax/patches-6.1/0901-regulator-add-Qualcomm-CPR-regulators.patch b/target/linux/qualcommax/patches-6.1/0901-regulator-add-Qualcomm-CPR-regulators.patch new file mode 100644 index 000000000..9b9f7159f --- /dev/null +++ b/target/linux/qualcommax/patches-6.1/0901-regulator-add-Qualcomm-CPR-regulators.patch @@ -0,0 +1,12144 @@ +From c9df32c057e43e38c8113199e64f7a64f8d341df Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Mon, 11 Apr 2022 14:35:36 +0200 +Subject: [PATCH] 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 | 5111 +++++++++++++++++++++++ + 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, 12085 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 +@@ -1524,4 +1524,37 @@ 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 +@@ -110,6 +110,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,5111 @@ ++/* ++ * 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(vreg->thread->ctrl->dev, 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, ++}; ++ ++/** ++ * 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/ipq807x/patches-5.15/0901-arm64-dts-ipq8074-add-label-to-clocks.patch b/target/linux/qualcommax/patches-6.1/0902-arm64-dts-ipq8074-add-label-to-clocks.patch similarity index 83% rename from target/linux/ipq807x/patches-5.15/0901-arm64-dts-ipq8074-add-label-to-clocks.patch rename to target/linux/qualcommax/patches-6.1/0902-arm64-dts-ipq8074-add-label-to-clocks.patch index 642349a3b..9b8b4df12 100644 --- a/target/linux/ipq807x/patches-5.15/0901-arm64-dts-ipq8074-add-label-to-clocks.patch +++ b/target/linux/qualcommax/patches-6.1/0902-arm64-dts-ipq8074-add-label-to-clocks.patch @@ -1,4 +1,4 @@ -From 4bdbb8ddf49ebca198719940c4b6246f90a4251d Mon Sep 17 00:00:00 2001 +From 6baf7e4abcea6f7ac21eccf072a20078b39d064c Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Wed, 9 Feb 2022 23:13:26 +0100 Subject: [PATCH] arm64: dts: ipq8074: add label to clocks @@ -13,9 +13,9 @@ Signed-off-by: Robert Marko --- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi +++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -12,7 +12,7 @@ - model = "Qualcomm Technologies, Inc. IPQ8074"; +@@ -15,7 +15,7 @@ compatible = "qcom,ipq8074"; + interrupt-parent = <&intc>; - clocks { + clocks: clocks {