From 5c73f28bfd234082aade53dd4b7be1d96ad0613a Mon Sep 17 00:00:00 2001 From: Mieczyslaw Nalewaj Date: Fri, 27 Mar 2026 17:48:03 +0100 Subject: [PATCH] generic: 6.18: remove obsolete backport patches Remove obsolete backport patches already included in kernel 6.18. Signed-off-by: Mieczyslaw Nalewaj Link: https://github.com/openwrt/openwrt/pull/21078 Signed-off-by: Robert Marko --- ...g-annotation-to-fix-build-with-GCC15.patch | 63 - ...v6.13-jiffies-Define-secs_to_jiffies.patch | 60 - ...unsigned-long-in-secs_to_jiffies-con.patch | 35 - ...-property-add-of_graph_get_next_port.patch | 199 - ...devm_clk_bulk_get_all_enabled-helper.patch | 118 - ...ework-bus-matching-to-avoid-warnings.patch | 61 - ...ARN-when-attempting-translating-non-.patch | 85 - ...Add-functions-to-parse-memory-region.patch | 163 - ...-copy-size-from-value-range-tracking.patch | 155 - ...Add-missing-IORESOURCE_MEM-flag-on-r.patch | 32 - ...d-add-support-for-FORESEE-F35SQA001G.patch | 38 - ...-add-support-for-FudanMicro-FM25S01A.patch | 124 - ...02-v6.18-mtd-nand-move-chunk-to-core.patch | 329 -- ...msh-remove-QE-bit-for-FM25S01A-flash.patch | 28 - ...wnand-qcom-cleanup-qcom_nandc-driver.patch | 1026 ----- ...d-qcom-Add-qcom-prefix-to-common-api.patch | 880 ---- ...14-mtd-nand-Add-qpic_common-API-file.patch | 2436 ----------- ...nand-qcom-use-FIELD_PREP-and-GENMASK.patch | 198 - ...-fix-broken-config-in-qcom_param_pag.patch | 64 - ...-Fix-build-issue-on-x86-architecture.patch | 77 - ...-driver-for-QCOM-SPI-NAND-flash-Inte.patch | 1737 -------- ...nd-Fix-ECC_CFG_ECC_DISABLE-shift-in-.patch | 28 - ...nd-avoid-memleak-in-qcom_spi_ecc_ini.patch | 35 - ...ND-should-be-tristate-and-depend-on-.patch | 49 - ...ate-errors-from-qcom_spi_block_erase.patch | 36 - ...ND_READ_LOCATION_2-register-handling.patch | 35 - ...nd-use-kmalloc-for-OOB-buffer-alloca.patch | 29 - ...-wlen-member-of-struct-qpic_spi_nand.patch | 30 - ...plicit-test-for-built-in-CONFIG_SPI_.patch | 37 - ...te-user-chip-specific-ECC-properties.patch | 166 - ...c-snand-use-CW_PER_PAGE_MASK-bitmask.patch | 113 - ...ic-snand-reallocate-BAM-transactions.patch | 81 - ...-qpic-snand-don-t-hardcode-ECC-steps.patch | 31 - ...mmon-add-defines-for-ECC_MODE-values.patch | 74 - ...-add-support-for-8-bits-ECC-strength.patch | 66 - ...nd-use-correct-CW_PER_PAGE-value-for.patch | 56 - ...nd-fix-calculating-of-ECC-OOB-region.patch | 69 - ...nd-brcmnand-remove-unused-parameters.patch | 88 - ...d-fix-NAND-timeout-when-accessing-eM.patch | 30 - ...cmnand-legacy-exec_op-implementation.patch | 299 -- ...nd-unregister-ECC-engine-on-probe-er.patch | 48 - ...nd-fix-direct-mapping-creation-sizes.patch | 63 - ...ry-a-regular-dirmap-if-creating-a-di.patch | 98 - ...epeat-reading-in-regular-mode-if-con.patch | 64 - ...-Introduce-a-way-to-avoid-raw-access.patch | 81 - ...d-support-for-SkyHigh-S35ML-3-family.patch | 201 - ...rt-for-defining-read-only-partitions.patch | 53 - ...6.13-block-introduce-add_disk_fwnode.patch | 94 - ...-partitions-fwnode-if-found-in-mmc-c.patch | 104 - ...rt-for-partition-table-defined-in-OF.patch | 200 - ...ink-move-manual-flow-control-setting.patch | 41 - ...-MLO_AN_FIXED-resolve-handling-to-if.patch | 42 - ...-MLO_AN_PHY-resolve-handling-to-if-s.patch | 37 - ...ve-switch-statement-in-resolve-handl.patch | 127 - ...net-phylink-clean-up-phylink_resolve.patch | 85 - ...-phylink-and-pcs-into-phylink_pcs_ne.patch | 95 - ...t-cur_link_an_mode-into-requested-an.patch | 290 -- ...k-add-debug-for-phylink_major_config.patch | 66 - ...04-v6.14-net-phy-add-phy_inband_caps.patch | 118 - ...881-implement-phy_inband_caps-method.patch | 41 - ...ell-implement-phy_inband_caps-method.patch | 63 - ...-v6.14-net-phy-add-phy_config_inband.patch | 79 - ...rvell-implement-config_inband-method.patch | 77 - ...t-phylink-add-pcs_inband_caps-method.patch | 159 - ...eta-implement-pcs_inband_caps-method.patch | 64 - ...pp2-implement-pcs_inband_caps-method.patch | 62 - ...-negotiation-of-in-band-capabilities.patch | 228 -- ...phylink-remove-phylink_phy_no_inband.patch | 110 - ...ynx-implement-pcs_inband_caps-method.patch | 53 - ...lynxi-implement-pcs_inband_caps-meth.patch | 47 - ...pcs-implement-pcs_inband_caps-method.patch | 58 - ...link-provide-phylink_get_inband_type.patch | 117 - ...ble-autoneg-for-interfaces-that-have.patch | 68 - ...3-net-dsa-use-ethtool-string-helpers.patch | 30 - ...sa-b53-mdio-add-support-for-BCM53101.patch | 76 - ...sa-b53-implement-setting-ageing-time.patch | 105 - ...ot-configure-bcm63xx-s-IMP-port-inte.patch | 70 - ...brcm-add-support-for-legacy-FCS-tags.patch | 188 - ...-net-dsa-b53-support-legacy-FCS-tags.patch | 48 - ...-net-dsa-b53-detect-BCM5325-variants.patch | 112 - ...port-for-FDB-operations-on-5325-5365.patch | 250 -- ...3-prevent-FAST_AGE-access-on-BCM5325.patch | 51 - ...ent-BRCM_HDR-access-on-older-devices.patch | 33 - ...nicast-multicast-flooding-on-BCM5325.patch | 128 - ...3-Add-phy_enable-phy_disable-methods.patch | 50 - ...efine-chip-IDs-for-more-bcm63xx-SoCs.patch | 124 - ...nce-and-register-layout-for-bcm63268.patch | 69 - ...mmap-Add-register-layout-for-bcm6318.patch | 47 - ...mmap-Add-register-layout-for-bcm6368.patch | 42 - ...Implement-bcm63xx-ephy-power-control.patch | 100 - ...d-gphy-port-to-phy-info-for-bcm63268.patch | 33 - ...mplement-bcm63268-gphy-power-control.patch | 77 - ...rved-register-access-in-b53_fdb_dump.patch | 72 - ...dsa-b53-fix-ageing-time-for-BCM53101.patch | 77 - ...und-ARL-searches-for-4-ARL-bin-chips.patch | 61 - ...mark-link-local-traffic-as-offloaded.patch | 59 - ...ead-25-use-the-entry-for-comparision.patch | 85 - ...-ARL-entries-into-their-own-function.patch | 117 - ...ARL-entries-into-their-own-functions.patch | 93 - ...accessors-for-accessing-ARL_SRCH_CTL.patch | 85 - ...earch-entry-into-their-own-functions.patch | 86 - ...-ARL-entry-functions-into-ops-struct.patch | 348 -- ...-for-5389-5397-5398-ARL-entry-format.patch | 221 - ...support-for-bcm63xx-ARL-entry-format.patch | 177 - ...LAN_ID_IDX-write-size-for-BCM5325-65.patch | 38 - ...acting-VID-from-entry-for-BCM5325-65.patch | 35 - ...-search-result-offset-for-BCM5325-65.patch | 78 - ...t-unicast-ARL-entries-for-BCM5325-65.patch | 51 - ...25-65-ARL-entry-multicast-port-masks.patch | 120 - ...sa-b53-fix-BCM5325-65-ARL-entry-VIDs.patch | 140 - ...e-IFF_NO_QUEUE-in-virtual-interfaces.patch | 79 - ...v6.17-ppp-convert-to-percpu-netstats.patch | 126 - .../622-v6.18-ppp-remove-rwlock-usage.patch | 334 -- .../623-v6.18-pppoe-remove-rwlock-usage.patch | 321 -- ...sock-reference-counting-on-fast-path.patch | 124 - ....13-net-pse-pd-Add-power-limit-check.patch | 41 - ...d-tps23881-Simplify-function-returns.patch | 112 - ...-Use-helpers-to-calculate-bit-offset.patch | 190 - ...1-Add-missing-configuration-register.patch | 63 - ...l_get_status-into-multiple-callbacks.patch | 714 ---- ...ove-is_enabled-callback-from-drivers.patch | 184 - ...power-limit-and-measurement-features.patch | 337 -- ...d-Fix-missing-PI-of_node-description.patch | 28 - ...ean-ethtool-header-of-PSE-structures.patch | 92 - ...oduce-attached_phydev-to-pse-control.patch | 171 - ...-pd-Add-support-for-reporting-events.patch | 363 -- ...-tps23881-Add-support-for-PSE-events.patch | 252 -- ...pd-Add-support-for-PSE-power-domains.patch | 218 - ...-Add-support-for-power-domains-index.patch | 78 - ...dd-helper-to-report-hw-enable-status.patch | 74 - ...ort-for-budget-evaluation-strategies.patch | 1104 ----- ...gulator-Add-support-for-power-budget.patch | 257 -- ...-pd692x0-Add-PSE-PI-priority-feature.patch | 326 -- ...2x0-Add-controller-and-manager-power.patch | 71 - ...881-Add-static-port-priority-feature.patch | 392 -- ...et-pse-pd-pd692x0-reduce-stack-usage.patch | 55 - ...pse-pd-pd692x0-Fix-power-budget-leak.patch | 121 - ...2x0-Skip-power-budget-when-undefined.patch | 37 - ...-pd-Add-Si3474-PSE-controller-driver.patch | 636 --- ...3881-Fix-current-measurement-scaling.patch | 31 - ...ly-receive-all-multicast-packets-if-.patch | 41 - ...Add-ethtool_netlink_generated-header.patch | 79 - ...thtool-Add-PSE-port-priority-support.patch | 68 - ...-net-usb-qmi_wwan-add-Quectel-RG255C.patch | 47 - ...-Introduce-device-managed-variant-of.patch | 74 - ...an-tag-insertion-stripping-by-defaul.patch | 32 - ...phy-mediatek-ge-soc-Fix-coding-style.patch | 88 - ...-ge-soc-Shrink-line-wrapping-to-80-c.patch | 271 -- ...-ge-soc-Propagate-error-code-correct.patch | 40 - ...-Re-organize-MediaTek-ethernet-phy-d.patch | 3565 ----------------- ...-Move-LED-helper-functions-into-mtk-.patch | 774 ---- ...-Improve-readability-of-mtk-phy-lib..patch | 72 - ...-Integrate-read-write-page-helper-fu.patch | 153 - ...ek-add-MT7530-MT7531-s-PHY-ID-macros.patch | 56 - ...t-phy-Constify-struct-mdio_device_id.patch | 700 ---- ...tek-Change-to-more-meaningful-macros.patch | 146 - ...-Add-token-ring-access-helper-functi.patch | 448 --- ...-Add-token-ring-set-bit-operation-su.patch | 73 - ...-Add-token-ring-clear-bit-operation-.patch | 122 - ...-Move-some-macros-to-phy-lib-for-lat.patch | 45 - ...-permit-to-compile-test-GE-SOC-PHY-d.patch | 37 - ...atek-add-Airoha-PHY-ID-to-SoC-driver.patch | 129 - ...-init-val-in-.phy_led_polarity_set-f.patch | 40 - ...et-ethernet-mediatek-add-EEE-support.patch | 157 - ...tia-allow-forcing-order-of-MDI-pairs.patch | 107 - ...-fix-return-value-check-in-aqr107_co.patch | 31 - ...rt-active-high-property-for-PHY-LEDs.patch | 53 - ...-correctly-describe-LED-polarity-ove.patch | 108 - ...et-phy-mxl-gpy-add-basic-LED-support.patch | 332 -- ...add-missing-support-for-TRIGGER_NETD.patch | 28 - ...-gpy-correctly-describe-LED-polarity.patch | 58 - ...-intel-xway-add-support-for-PHY-LEDs.patch | 379 -- ...fix-link-properties-on-USXGMII-and-i.patch | 56 - ...-Introduce-MT7992-WED-support-to-MT7.patch | 116 - ...e-proper-wed-reference-in-mt76-wed-d.patch | 79 - ...dma-mask-limitation-and-GFP_DMA32-fo.patch | 50 - ...defined-behavior-in-_led_polarity_se.patch | 64 - ...et-dsa-mv88e6xxx-Support-LED-control.patch | 1250 ------ ...x-fix-unreleased-fwnode_handle-in-se.patch | 31 - ...x-Fix-fwnode-reference-leaks-in-mv88.patch | 68 - ...e-phy_id_compare_model-PHY-ID-helper.patch | 39 - ...ginal-workaround-for-RTL8125-broken-.patch | 33 - ...TSO-on-selected-chip-versions-per-de.patch | 52 - ...plement-additional-ethtool-stats-ops.patch | 130 - ...169-don-t-take-RTNL-lock-in-rtl_task.patch | 50 - ...-custom-flag-with-disable_work-et-al.patch | 94 - ...icated-messages-if-loading-firmware-.patch | 41 - ...9-remove-rtl_dash_loop_wait_high-low.patch | 82 - ...-EEE-at-2.5G-per-default-on-RTL8125B.patch | 28 - ...istent-indenting-in-rtl8169_get_eth_.patch | 30 - ...TL8125-EEE-config-with-vendor-driver.patch | 49 - ...125-RTL8126-PHY-config-with-vendor-d.patch | 46 - ...TL8126-EEE-config-with-vendor-driver.patch | 25 - ...itialization-of-RSS-registers-on-RTL.patch | 38 - ...leftover-locks-after-reverted-change.patch | 113 - ...6.13-r8169-improve-__rtl8169_set_wol.patch | 108 - ...13-r8169-improve-rtl_set_d3_pll_down.patch | 44 - ..._PHY-handling-with-r8125-r8126-vendo.patch | 29 - ...-r8169_mod_reg8_cond-to-simplify-rtl.patch | 117 - ...r-driver-2.5G-5G-EEE-advertisement-c.patch | 82 - ...sed-flag-RTL_FLAG_TASK_RESET_NO_QUEU.patch | 35 - ...9-remove-support-for-chip-version-11.patch | 114 - ...adjust-version-numbering-for-RTL8126.patch | 257 -- ...r8169-add-support-for-RTL8125D-rev.b.patch | 90 - ...8169-add-support-for-RTL8125BP-rev.b.patch | 184 - ...ig-option-for-LED-support-user-visib.patch | 28 - ...9-add-support-for-Intel-Killer-E5000.patch | 25 - ...5-ops-for-MDIO_MMD_VENDOR2-registers.patch | 67 - ...ax-jumbo-packet-size-on-RTL8125-RTL8.patch | 40 - ...way-from-deprecated-pcim_iomap_table.patch | 35 - ...8168H-RTL8168EP-RTL8168FP-ASPM-suppo.patch | 27 - ...r-rtl_csi_mod-for-accessing-extended.patch | 74 - ...6-r8169-add-helper-rtl8125_phy_param.patch | 82 - ...8169-refactor-chip-version-detection.patch | 401 -- ...GA_MAC_VER_LAST-to-facilitate-adding.patch | 159 - ...pci_prepare_to_sleep-in-rtl_shutdown.patch | 37 - ...rge-chip-versions-70-and-71-RTL8126A.patch | 106 - ...rge-chip-versions-64-and-65-RTL8125D.patch | 65 - ...erge-chip-versions-52-and-53-RTL8117.patch | 113 - ...v6.16-r8169-add-support-for-RTL8127A.patch | 323 -- ...read-duplex-and-gbit-master-from-PHY.patch | 106 - ...change-order-of-calls-in-C22-read_st.patch | 53 - ...clear-1000Base-T-link-partner-advert.patch | 30 - ...add-support-for-reading-MDIO_MMD_VEN.patch | 47 - ...clear-1000Base-T-lpa-if-link-is-down.patch | 52 - ...clear-master_slave_state-if-link-is-.patch | 35 - ...phy-realtek-always-clear-NBase-T-lpa.patch | 42 - ...ltek-PHY-driver-to-its-own-subdirect.patch | 3247 --------------- ...add-hwmon-support-for-temp-sensor-on.patch | 173 - ...HWMON-support-for-standalone-version.patch | 64 - ...make-HWMON-support-a-user-visible-Kc.patch | 35 - ...y-realtek-use-string-choices-helpers.patch | 54 - ...improve-mmd-register-access-for-inte.patch | 134 - ...switch-from-paged-to-MMD-ops-in-rtl8.patch | 52 - ...ltek-add-helper-RTL822X_VND2_C22_REG.patch | 48 - ...add-defines-for-shadowed-c45-standar.patch | 113 - ...net-phy-realtek-disable-PHY-mode-EEE.patch | 54 - ...-Add-support-for-WOL-magic-packet-on.patch | 126 - ...ek-remove-unsed-RTL821x_PHYSR-macros.patch | 28 - ...ltek-Clean-up-RTL821x-ExtPage-access.patch | 95 - ...ealtek-add-RTL8211F-register-defines.patch | 139 - ...ealtek-Group-RTL82-macro-definitions.patch | 123 - ...use-__set_bit-in-rtl8211f_led_hw_con.patch | 42 - ...Add-support-for-PHY-LEDs-on-RTL8211E.patch | 215 - ...phy-realtek-add-RTL8127-internal-PHY.patch | 35 - ...altek-convert-RTL8226-CG-to-c45-only.patch | 169 - ...le-serdes-option-mode-for-RTL8226-CG.patch | 92 - ...s-PHY-driver-to-.match_phy_device-OP.patch | 303 -- ...hy-introduce-genphy_match_phy_device.patch | 109 - ...dd-support-for-Aeonsemi-AS21xxx-PHYs.patch | 1180 ------ ...dsa-Move-KS8995-to-the-DSA-subsystem.patch | 1092 ----- ...et-dsa-ks8995-Add-proper-RESET-delay.patch | 40 - ...-ks8995-Delete-sysfs-register-access.patch | 109 - ...t-dsa-ks8995-Add-basic-switch-set-up.patch | 546 --- ...add-error-handling-to-rtl8211f_get_w.patch | 39 - ...Avoid-PHYCR2-access-if-PHYCR2-not-pr.patch | 61 - ...tek-fix-RTL8211F-wake-on-lan-support.patch | 352 -- ...-phy-realtek-fix-rtl8221b-vm-cg-name.patch | 70 - ...support-for-TRIGGER_NETDEV_LINK-on-R.patch | 105 - ...k-create-rtl8211f_config_rgmii_delay.patch | 128 - ...altek-eliminate-priv-phycr2-variable.patch | 101 - ...ealtek-eliminate-has_phycr2-variable.patch | 55 - ...allow-CLKOUT-to-be-disabled-on-RTL82.patch | 101 - ...altek-eliminate-priv-phycr1-variable.patch | 107 - ...create-rtl8211f_config_phy_eee-helpe.patch | 58 - ...fix-RTL8127-hang-on-suspend-shutdown.patch | 50 - ...e-phy_id_compare_vendor-PHY-ID-helpe.patch | 58 - ...better-handle-PHY-HW-reset-on-soft-r.patch | 45 - ...VD-Restore-disabling-of-PHY-mode-EEE.patch | 61 - ...-visibility-member-to-struct-hwmon_o.patch | 88 - ...ks-add-binding-for-gated-fixed-clock.patch | 82 - ...ate-documentation-for-gpio-gate-cloc.patch | 27 - ...e-dev_err_probe-for-gpio-get-failure.patch | 44 - ...io-add-driver-for-gated-fixed-clocks.patch | 229 -- ...-regmap-Use-generic-request-free-ops.patch | 30 - ...523-fix-can_sleep-flag-for-GPIO-chip.patch | 28 - ...-termination-to-fix-build-with-GCC15.patch | 39 - ...ings-leds-Add-LED1202-LED-Controller.patch | 160 - ...92-v6.14-leds-Add-LED1202-I2C-driver.patch | 475 --- ...st1202-Fix-NULL-pointer-access-error.patch | 73 - ...a-faux-bus-for-use-when-a-simple-dev.patch | 386 -- 281 files changed, 48293 deletions(-) delete mode 100644 target/linux/generic/backport-6.18/152-v6.16-net-wireguard-add-nonstring-annotation-to-fix-build-with-GCC15.patch delete mode 100644 target/linux/generic/backport-6.18/200-01-v6.13-jiffies-Define-secs_to_jiffies.patch delete mode 100644 target/linux/generic/backport-6.18/200-02-v6.14-jiffies-Cast-to-unsigned-long-in-secs_to_jiffies-con.patch delete mode 100644 target/linux/generic/backport-6.18/201-v6.13-of-property-add-of_graph_get_next_port.patch delete mode 100644 target/linux/generic/backport-6.18/202-v6.13-clk-Provide-devm_clk_bulk_get_all_enabled-helper.patch delete mode 100644 target/linux/generic/backport-6.18/203-01-v6.13-of-address-Rework-bus-matching-to-avoid-warnings.patch delete mode 100644 target/linux/generic/backport-6.18/203-02-v6.13-of-address-Fix-WARN-when-attempting-translating-non-.patch delete mode 100644 target/linux/generic/backport-6.18/205-v6.16-of-reserved_mem-Add-functions-to-parse-memory-region.patch delete mode 100644 target/linux/generic/backport-6.18/210-v6.13-fortify-Hide-run-time-copy-size-from-value-range-tracking.patch delete mode 100644 target/linux/generic/backport-6.18/212-v6.17-of-reserved_mem-Add-missing-IORESOURCE_MEM-flag-on-r.patch delete mode 100644 target/linux/generic/backport-6.18/400-v6.14-mtd-spinand-add-support-for-FORESEE-F35SQA001G.patch delete mode 100644 target/linux/generic/backport-6.18/401-v6.17-mtd-spinand-add-support-for-FudanMicro-FM25S01A.patch delete mode 100644 target/linux/generic/backport-6.18/402-v6.18-mtd-nand-move-chunk-to-core.patch delete mode 100644 target/linux/generic/backport-6.18/404-v6.19-mtd-spinand-fmsh-remove-QE-bit-for-FM25S01A-flash.patch delete mode 100644 target/linux/generic/backport-6.18/410-01-v6.14-mtd-rawnand-qcom-cleanup-qcom_nandc-driver.patch delete mode 100644 target/linux/generic/backport-6.18/410-02-v6.14-mtd-rawnand-qcom-Add-qcom-prefix-to-common-api.patch delete mode 100644 target/linux/generic/backport-6.18/410-03-v6.14-mtd-nand-Add-qpic_common-API-file.patch delete mode 100644 target/linux/generic/backport-6.18/410-04-v6.14-mtd-rawnand-qcom-use-FIELD_PREP-and-GENMASK.patch delete mode 100644 target/linux/generic/backport-6.18/410-05-v6.14-mtd-rawnand-qcom-fix-broken-config-in-qcom_param_pag.patch delete mode 100644 target/linux/generic/backport-6.18/410-06-v6.14-mtd-rawnand-qcom-Fix-build-issue-on-x86-architecture.patch delete mode 100644 target/linux/generic/backport-6.18/410-07-v6.15-spi-spi-qpic-add-driver-for-QCOM-SPI-NAND-flash-Inte.patch delete mode 100644 target/linux/generic/backport-6.18/410-08-v6.15-spi-spi-qpic-snand-Fix-ECC_CFG_ECC_DISABLE-shift-in-.patch delete mode 100644 target/linux/generic/backport-6.18/410-09-v6.15-spi-spi-qpic-snand-avoid-memleak-in-qcom_spi_ecc_ini.patch delete mode 100644 target/linux/generic/backport-6.18/410-10-v6.15-spi-SPI_QPIC_SNAND-should-be-tristate-and-depend-on-.patch delete mode 100644 target/linux/generic/backport-6.18/410-11-v6.15-spi-spi-qpic-snand-propagate-errors-from-qcom_spi_block_erase.patch delete mode 100644 target/linux/generic/backport-6.18/410-12-v6.15-spi-spi-qpic-snand-fix-NAND_READ_LOCATION_2-register-handling.patch delete mode 100644 target/linux/generic/backport-6.18/410-13-v6.15-spi-spi-qpic-snand-use-kmalloc-for-OOB-buffer-alloca.patch delete mode 100644 target/linux/generic/backport-6.18/410-14-v6.16-spi-spi-qpic-snand-remove-unused-wlen-member-of-struct-qpic_spi_nand.patch delete mode 100644 target/linux/generic/backport-6.18/411-v6.15-mtd-nand-Drop-explicit-test-for-built-in-CONFIG_SPI_.patch delete mode 100644 target/linux/generic/backport-6.18/412-v6.16-next-spi-spi-qpic-snand-validate-user-chip-specific-ECC-properties.patch delete mode 100644 target/linux/generic/backport-6.18/413-v6.16-spi-spi-qpic-snand-use-CW_PER_PAGE_MASK-bitmask.patch delete mode 100644 target/linux/generic/backport-6.18/414-v6.16-spi-spi-qpic-snand-reallocate-BAM-transactions.patch delete mode 100644 target/linux/generic/backport-6.18/415-v6.16-spi-spi-qpic-snand-don-t-hardcode-ECC-steps.patch delete mode 100644 target/linux/generic/backport-6.18/416-v6.17-mtd-nand-qpic-common-add-defines-for-ECC_MODE-values.patch delete mode 100644 target/linux/generic/backport-6.18/417-v6.17-spi-spi-qpic-snand-add-support-for-8-bits-ECC-strength.patch delete mode 100644 target/linux/generic/backport-6.18/418-v6.17-spi-spi-qpic-snand-use-correct-CW_PER_PAGE-value-for.patch delete mode 100644 target/linux/generic/backport-6.18/419-v6.17-spi-spi-qpic-snand-fix-calculating-of-ECC-OOB-region.patch delete mode 100644 target/linux/generic/backport-6.18/420-01-v6.16-mtd-rawnand-brcmnand-remove-unused-parameters.patch delete mode 100644 target/linux/generic/backport-6.18/420-02-v6.16-mtd-nand-brcmnand-fix-NAND-timeout-when-accessing-eM.patch delete mode 100644 target/linux/generic/backport-6.18/420-03-v6.16-mtd-rawnand-brcmnand-legacy-exec_op-implementation.patch delete mode 100644 target/linux/generic/backport-6.18/422-v6.17-spi-spi-qpic-snand-unregister-ECC-engine-on-probe-er.patch delete mode 100644 target/linux/generic/backport-6.18/429-01-v6.18-mtd-spinand-fix-direct-mapping-creation-sizes.patch delete mode 100644 target/linux/generic/backport-6.18/429-02-v6.18-mtd-spinand-try-a-regular-dirmap-if-creating-a-di.patch delete mode 100644 target/linux/generic/backport-6.18/429-03-v6.18-mtd-spinand-repeat-reading-in-regular-mode-if-con.patch delete mode 100644 target/linux/generic/backport-6.18/430-v6.14-mtd-spinand-Introduce-a-way-to-avoid-raw-access.patch delete mode 100644 target/linux/generic/backport-6.18/431-v6.14-mtd-spinand-Add-support-for-SkyHigh-S35ML-3-family.patch delete mode 100644 target/linux/generic/backport-6.18/500-01-v6.13-block-add-support-for-defining-read-only-partitions.patch delete mode 100644 target/linux/generic/backport-6.18/500-02-v6.13-block-introduce-add_disk_fwnode.patch delete mode 100644 target/linux/generic/backport-6.18/500-03-v6.13-mmc-block-attach-partitions-fwnode-if-found-in-mmc-c.patch delete mode 100644 target/linux/generic/backport-6.18/500-04-v6.13-block-add-support-for-partition-table-defined-in-OF.patch delete mode 100644 target/linux/generic/backport-6.18/600-01-v6.13-net-phylink-move-manual-flow-control-setting.patch delete mode 100644 target/linux/generic/backport-6.18/600-02-v6.13-net-phylink-move-MLO_AN_FIXED-resolve-handling-to-if.patch delete mode 100644 target/linux/generic/backport-6.18/600-03-v6.13-net-phylink-move-MLO_AN_PHY-resolve-handling-to-if-s.patch delete mode 100644 target/linux/generic/backport-6.18/600-04-v6.13-net-phylink-remove-switch-statement-in-resolve-handl.patch delete mode 100644 target/linux/generic/backport-6.18/600-05-v6.13-net-phylink-clean-up-phylink_resolve.patch delete mode 100644 target/linux/generic/backport-6.18/601-01-v6.14-net-phylink-pass-phylink-and-pcs-into-phylink_pcs_ne.patch delete mode 100644 target/linux/generic/backport-6.18/601-02-v6.14-net-phylink-split-cur_link_an_mode-into-requested-an.patch delete mode 100644 target/linux/generic/backport-6.18/601-03-v6.14-net-phylink-add-debug-for-phylink_major_config.patch delete mode 100644 target/linux/generic/backport-6.18/601-04-v6.14-net-phy-add-phy_inband_caps.patch delete mode 100644 target/linux/generic/backport-6.18/601-05-v6.14-net-phy-bcm84881-implement-phy_inband_caps-method.patch delete mode 100644 target/linux/generic/backport-6.18/601-06-v6.14-net-phy-marvell-implement-phy_inband_caps-method.patch delete mode 100644 target/linux/generic/backport-6.18/601-07-v6.14-net-phy-add-phy_config_inband.patch delete mode 100644 target/linux/generic/backport-6.18/601-08-v6.14-net-phy-marvell-implement-config_inband-method.patch delete mode 100644 target/linux/generic/backport-6.18/601-09-v6.14-net-phylink-add-pcs_inband_caps-method.patch delete mode 100644 target/linux/generic/backport-6.18/601-10-v6.14-net-mvneta-implement-pcs_inband_caps-method.patch delete mode 100644 target/linux/generic/backport-6.18/601-11-v6.14-net-mvpp2-implement-pcs_inband_caps-method.patch delete mode 100644 target/linux/generic/backport-6.18/601-12-v6.14-net-phylink-add-negotiation-of-in-band-capabilities.patch delete mode 100644 target/linux/generic/backport-6.18/601-13-v6.14-net-phylink-remove-phylink_phy_no_inband.patch delete mode 100644 target/linux/generic/backport-6.18/602-01-v6.14-net-pcs-pcs-lynx-implement-pcs_inband_caps-method.patch delete mode 100644 target/linux/generic/backport-6.18/602-02-v6.14-net-pcs-pcs-mtk-lynxi-implement-pcs_inband_caps-meth.patch delete mode 100644 target/linux/generic/backport-6.18/602-03-v6.14-net-pcs-xpcs-implement-pcs_inband_caps-method.patch delete mode 100644 target/linux/generic/backport-6.18/605-02-v6.17-net-phylink-provide-phylink_get_inband_type.patch delete mode 100644 target/linux/generic/backport-6.18/605-03-v6.17-net-phylink-disable-autoneg-for-interfaces-that-have.patch delete mode 100644 target/linux/generic/backport-6.18/610-01-v6.13-net-dsa-use-ethtool-string-helpers.patch delete mode 100644 target/linux/generic/backport-6.18/610-02-v6.15-net-dsa-b53-mdio-add-support-for-BCM53101.patch delete mode 100644 target/linux/generic/backport-6.18/610-03-v6.16-net-dsa-b53-implement-setting-ageing-time.patch delete mode 100644 target/linux/generic/backport-6.18/610-04-v6.16-net-dsa-b53-do-not-configure-bcm63xx-s-IMP-port-inte.patch delete mode 100644 target/linux/generic/backport-6.18/611-01-v6.17-net-dsa-tag_brcm-add-support-for-legacy-FCS-tags.patch delete mode 100644 target/linux/generic/backport-6.18/611-02-v6.17-net-dsa-b53-support-legacy-FCS-tags.patch delete mode 100644 target/linux/generic/backport-6.18/611-03-v6.17-net-dsa-b53-detect-BCM5325-variants.patch delete mode 100644 target/linux/generic/backport-6.18/611-04-v6.17-net-dsa-b53-add-support-for-FDB-operations-on-5325-5365.patch delete mode 100644 target/linux/generic/backport-6.18/611-05-v6.17-net-dsa-b53-prevent-FAST_AGE-access-on-BCM5325.patch delete mode 100644 target/linux/generic/backport-6.18/611-06-v6.17-net-dsa-b53-prevent-BRCM_HDR-access-on-older-devices.patch delete mode 100644 target/linux/generic/backport-6.18/611-07-v6.17-net-dsa-b53-fix-unicast-multicast-flooding-on-BCM5325.patch delete mode 100644 target/linux/generic/backport-6.18/611-08-v6.18-net-dsa-b53-Add-phy_enable-phy_disable-methods.patch delete mode 100644 target/linux/generic/backport-6.18/611-09-v6.18-net-dsa-b53-Define-chip-IDs-for-more-bcm63xx-SoCs.patch delete mode 100644 target/linux/generic/backport-6.18/611-10-v6.18-net-dsa-b53-mmap-Add-syscon-reference-and-register-layout-for-bcm63268.patch delete mode 100644 target/linux/generic/backport-6.18/611-11-v6.18-net-dsa-b53-mmap-Add-register-layout-for-bcm6318.patch delete mode 100644 target/linux/generic/backport-6.18/611-12-v6.18-net-dsa-b53-mmap-Add-register-layout-for-bcm6368.patch delete mode 100644 target/linux/generic/backport-6.18/611-13-v6.18-net-dsa-b53-mmap-Implement-bcm63xx-ephy-power-control.patch delete mode 100644 target/linux/generic/backport-6.18/611-14-v6.18-net-dsa-b53-mmap-Add-gphy-port-to-phy-info-for-bcm63268.patch delete mode 100644 target/linux/generic/backport-6.18/611-15-v6.18-net-dsa-b53-mmap-Implement-bcm63268-gphy-power-control.patch delete mode 100644 target/linux/generic/backport-6.18/611-16-v6.18-net-dsa-b53-fix-reserved-register-access-in-b53_fdb_dump.patch delete mode 100644 target/linux/generic/backport-6.18/611-17-v6.18-net-dsa-b53-fix-ageing-time-for-BCM53101.patch delete mode 100644 target/linux/generic/backport-6.18/611-18-v6.18-net-dsa-b53-properly-bound-ARL-searches-for-4-ARL-bin-chips.patch delete mode 100644 target/linux/generic/backport-6.18/611-19-v6.18-net-dsa-tag_brcm-do-not-mark-link-local-traffic-as-offloaded.patch delete mode 100644 target/linux/generic/backport-6.18/612-01-v6.19-net-dsa-b53-b53_arl_read-25-use-the-entry-for-comparision.patch delete mode 100644 target/linux/generic/backport-6.18/612-02-v6.19-net-dsa-b53-move-reading-ARL-entries-into-their-own-function.patch delete mode 100644 target/linux/generic/backport-6.18/612-03-v6.19-net-dsa-b53-move-writing-ARL-entries-into-their-own-functions.patch delete mode 100644 target/linux/generic/backport-6.18/612-04-v6.19-net-dsa-b53-provide-accessors-for-accessing-ARL_SRCH_CTL.patch delete mode 100644 target/linux/generic/backport-6.18/612-05-v6.19-net-dsa-b53-split-reading-search-entry-into-their-own-functions.patch delete mode 100644 target/linux/generic/backport-6.18/612-06-v6.19-net-dsa-b53-move-ARL-entry-functions-into-ops-struct.patch delete mode 100644 target/linux/generic/backport-6.18/612-07-v6.19-net-dsa-b53-add-support-for-5389-5397-5398-ARL-entry-format.patch delete mode 100644 target/linux/generic/backport-6.18/612-08-v6.19-net-dsa-b53-add-support-for-bcm63xx-ARL-entry-format.patch delete mode 100644 target/linux/generic/backport-6.18/613-01-v6.19-net-dsa-b53-fix-VLAN_ID_IDX-write-size-for-BCM5325-65.patch delete mode 100644 target/linux/generic/backport-6.18/613-02-v6.19-net-dsa-b53-fix-extracting-VID-from-entry-for-BCM5325-65.patch delete mode 100644 target/linux/generic/backport-6.18/613-03-v6.19-net-dsa-b53-use-same-ARL-search-result-offset-for-BCM5325-65.patch delete mode 100644 target/linux/generic/backport-6.18/613-04-v6.19-net-dsa-b53-fix-CPU-port-unicast-ARL-entries-for-BCM5325-65.patch delete mode 100644 target/linux/generic/backport-6.18/613-05-v6.19-net-dsa-b53-fix-BCM5325-65-ARL-entry-multicast-port-masks.patch delete mode 100644 target/linux/generic/backport-6.18/613-06-v6.19-net-dsa-b53-fix-BCM5325-65-ARL-entry-VIDs.patch delete mode 100644 target/linux/generic/backport-6.18/620-v6.15-ppp-use-IFF_NO_QUEUE-in-virtual-interfaces.patch delete mode 100644 target/linux/generic/backport-6.18/621-v6.17-ppp-convert-to-percpu-netstats.patch delete mode 100644 target/linux/generic/backport-6.18/622-v6.18-ppp-remove-rwlock-usage.patch delete mode 100644 target/linux/generic/backport-6.18/623-v6.18-pppoe-remove-rwlock-usage.patch delete mode 100644 target/linux/generic/backport-6.18/624-v6.18-pppoe-drop-sock-reference-counting-on-fast-path.patch delete mode 100644 target/linux/generic/backport-6.18/626-01-v6.13-net-pse-pd-Add-power-limit-check.patch delete mode 100644 target/linux/generic/backport-6.18/626-02-v6.13-net-pse-pd-tps23881-Simplify-function-returns.patch delete mode 100644 target/linux/generic/backport-6.18/626-03-v6.13-net-pse-pd-tps23881-Use-helpers-to-calculate-bit-offset.patch delete mode 100644 target/linux/generic/backport-6.18/626-04-v6.13-net-pse-pd-tps23881-Add-missing-configuration-register.patch delete mode 100644 target/linux/generic/backport-6.18/626-05-v6.13-net-pse-pd-Split-ethtool_get_status-into-multiple-callbacks.patch delete mode 100644 target/linux/generic/backport-6.18/626-06-v6.13-net-pse-pd-Remove-is_enabled-callback-from-drivers.patch delete mode 100644 target/linux/generic/backport-6.18/626-07-v6.13-net-pse-pd-tps23881-Add-power-limit-and-measurement-features.patch delete mode 100644 target/linux/generic/backport-6.18/626-08-v6.13-net-pse-pd-Fix-missing-PI-of_node-description.patch delete mode 100644 target/linux/generic/backport-6.18/626-09-v6.13-net-pse-pd-Clean-ethtool-header-of-PSE-structures.patch delete mode 100644 target/linux/generic/backport-6.18/626-10-v6.17-net-pse-pd-Introduce-attached_phydev-to-pse-control.patch delete mode 100644 target/linux/generic/backport-6.18/626-11-v6.17-net-pse-pd-Add-support-for-reporting-events.patch delete mode 100644 target/linux/generic/backport-6.18/626-12-v6.17-net-pse-pd-tps23881-Add-support-for-PSE-events.patch delete mode 100644 target/linux/generic/backport-6.18/626-13-v6.17-net-pse-pd-Add-support-for-PSE-power-domains.patch delete mode 100644 target/linux/generic/backport-6.18/626-14-v6.17-net-pse-pd-ethtool-Add-support-for-power-domains-index.patch delete mode 100644 target/linux/generic/backport-6.18/626-15-v6.17-net-pse-pd-Add-helper-to-report-hw-enable-status.patch delete mode 100644 target/linux/generic/backport-6.18/626-16-v6.17-net-pse-pd-Add-support-for-budget-evaluation-strategies.patch delete mode 100644 target/linux/generic/backport-6.18/626-16b-v6.17-regulator-Add-support-for-power-budget.patch delete mode 100644 target/linux/generic/backport-6.18/626-17-v6.17-net-pse-pd-pd692x0-Add-PSE-PI-priority-feature.patch delete mode 100644 target/linux/generic/backport-6.18/626-18-v6.17-net-pse-pd-pd692x0-Add-controller-and-manager-power.patch delete mode 100644 target/linux/generic/backport-6.18/626-19-v6.17-net-pse-pd-tps23881-Add-static-port-priority-feature.patch delete mode 100644 target/linux/generic/backport-6.18/626-20-v6.17-net-pse-pd-pd692x0-reduce-stack-usage.patch delete mode 100644 target/linux/generic/backport-6.18/626-21-v6.18-net-pse-pd-pd692x0-Fix-power-budget-leak.patch delete mode 100644 target/linux/generic/backport-6.18/626-22-v6.18-net-pse-pd-pd692x0-Skip-power-budget-when-undefined.patch delete mode 100644 target/linux/generic/backport-6.18/626-23-v6.18-net-pse-pd-Add-Si3474-PSE-controller-driver.patch delete mode 100644 target/linux/generic/backport-6.18/626-24-v6.19-net-pse-pd-tps23881-Fix-current-measurement-scaling.patch delete mode 100644 target/linux/generic/backport-6.18/626-v6.16-net-bridge-locally-receive-all-multicast-packets-if-.patch delete mode 100644 target/linux/generic/backport-6.18/627-01-v6.17-net-pse-pd-Add-ethtool_netlink_generated-header.patch delete mode 100644 target/linux/generic/backport-6.18/627-02-v6.17-net-ethtool-Add-PSE-port-priority-support.patch delete mode 100644 target/linux/generic/backport-6.18/630-v6.13-net-usb-qmi_wwan-add-Quectel-RG255C.patch delete mode 100644 target/linux/generic/backport-6.18/630-v6.14-PM-sleep-wakeirq-Introduce-device-managed-variant-of.patch delete mode 100644 target/linux/generic/backport-6.18/710-v6.16-igc-enable-HW-vlan-tag-insertion-stripping-by-defaul.patch delete mode 100644 target/linux/generic/backport-6.18/720-01-v6.13-net-phy-mediatek-ge-soc-Fix-coding-style.patch delete mode 100644 target/linux/generic/backport-6.18/720-02-v6.13-net-phy-mediatek-ge-soc-Shrink-line-wrapping-to-80-c.patch delete mode 100644 target/linux/generic/backport-6.18/720-03-v6.13-net-phy-mediatek-ge-soc-Propagate-error-code-correct.patch delete mode 100644 target/linux/generic/backport-6.18/720-04-v6.13-net-phy-mediatek-Re-organize-MediaTek-ethernet-phy-d.patch delete mode 100644 target/linux/generic/backport-6.18/720-05-v6.13-net-phy-mediatek-Move-LED-helper-functions-into-mtk-.patch delete mode 100644 target/linux/generic/backport-6.18/720-06-v6.13-net-phy-mediatek-Improve-readability-of-mtk-phy-lib..patch delete mode 100644 target/linux/generic/backport-6.18/720-07-v6.13-net-phy-mediatek-Integrate-read-write-page-helper-fu.patch delete mode 100644 target/linux/generic/backport-6.18/720-08-v6.13-net-phy-mediatek-add-MT7530-MT7531-s-PHY-ID-macros.patch delete mode 100644 target/linux/generic/backport-6.18/720-09-v6.14-net-phy-Constify-struct-mdio_device_id.patch delete mode 100644 target/linux/generic/backport-6.18/720-10-v6.15-net-phy-mediatek-Change-to-more-meaningful-macros.patch delete mode 100644 target/linux/generic/backport-6.18/720-11-v6.15-net-phy-mediatek-Add-token-ring-access-helper-functi.patch delete mode 100644 target/linux/generic/backport-6.18/720-12-v6.15-net-phy-mediatek-Add-token-ring-set-bit-operation-su.patch delete mode 100644 target/linux/generic/backport-6.18/720-13-v6.15-net-phy-mediatek-Add-token-ring-clear-bit-operation-.patch delete mode 100644 target/linux/generic/backport-6.18/720-14-v6.15-net-phy-mediatek-Move-some-macros-to-phy-lib-for-lat.patch delete mode 100644 target/linux/generic/backport-6.18/720-15-v6.16-net-phy-mediatek-permit-to-compile-test-GE-SOC-PHY-d.patch delete mode 100644 target/linux/generic/backport-6.18/720-16-v6.16-net-phy-mediatek-add-Airoha-PHY-ID-to-SoC-driver.patch delete mode 100644 target/linux/generic/backport-6.18/720-17-v6.16-net-phy-mediatek-init-val-in-.phy_led_polarity_set-f.patch delete mode 100644 target/linux/generic/backport-6.18/721-01-v6.15-net-ethernet-mediatek-add-EEE-support.patch delete mode 100644 target/linux/generic/backport-6.18/730-01-v6.13-net-phy-aquantia-allow-forcing-order-of-MDI-pairs.patch delete mode 100644 target/linux/generic/backport-6.18/730-02-v6.13-net-phy-aquantia-fix-return-value-check-in-aqr107_co.patch delete mode 100644 target/linux/generic/backport-6.18/730-03-v6.13-net-phy-support-active-high-property-for-PHY-LEDs.patch delete mode 100644 target/linux/generic/backport-6.18/730-04-v6.13-net-phy-aquantia-correctly-describe-LED-polarity-ove.patch delete mode 100644 target/linux/generic/backport-6.18/730-05-v6.13-net-phy-mxl-gpy-add-basic-LED-support.patch delete mode 100644 target/linux/generic/backport-6.18/730-06-v6.13-net-phy-mxl-gpy-add-missing-support-for-TRIGGER_NETD.patch delete mode 100644 target/linux/generic/backport-6.18/730-07-v6.13-net-phy-mxl-gpy-correctly-describe-LED-polarity.patch delete mode 100644 target/linux/generic/backport-6.18/730-08-v6.13-net-phy-intel-xway-add-support-for-PHY-LEDs.patch delete mode 100644 target/linux/generic/backport-6.18/730-09-v6.18-net-phy-mxl-gpy-fix-link-properties-on-USXGMII-and-i.patch delete mode 100644 target/linux/generic/backport-6.18/731-v6.18-net-mediatek-wed-Introduce-MT7992-WED-support-to-MT7.patch delete mode 100644 target/linux/generic/backport-6.18/732-v6.18-wifi-mt76-wed-use-proper-wed-reference-in-mt76-wed-d.patch delete mode 100644 target/linux/generic/backport-6.18/733-v6.18-net-mtk-wed-add-dma-mask-limitation-and-GFP_DMA32-fo.patch delete mode 100644 target/linux/generic/backport-6.18/735-v6.13-net-phy-avoid-undefined-behavior-in-_led_polarity_se.patch delete mode 100644 target/linux/generic/backport-6.18/740-v6.13-net-dsa-mv88e6xxx-Support-LED-control.patch delete mode 100644 target/linux/generic/backport-6.18/741-v6.13-net-dsa-mv88e6xxx-fix-unreleased-fwnode_handle-in-se.patch delete mode 100644 target/linux/generic/backport-6.18/742-v6.17-net-dsa-mv88e6xxx-Fix-fwnode-reference-leaks-in-mv88.patch delete mode 100644 target/linux/generic/backport-6.18/760-v6.18-net-phy-introduce-phy_id_compare_model-PHY-ID-helper.patch delete mode 100644 target/linux/generic/backport-6.18/780-01-v6.13-r8169-remove-original-workaround-for-RTL8125-broken-.patch delete mode 100644 target/linux/generic/backport-6.18/780-02-v6.13-r8169-enable-SG-TSO-on-selected-chip-versions-per-de.patch delete mode 100644 target/linux/generic/backport-6.18/780-03-v6.13-r8169-implement-additional-ethtool-stats-ops.patch delete mode 100644 target/linux/generic/backport-6.18/780-04-v6.13-r8169-don-t-take-RTNL-lock-in-rtl_task.patch delete mode 100644 target/linux/generic/backport-6.18/780-05-v6.13-replace-custom-flag-with-disable_work-et-al.patch delete mode 100644 target/linux/generic/backport-6.18/780-06-v6.13-r8169-avoid-duplicated-messages-if-loading-firmware-.patch delete mode 100644 target/linux/generic/backport-6.18/780-07-v6.13-r8169-remove-rtl_dash_loop_wait_high-low.patch delete mode 100644 target/linux/generic/backport-6.18/780-08-v6.13-r8169-enable-EEE-at-2.5G-per-default-on-RTL8125B.patch delete mode 100644 target/linux/generic/backport-6.18/780-10-v6.13-r8169-fix-inconsistent-indenting-in-rtl8169_get_eth_.patch delete mode 100644 target/linux/generic/backport-6.18/780-11-v6.13-r8169-align-RTL8125-EEE-config-with-vendor-driver.patch delete mode 100644 target/linux/generic/backport-6.18/780-12-v6.13-r8169-align-RTL8125-RTL8126-PHY-config-with-vendor-d.patch delete mode 100644 target/linux/generic/backport-6.18/780-13-v6.13-r8169-align-RTL8126-EEE-config-with-vendor-driver.patch delete mode 100644 target/linux/generic/backport-6.18/780-14-v6.13-r8169-improve-initialization-of-RSS-registers-on-RTL.patch delete mode 100644 target/linux/generic/backport-6.18/780-15-v6.13-r8169-remove-leftover-locks-after-reverted-change.patch delete mode 100644 target/linux/generic/backport-6.18/780-16-v6.13-r8169-improve-__rtl8169_set_wol.patch delete mode 100644 target/linux/generic/backport-6.18/780-17-v6.13-r8169-improve-rtl_set_d3_pll_down.patch delete mode 100644 target/linux/generic/backport-6.18/780-18-v6.13-r8169-align-WAKE_PHY-handling-with-r8125-r8126-vendo.patch delete mode 100644 target/linux/generic/backport-6.18/780-19-v6.13-r8169-use-helper-r8169_mod_reg8_cond-to-simplify-rtl.patch delete mode 100644 target/linux/generic/backport-6.18/780-20-v6.13-r8169-copy-vendor-driver-2.5G-5G-EEE-advertisement-c.patch delete mode 100644 target/linux/generic/backport-6.18/780-21-v6.14-r8169-remove-unused-flag-RTL_FLAG_TASK_RESET_NO_QUEU.patch delete mode 100644 target/linux/generic/backport-6.18/780-22-v6.14-r8169-remove-support-for-chip-version-11.patch delete mode 100644 target/linux/generic/backport-6.18/780-23-v6.14-r8169-adjust-version-numbering-for-RTL8126.patch delete mode 100644 target/linux/generic/backport-6.18/780-24-v6.14-r8169-add-support-for-RTL8125D-rev.b.patch delete mode 100644 target/linux/generic/backport-6.18/780-25-v6.14-r8169-add-support-for-RTL8125BP-rev.b.patch delete mode 100644 target/linux/generic/backport-6.18/780-26-v6.15-r8169-make-Kconfig-option-for-LED-support-user-visib.patch delete mode 100644 target/linux/generic/backport-6.18/780-28-v6.15-r8169-add-support-for-Intel-Killer-E5000.patch delete mode 100644 target/linux/generic/backport-6.18/780-29-v6.15-r8169-add-PHY-c45-ops-for-MDIO_MMD_VENDOR2-registers.patch delete mode 100644 target/linux/generic/backport-6.18/780-30-v6.15-r8169-increase-max-jumbo-packet-size-on-RTL8125-RTL8.patch delete mode 100644 target/linux/generic/backport-6.18/780-31-v6.15-r8169-switch-away-from-deprecated-pcim_iomap_table.patch delete mode 100644 target/linux/generic/backport-6.18/780-32-v6.15-r8169-enable-RTL8168H-RTL8168EP-RTL8168FP-ASPM-suppo.patch delete mode 100644 target/linux/generic/backport-6.18/780-34-v6.16-r8169-add-helper-rtl_csi_mod-for-accessing-extended.patch delete mode 100644 target/linux/generic/backport-6.18/780-35-v6.16-r8169-add-helper-rtl8125_phy_param.patch delete mode 100644 target/linux/generic/backport-6.18/780-36-v6.16-r8169-refactor-chip-version-detection.patch delete mode 100644 target/linux/generic/backport-6.18/780-37-v6.16-r8169-add-RTL_GIGA_MAC_VER_LAST-to-facilitate-adding.patch delete mode 100644 target/linux/generic/backport-6.18/780-38-v6.16-r8169-use-pci_prepare_to_sleep-in-rtl_shutdown.patch delete mode 100644 target/linux/generic/backport-6.18/780-39-v6.16-r8169-merge-chip-versions-70-and-71-RTL8126A.patch delete mode 100644 target/linux/generic/backport-6.18/780-40-v6.16-r8169-merge-chip-versions-64-and-65-RTL8125D.patch delete mode 100644 target/linux/generic/backport-6.18/780-41-v6.16-r8169-merge-chip-versions-52-and-53-RTL8117.patch delete mode 100644 target/linux/generic/backport-6.18/780-42-v6.16-r8169-add-support-for-RTL8127A.patch delete mode 100644 target/linux/generic/backport-6.18/781-01-v6.13-net-phy-realtek-read-duplex-and-gbit-master-from-PHY.patch delete mode 100644 target/linux/generic/backport-6.18/781-02-v6.13-net-phy-realtek-change-order-of-calls-in-C22-read_st.patch delete mode 100644 target/linux/generic/backport-6.18/781-03-v6.13-net-phy-realtek-clear-1000Base-T-link-partner-advert.patch delete mode 100644 target/linux/generic/backport-6.18/781-06-v6.14-net-phy-realtek-add-support-for-reading-MDIO_MMD_VEN.patch delete mode 100644 target/linux/generic/backport-6.18/781-07-v6.14-net-phy-realtek-clear-1000Base-T-lpa-if-link-is-down.patch delete mode 100644 target/linux/generic/backport-6.18/781-08-v6.14-net-phy-realtek-clear-master_slave_state-if-link-is-.patch delete mode 100644 target/linux/generic/backport-6.18/781-09-v6.14-net-phy-realtek-always-clear-NBase-T-lpa.patch delete mode 100644 target/linux/generic/backport-6.18/781-10-v6.14-net-phy-move-realtek-PHY-driver-to-its-own-subdirect.patch delete mode 100644 target/linux/generic/backport-6.18/781-11-v6.14-net-phy-realtek-add-hwmon-support-for-temp-sensor-on.patch delete mode 100644 target/linux/generic/backport-6.18/781-12-v6.14-net-phy-realtek-HWMON-support-for-standalone-version.patch delete mode 100644 target/linux/generic/backport-6.18/781-13-v6.15-net-phy-realtek-make-HWMON-support-a-user-visible-Kc.patch delete mode 100644 target/linux/generic/backport-6.18/781-14-v6.15-net-phy-realtek-use-string-choices-helpers.patch delete mode 100644 target/linux/generic/backport-6.18/781-15-v6.15-net-phy-realtek-improve-mmd-register-access-for-inte.patch delete mode 100644 target/linux/generic/backport-6.18/781-16-v6.15-net-phy-realtek-switch-from-paged-to-MMD-ops-in-rtl8.patch delete mode 100644 target/linux/generic/backport-6.18/781-17-v6.15-net-phy-realtek-add-helper-RTL822X_VND2_C22_REG.patch delete mode 100644 target/linux/generic/backport-6.18/781-18-v6.15-net-phy-realtek-add-defines-for-shadowed-c45-standar.patch delete mode 100644 target/linux/generic/backport-6.18/781-19-v6.15-net-phy-realtek-disable-PHY-mode-EEE.patch delete mode 100644 target/linux/generic/backport-6.18/781-20-v6.16-net-phy-realtek-Add-support-for-WOL-magic-packet-on.patch delete mode 100644 target/linux/generic/backport-6.18/781-21-v6.16-net-phy-realtek-remove-unsed-RTL821x_PHYSR-macros.patch delete mode 100644 target/linux/generic/backport-6.18/781-22-v6.16-net-phy-realtek-Clean-up-RTL821x-ExtPage-access.patch delete mode 100644 target/linux/generic/backport-6.18/781-23-v6.16-net-phy-realtek-add-RTL8211F-register-defines.patch delete mode 100644 target/linux/generic/backport-6.18/781-24-v6.16-net-phy-realtek-Group-RTL82-macro-definitions.patch delete mode 100644 target/linux/generic/backport-6.18/781-25-v6.16-net-phy-realtek-use-__set_bit-in-rtl8211f_led_hw_con.patch delete mode 100644 target/linux/generic/backport-6.18/781-26-v6.16-net-phy-realtek-Add-support-for-PHY-LEDs-on-RTL8211E.patch delete mode 100644 target/linux/generic/backport-6.18/781-27-v6.16-net-phy-realtek-add-RTL8127-internal-PHY.patch delete mode 100644 target/linux/generic/backport-6.18/781-28-v6.18-net-phy-realtek-convert-RTL8226-CG-to-c45-only.patch delete mode 100644 target/linux/generic/backport-6.18/781-29-v6.18-net-phy-realtek-enable-serdes-option-mode-for-RTL8226-CG.patch delete mode 100644 target/linux/generic/backport-6.18/782-01-v6.16-net-phy-pass-PHY-driver-to-.match_phy_device-OP.patch delete mode 100644 target/linux/generic/backport-6.18/782-04-v6.16-net-phy-introduce-genphy_match_phy_device.patch delete mode 100644 target/linux/generic/backport-6.18/782-05-v6.16-net-phy-Add-support-for-Aeonsemi-AS21xxx-PHYs.patch delete mode 100644 target/linux/generic/backport-6.18/783-01-v6.18-net-dsa-Move-KS8995-to-the-DSA-subsystem.patch delete mode 100644 target/linux/generic/backport-6.18/783-02-v6.18-net-dsa-ks8995-Add-proper-RESET-delay.patch delete mode 100644 target/linux/generic/backport-6.18/783-03-v6.18-net-dsa-ks8995-Delete-sysfs-register-access.patch delete mode 100644 target/linux/generic/backport-6.18/783-04-v6.18-net-dsa-ks8995-Add-basic-switch-set-up.patch delete mode 100644 target/linux/generic/backport-6.18/784-01-v6.17-net-phy-realtek-add-error-handling-to-rtl8211f_get_w.patch delete mode 100644 target/linux/generic/backport-6.18/784-02-v6.18-net-phy-realtek-Avoid-PHYCR2-access-if-PHYCR2-not-pr.patch delete mode 100644 target/linux/generic/backport-6.18/784-02-v6.18-net-phy-realtek-fix-RTL8211F-wake-on-lan-support.patch delete mode 100644 target/linux/generic/backport-6.18/784-03-v6.18-net-phy-realtek-fix-rtl8221b-vm-cg-name.patch delete mode 100644 target/linux/generic/backport-6.18/784-03-v6.18-net-phy-realtek-support-for-TRIGGER_NETDEV_LINK-on-R.patch delete mode 100644 target/linux/generic/backport-6.18/784-08-v6.19-net-phy-realtek-create-rtl8211f_config_rgmii_delay.patch delete mode 100644 target/linux/generic/backport-6.18/784-09-v6.19-net-phy-realtek-eliminate-priv-phycr2-variable.patch delete mode 100644 target/linux/generic/backport-6.18/784-10-v6.19-net-phy-realtek-eliminate-has_phycr2-variable.patch delete mode 100644 target/linux/generic/backport-6.18/784-11-v6.19-net-phy-realtek-allow-CLKOUT-to-be-disabled-on-RTL82.patch delete mode 100644 target/linux/generic/backport-6.18/784-12-v6.19-net-phy-realtek-eliminate-priv-phycr1-variable.patch delete mode 100644 target/linux/generic/backport-6.18/784-13-v6.19-net-phy-realtek-create-rtl8211f_config_phy_eee-helpe.patch delete mode 100644 target/linux/generic/backport-6.18/785-v6.18-r8169-fix-RTL8127-hang-on-suspend-shutdown.patch delete mode 100644 target/linux/generic/backport-6.18/786-01-v6.18-net-phy-introduce-phy_id_compare_vendor-PHY-ID-helpe.patch delete mode 100644 target/linux/generic/backport-6.18/786-02-v6.18-net-phy-as21xxx-better-handle-PHY-HW-reset-on-soft-r.patch delete mode 100644 target/linux/generic/backport-6.18/787-v6.19-net-phy-RTL8211FVD-Restore-disabling-of-PHY-mode-EEE.patch delete mode 100644 target/linux/generic/backport-6.18/800-v6.13-hwmon-Add-static-visibility-member-to-struct-hwmon_o.patch delete mode 100644 target/linux/generic/backport-6.18/801-01-v6.13-dt-bindings-clocks-add-binding-for-gated-fixed-clock.patch delete mode 100644 target/linux/generic/backport-6.18/801-02-v6.13-clk-clk-gpio-update-documentation-for-gpio-gate-cloc.patch delete mode 100644 target/linux/generic/backport-6.18/801-03-v6.13-clk-clk-gpio-use-dev_err_probe-for-gpio-get-failure.patch delete mode 100644 target/linux/generic/backport-6.18/801-04-v6.13-clk-clk-gpio-add-driver-for-gated-fixed-clocks.patch delete mode 100644 target/linux/generic/backport-6.18/810-v6.14-gpio-regmap-Use-generic-request-free-ops.patch delete mode 100644 target/linux/generic/backport-6.18/813-v6.16-pinctrl-aw9523-fix-can_sleep-flag-for-GPIO-chip.patch delete mode 100644 target/linux/generic/backport-6.18/820-v6.15-power-supply-sysfs-remove-duplicate-nul-termination-to-fix-build-with-GCC15.patch delete mode 100644 target/linux/generic/backport-6.18/891-v6.14-dt-bindings-leds-Add-LED1202-LED-Controller.patch delete mode 100644 target/linux/generic/backport-6.18/892-v6.14-leds-Add-LED1202-I2C-driver.patch delete mode 100644 target/linux/generic/backport-6.18/893-v6.14-leds_st1202-Fix-NULL-pointer-access-error.patch delete mode 100644 target/linux/generic/backport-6.18/900-v6.14-driver-core-add-a-faux-bus-for-use-when-a-simple-dev.patch diff --git a/target/linux/generic/backport-6.18/152-v6.16-net-wireguard-add-nonstring-annotation-to-fix-build-with-GCC15.patch b/target/linux/generic/backport-6.18/152-v6.16-net-wireguard-add-nonstring-annotation-to-fix-build-with-GCC15.patch deleted file mode 100644 index 1fdf2f1dbd..0000000000 --- a/target/linux/generic/backport-6.18/152-v6.16-net-wireguard-add-nonstring-annotation-to-fix-build-with-GCC15.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 71e5da46e78c1cd24e2feed251a2845327447ad8 Mon Sep 17 00:00:00 2001 -From: Kees Cook -Date: Wed, 21 May 2025 23:27:04 +0200 -Subject: wireguard: global: add __nonstring annotations for unterminated - strings - -When a character array without a terminating NUL character has a static -initializer, GCC 15's -Wunterminated-string-initialization will only -warn if the array lacks the "nonstring" attribute[1]. Mark the arrays -with __nonstring to correctly identify the char array as "not a C string" -and thereby eliminate the warning: - -../drivers/net/wireguard/cookie.c:29:56: warning: initializer-string for array of 'unsigned char' truncates NUL terminator but destination lacks 'nonstring' attribute (9 chars into 8 available) [-Wunterminated-string-initialization] - 29 | static const u8 mac1_key_label[COOKIE_KEY_LABEL_LEN] = "mac1----"; - | ^~~~~~~~~~ -../drivers/net/wireguard/cookie.c:30:58: warning: initializer-string for array of 'unsigned char' truncates NUL terminator but destination lacks 'nonstring' attribute (9 chars into 8 available) [-Wunterminated-string-initialization] - 30 | static const u8 cookie_key_label[COOKIE_KEY_LABEL_LEN] = "cookie--"; - | ^~~~~~~~~~ -../drivers/net/wireguard/noise.c:28:38: warning: initializer-string for array of 'unsigned char' truncates NUL terminator but destination lacks 'nonstring' attribute (38 chars into 37 available) [-Wunterminated-string-initialization] - 28 | static const u8 handshake_name[37] = "Noise_IKpsk2_25519_ChaChaPoly_BLAKE2s"; - | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -../drivers/net/wireguard/noise.c:29:39: warning: initializer-string for array of 'unsigned char' truncates NUL terminator but destination lacks 'nonstring' attribute (35 chars into 34 available) [-Wunterminated-string-initialization] - 29 | static const u8 identifier_name[34] = "WireGuard v1 zx2c4 Jason@zx2c4.com"; - | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The arrays are always used with their fixed size, so use __nonstring. - -Link: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=117178 [1] -Signed-off-by: Kees Cook -Signed-off-by: Jason A. Donenfeld -Link: https://patch.msgid.link/20250521212707.1767879-3-Jason@zx2c4.com -Signed-off-by: Paolo Abeni ---- - drivers/net/wireguard/cookie.c | 4 ++-- - drivers/net/wireguard/noise.c | 4 ++-- - 2 files changed, 4 insertions(+), 4 deletions(-) - ---- a/drivers/net/wireguard/cookie.c -+++ b/drivers/net/wireguard/cookie.c -@@ -26,8 +26,8 @@ void wg_cookie_checker_init(struct cooki - } - - enum { COOKIE_KEY_LABEL_LEN = 8 }; --static const u8 mac1_key_label[COOKIE_KEY_LABEL_LEN] = "mac1----"; --static const u8 cookie_key_label[COOKIE_KEY_LABEL_LEN] = "cookie--"; -+static const u8 mac1_key_label[COOKIE_KEY_LABEL_LEN] __nonstring = "mac1----"; -+static const u8 cookie_key_label[COOKIE_KEY_LABEL_LEN] __nonstring = "cookie--"; - - static void precompute_key(u8 key[NOISE_SYMMETRIC_KEY_LEN], - const u8 pubkey[NOISE_PUBLIC_KEY_LEN], ---- a/drivers/net/wireguard/noise.c -+++ b/drivers/net/wireguard/noise.c -@@ -25,8 +25,8 @@ - * <- e, ee, se, psk, {} - */ - --static const u8 handshake_name[37] = "Noise_IKpsk2_25519_ChaChaPoly_BLAKE2s"; --static const u8 identifier_name[34] = "WireGuard v1 zx2c4 Jason@zx2c4.com"; -+static const u8 handshake_name[37] __nonstring = "Noise_IKpsk2_25519_ChaChaPoly_BLAKE2s"; -+static const u8 identifier_name[34] __nonstring = "WireGuard v1 zx2c4 Jason@zx2c4.com"; - static u8 handshake_init_hash[NOISE_HASH_LEN] __ro_after_init; - static u8 handshake_init_chaining_key[NOISE_HASH_LEN] __ro_after_init; - static atomic64_t keypair_counter = ATOMIC64_INIT(0); diff --git a/target/linux/generic/backport-6.18/200-01-v6.13-jiffies-Define-secs_to_jiffies.patch b/target/linux/generic/backport-6.18/200-01-v6.13-jiffies-Define-secs_to_jiffies.patch deleted file mode 100644 index ad9af1d4bb..0000000000 --- a/target/linux/generic/backport-6.18/200-01-v6.13-jiffies-Define-secs_to_jiffies.patch +++ /dev/null @@ -1,60 +0,0 @@ -From b35108a51cf7bab58d7eace1267d7965978bcdb8 Mon Sep 17 00:00:00 2001 -From: Easwar Hariharan -Date: Wed, 30 Oct 2024 17:47:35 +0000 -Subject: [PATCH] jiffies: Define secs_to_jiffies() - -secs_to_jiffies() is defined in hci_event.c and cannot be reused by -other call sites. Hoist it into the core code to allow conversion of the -~1150 usages of msecs_to_jiffies() that either: - - - use a multiplier value of 1000 or equivalently MSEC_PER_SEC, or - - have timeouts that are denominated in seconds (i.e. end in 000) - -It's implemented as a macro to allow usage in static initializers. - -This will also allow conversion of yet more sites that use (sec * HZ) -directly, and improve their readability. - -Suggested-by: Michael Kelley -Signed-off-by: Easwar Hariharan -Signed-off-by: Thomas Gleixner -Reviewed-by: Luiz Augusto von Dentz -Link: https://lore.kernel.org/all/20241030-open-coded-timeouts-v3-1-9ba123facf88@linux.microsoft.com ---- - include/linux/jiffies.h | 13 +++++++++++++ - net/bluetooth/hci_event.c | 2 -- - 2 files changed, 13 insertions(+), 2 deletions(-) - ---- a/include/linux/jiffies.h -+++ b/include/linux/jiffies.h -@@ -526,6 +526,19 @@ static __always_inline unsigned long mse - } - } - -+/** -+ * secs_to_jiffies: - convert seconds to jiffies -+ * @_secs: time in seconds -+ * -+ * Conversion is done by simple multiplication with HZ -+ * -+ * secs_to_jiffies() is defined as a macro rather than a static inline -+ * function so it can be used in static initializers. -+ * -+ * Return: jiffies value -+ */ -+#define secs_to_jiffies(_secs) ((_secs) * HZ) -+ - extern unsigned long __usecs_to_jiffies(const unsigned int u); - #if !(USEC_PER_SEC % HZ) - static inline unsigned long _usecs_to_jiffies(const unsigned int u) ---- a/net/bluetooth/hci_event.c -+++ b/net/bluetooth/hci_event.c -@@ -42,8 +42,6 @@ - #define ZERO_KEY "\x00\x00\x00\x00\x00\x00\x00\x00" \ - "\x00\x00\x00\x00\x00\x00\x00\x00" - --#define secs_to_jiffies(_secs) msecs_to_jiffies((_secs) * 1000) -- - /* Handle HCI Event packets */ - - static void *hci_ev_skb_pull(struct hci_dev *hdev, struct sk_buff *skb, diff --git a/target/linux/generic/backport-6.18/200-02-v6.14-jiffies-Cast-to-unsigned-long-in-secs_to_jiffies-con.patch b/target/linux/generic/backport-6.18/200-02-v6.14-jiffies-Cast-to-unsigned-long-in-secs_to_jiffies-con.patch deleted file mode 100644 index cddd558dee..0000000000 --- a/target/linux/generic/backport-6.18/200-02-v6.14-jiffies-Cast-to-unsigned-long-in-secs_to_jiffies-con.patch +++ /dev/null @@ -1,35 +0,0 @@ -From bb2784d9ab49587ba4fbff37a319fff2924db289 Mon Sep 17 00:00:00 2001 -From: Easwar Hariharan -Date: Thu, 30 Jan 2025 19:26:58 +0000 -Subject: [PATCH] jiffies: Cast to unsigned long in secs_to_jiffies() - conversion - -While converting users of msecs_to_jiffies(), lkp reported that some range -checks would always be true because of the mismatch between the implied int -value of secs_to_jiffies() vs the unsigned long return value of the -msecs_to_jiffies() calls it was replacing. - -Fix this by casting the secs_to_jiffies() input value to unsigned long. - -Fixes: b35108a51cf7ba ("jiffies: Define secs_to_jiffies()") -Reported-by: kernel test robot -Signed-off-by: Easwar Hariharan -Signed-off-by: Thomas Gleixner -Cc: stable@vger.kernel.org -Link: https://lore.kernel.org/all/20250130192701.99626-1-eahariha@linux.microsoft.com -Closes: https://lore.kernel.org/oe-kbuild-all/202501301334.NB6NszQR-lkp@intel.com/ ---- - include/linux/jiffies.h | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/include/linux/jiffies.h -+++ b/include/linux/jiffies.h -@@ -537,7 +537,7 @@ static __always_inline unsigned long mse - * - * Return: jiffies value - */ --#define secs_to_jiffies(_secs) ((_secs) * HZ) -+#define secs_to_jiffies(_secs) (unsigned long)((_secs) * HZ) - - extern unsigned long __usecs_to_jiffies(const unsigned int u); - #if !(USEC_PER_SEC % HZ) diff --git a/target/linux/generic/backport-6.18/201-v6.13-of-property-add-of_graph_get_next_port.patch b/target/linux/generic/backport-6.18/201-v6.13-of-property-add-of_graph_get_next_port.patch deleted file mode 100644 index 5178dc83ae..0000000000 --- a/target/linux/generic/backport-6.18/201-v6.13-of-property-add-of_graph_get_next_port.patch +++ /dev/null @@ -1,199 +0,0 @@ -From 02ac5f9d6caec96071103f7c62b5117526e47b64 Mon Sep 17 00:00:00 2001 -From: Kuninori Morimoto -Date: Thu, 24 Oct 2024 02:20:02 +0000 -Subject: [PATCH] of: property: add of_graph_get_next_port() - -We have endpoint base functions - - of_graph_get_next_endpoint() - - of_graph_get_endpoint_count() - - for_each_endpoint_of_node() - -Here, for_each_endpoint_of_node() loop finds each endpoints - - ports { - port@0 { -(1) endpoint {...}; - }; - port@1 { -(2) endpoint {...}; - }; - ... - }; - -In above case, it finds endpoint as (1) -> (2) -> ... - -Basically, user/driver knows which port is used for what, but not in -all cases. For example on flexible/generic driver case, how many ports -are used is not fixed. - -For example Sound Generic Card driver which is very flexible/generic and -used from many venders can't know how many ports are used, and used for -what, because it depends on each vender SoC and/or its used board. - -And more, the port can have multi endpoints. For example Generic Sound -Card case, it supports many type of connection between CPU / Codec, and -some of them uses multi endpoint in one port. see below. - - ports { -(A) port@0 { -(1) endpoint@0 {...}; -(2) endpoint@1 {...}; - }; -(B) port@1 { -(3) endpoint {...}; - }; - ... - }; - -Generic Sound Card want to handle each connection via "port" base instead -of "endpoint" base. But, it is very difficult to handle each "port" via -existing for_each_endpoint_of_node(). Because getting each "port" via -of_get_parent() from each "endpoint" doesn't work. For example in above -case, both (1) (2) endpoint has same "port" (= A). - -Add "port" base functions. - -Signed-off-by: Kuninori Morimoto -Link: https://lore.kernel.org/r/87ldyeb5t9.wl-kuninori.morimoto.gx@renesas.com -Signed-off-by: Rob Herring (Arm) ---- - drivers/of/property.c | 54 ++++++++++++++++++++++++++++++++++++++++ - include/linux/of_graph.h | 28 +++++++++++++++++++++ - 2 files changed, 82 insertions(+) - ---- a/drivers/of/property.c -+++ b/drivers/of/property.c -@@ -631,6 +631,43 @@ struct device_node *of_graph_get_port_by - EXPORT_SYMBOL(of_graph_get_port_by_id); - - /** -+ * of_graph_get_next_port() - get next port node. -+ * @parent: pointer to the parent device node, or parent ports node -+ * @prev: previous port node, or NULL to get first -+ * -+ * Parent device node can be used as @parent whether device node has ports node -+ * or not. It will work same as ports@0 node. -+ * -+ * Return: A 'port' node pointer with refcount incremented. Refcount -+ * of the passed @prev node is decremented. -+ */ -+struct device_node *of_graph_get_next_port(const struct device_node *parent, -+ struct device_node *prev) -+{ -+ if (!parent) -+ return NULL; -+ -+ if (!prev) { -+ struct device_node *node __free(device_node) = -+ of_get_child_by_name(parent, "ports"); -+ -+ if (node) -+ parent = node; -+ -+ return of_get_child_by_name(parent, "port"); -+ } -+ -+ do { -+ prev = of_get_next_child(parent, prev); -+ if (!prev) -+ break; -+ } while (!of_node_name_eq(prev, "port")); -+ -+ return prev; -+} -+EXPORT_SYMBOL(of_graph_get_next_port); -+ -+/** - * of_graph_get_next_endpoint() - get next endpoint node - * @parent: pointer to the parent device node - * @prev: previous endpoint node, or NULL to get first -@@ -824,6 +861,23 @@ unsigned int of_graph_get_endpoint_count - EXPORT_SYMBOL(of_graph_get_endpoint_count); - - /** -+ * of_graph_get_port_count() - get the number of port in a device or ports node -+ * @np: pointer to the device or ports node -+ * -+ * Return: count of port of this device or ports node -+ */ -+unsigned int of_graph_get_port_count(struct device_node *np) -+{ -+ unsigned int num = 0; -+ -+ for_each_of_graph_port(np, port) -+ num++; -+ -+ return num; -+} -+EXPORT_SYMBOL(of_graph_get_port_count); -+ -+/** - * of_graph_get_remote_node() - get remote parent device_node for given port/endpoint - * @node: pointer to parent device_node containing graph port/endpoint - * @port: identifier (value of reg property) of the parent port node ---- a/include/linux/of_graph.h -+++ b/include/linux/of_graph.h -@@ -11,6 +11,7 @@ - #ifndef __LINUX_OF_GRAPH_H - #define __LINUX_OF_GRAPH_H - -+#include - #include - #include - -@@ -37,14 +38,29 @@ struct of_endpoint { - for (child = of_graph_get_next_endpoint(parent, NULL); child != NULL; \ - child = of_graph_get_next_endpoint(parent, child)) - -+/** -+ * for_each_of_graph_port - iterate over every port in a device or ports node -+ * @parent: parent device or ports node containing port -+ * @child: loop variable pointing to the current port node -+ * -+ * When breaking out of the loop, and continue to use the @child, you need to -+ * use return_ptr(@child) or no_free_ptr(@child) not to call __free() for it. -+ */ -+#define for_each_of_graph_port(parent, child) \ -+ for (struct device_node *child __free(device_node) = of_graph_get_next_port(parent, NULL);\ -+ child != NULL; child = of_graph_get_next_port(parent, child)) -+ - #ifdef CONFIG_OF - bool of_graph_is_present(const struct device_node *node); - int of_graph_parse_endpoint(const struct device_node *node, - struct of_endpoint *endpoint); - unsigned int of_graph_get_endpoint_count(const struct device_node *np); -+unsigned int of_graph_get_port_count(struct device_node *np); - struct device_node *of_graph_get_port_by_id(struct device_node *node, u32 id); - struct device_node *of_graph_get_next_endpoint(const struct device_node *parent, - struct device_node *previous); -+struct device_node *of_graph_get_next_port(const struct device_node *parent, -+ struct device_node *port); - struct device_node *of_graph_get_endpoint_by_regs( - const struct device_node *parent, int port_reg, int reg); - struct device_node *of_graph_get_remote_endpoint( -@@ -73,6 +89,11 @@ static inline unsigned int of_graph_get_ - return 0; - } - -+static inline unsigned int of_graph_get_port_count(struct device_node *np) -+{ -+ return 0; -+} -+ - static inline struct device_node *of_graph_get_port_by_id( - struct device_node *node, u32 id) - { -@@ -83,6 +104,13 @@ static inline struct device_node *of_gra - const struct device_node *parent, - struct device_node *previous) - { -+ return NULL; -+} -+ -+static inline struct device_node *of_graph_get_next_port( -+ const struct device_node *parent, -+ struct device_node *previous) -+{ - return NULL; - } - diff --git a/target/linux/generic/backport-6.18/202-v6.13-clk-Provide-devm_clk_bulk_get_all_enabled-helper.patch b/target/linux/generic/backport-6.18/202-v6.13-clk-Provide-devm_clk_bulk_get_all_enabled-helper.patch deleted file mode 100644 index c02e4ed6a2..0000000000 --- a/target/linux/generic/backport-6.18/202-v6.13-clk-Provide-devm_clk_bulk_get_all_enabled-helper.patch +++ /dev/null @@ -1,118 +0,0 @@ -From 51e32e897539663957f7a0950f66b48f8896efee Mon Sep 17 00:00:00 2001 -From: Cristian Ciocaltea -Date: Sat, 19 Oct 2024 14:16:00 +0300 -Subject: [PATCH] clk: Provide devm_clk_bulk_get_all_enabled() helper - -Commit 265b07df758a ("clk: Provide managed helper to get and enable bulk -clocks") added devm_clk_bulk_get_all_enable() function, but missed to -return the number of clocks stored in the clk_bulk_data table referenced -by the clks argument. Without knowing the number, it's not possible to -iterate these clocks when needed, hence the argument is useless and -could have been simply removed. - -Introduce devm_clk_bulk_get_all_enabled() variant, which is consistent -with devm_clk_bulk_get_all() in terms of the returned value: - - > 0 if one or more clocks have been stored - = 0 if there are no clocks - < 0 if an error occurred - -Moreover, the naming is consistent with devm_clk_get_enabled(), i.e. use -the past form of 'enable'. - -To reduce code duplication and improve patch readability, make -devm_clk_bulk_get_all_enable() use the new helper, as suggested by -Stephen Boyd. - -Reviewed-by: AngeloGioacchino Del Regno -Reviewed-by: Manivannan Sadhasivam -Signed-off-by: Cristian Ciocaltea -Link: https://lore.kernel.org/r/20241019-clk_bulk_ena_fix-v4-1-57f108f64e70@collabora.com -Signed-off-by: Stephen Boyd ---- - drivers/clk/clk-devres.c | 9 +++++---- - include/linux/clk.h | 21 ++++++++++++++++----- - 2 files changed, 21 insertions(+), 9 deletions(-) - ---- a/drivers/clk/clk-devres.c -+++ b/drivers/clk/clk-devres.c -@@ -218,8 +218,8 @@ static void devm_clk_bulk_release_all_en - clk_bulk_put_all(devres->num_clks, devres->clks); - } - --int __must_check devm_clk_bulk_get_all_enable(struct device *dev, -- struct clk_bulk_data **clks) -+int __must_check devm_clk_bulk_get_all_enabled(struct device *dev, -+ struct clk_bulk_data **clks) - { - struct clk_bulk_devres *devres; - int ret; -@@ -244,11 +244,12 @@ int __must_check devm_clk_bulk_get_all_e - } else { - clk_bulk_put_all(devres->num_clks, devres->clks); - devres_free(devres); -+ return ret; - } - -- return ret; -+ return devres->num_clks; - } --EXPORT_SYMBOL_GPL(devm_clk_bulk_get_all_enable); -+EXPORT_SYMBOL_GPL(devm_clk_bulk_get_all_enabled); - - static int devm_clk_match(struct device *dev, void *res, void *data) - { ---- a/include/linux/clk.h -+++ b/include/linux/clk.h -@@ -520,11 +520,13 @@ int __must_check devm_clk_bulk_get_all(s - struct clk_bulk_data **clks); - - /** -- * devm_clk_bulk_get_all_enable - Get and enable all clocks of the consumer (managed) -+ * devm_clk_bulk_get_all_enabled - Get and enable all clocks of the consumer (managed) - * @dev: device for clock "consumer" - * @clks: pointer to the clk_bulk_data table of consumer - * -- * Returns success (0) or negative errno. -+ * Returns a positive value for the number of clocks obtained while the -+ * clock references are stored in the clk_bulk_data table in @clks field. -+ * Returns 0 if there're none and a negative value if something failed. - * - * This helper function allows drivers to get all clocks of the - * consumer and enables them in one operation with management. -@@ -532,8 +534,8 @@ int __must_check devm_clk_bulk_get_all(s - * is unbound. - */ - --int __must_check devm_clk_bulk_get_all_enable(struct device *dev, -- struct clk_bulk_data **clks); -+int __must_check devm_clk_bulk_get_all_enabled(struct device *dev, -+ struct clk_bulk_data **clks); - - /** - * devm_clk_get - lookup and obtain a managed reference to a clock producer. -@@ -1041,7 +1043,7 @@ static inline int __must_check devm_clk_ - return 0; - } - --static inline int __must_check devm_clk_bulk_get_all_enable(struct device *dev, -+static inline int __must_check devm_clk_bulk_get_all_enabled(struct device *dev, - struct clk_bulk_data **clks) - { - return 0; -@@ -1136,6 +1138,15 @@ static inline struct clk *clk_get_sys(co - - #endif - -+/* Deprecated. Use devm_clk_bulk_get_all_enabled() */ -+static inline int __must_check -+devm_clk_bulk_get_all_enable(struct device *dev, struct clk_bulk_data **clks) -+{ -+ int ret = devm_clk_bulk_get_all_enabled(dev, clks); -+ -+ return ret > 0 ? 0 : ret; -+} -+ - /* clk_prepare_enable helps cases using clk_enable in non-atomic context. */ - static inline int clk_prepare_enable(struct clk *clk) - { diff --git a/target/linux/generic/backport-6.18/203-01-v6.13-of-address-Rework-bus-matching-to-avoid-warnings.patch b/target/linux/generic/backport-6.18/203-01-v6.13-of-address-Rework-bus-matching-to-avoid-warnings.patch deleted file mode 100644 index d7a6751861..0000000000 --- a/target/linux/generic/backport-6.18/203-01-v6.13-of-address-Rework-bus-matching-to-avoid-warnings.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 64ee3cf096ac590e7da2ceac1c390546bff5e240 Mon Sep 17 00:00:00 2001 -From: "Rob Herring (Arm)" -Date: Fri, 8 Nov 2024 13:35:48 -0600 -Subject: [PATCH] of/address: Rework bus matching to avoid warnings - -With warnings added for deprecated #address-cells/#size-cells handling, -the DT address handling code causes warnings when used on nodes with no -address. This happens frequently with calls to of_platform_populate() as -it is perfectly acceptable to have devices without a 'reg' property. The -desired behavior is to just silently return an error when retrieving an -address. - -The warnings can be avoided by checking for "#address-cells" presence -first and checking for an address property before fetching -"#address-cells" and "#size-cells". - -Reported-by: Marek Szyprowski -Reported-by: Steven Price -Tested-by: Marek Szyprowski -Link: https://lore.kernel.org/r/20241108193547.2647986-2-robh@kernel.org -Signed-off-by: Rob Herring (Arm) ---- - drivers/of/address.c | 14 +++++++++----- - 1 file changed, 9 insertions(+), 5 deletions(-) - ---- a/drivers/of/address.c -+++ b/drivers/of/address.c -@@ -331,7 +331,11 @@ static unsigned int of_bus_isa_get_flags - - static int of_bus_default_flags_match(struct device_node *np) - { -- return of_bus_n_addr_cells(np) == 3; -+ /* -+ * Check for presence first since of_bus_n_addr_cells() will warn when -+ * walking parent nodes. -+ */ -+ return of_property_present(np, "#address-cells") && (of_bus_n_addr_cells(np) == 3); - } - - /* -@@ -700,16 +704,16 @@ const __be32 *__of_get_address(struct de - if (strcmp(bus->name, "pci") && (bar_no >= 0)) - return NULL; - -- bus->count_cells(dev, &na, &ns); -- if (!OF_CHECK_ADDR_COUNT(na)) -- return NULL; -- - /* Get "reg" or "assigned-addresses" property */ - prop = of_get_property(dev, bus->addresses, &psize); - if (prop == NULL) - return NULL; - psize /= 4; - -+ bus->count_cells(dev, &na, &ns); -+ if (!OF_CHECK_ADDR_COUNT(na)) -+ return NULL; -+ - onesize = na + ns; - for (i = 0; psize >= onesize; psize -= onesize, prop += onesize, i++) { - u32 val = be32_to_cpu(prop[0]); diff --git a/target/linux/generic/backport-6.18/203-02-v6.13-of-address-Fix-WARN-when-attempting-translating-non-.patch b/target/linux/generic/backport-6.18/203-02-v6.13-of-address-Fix-WARN-when-attempting-translating-non-.patch deleted file mode 100644 index 2ad67cbde7..0000000000 --- a/target/linux/generic/backport-6.18/203-02-v6.13-of-address-Fix-WARN-when-attempting-translating-non-.patch +++ /dev/null @@ -1,85 +0,0 @@ -From 6e5773d52f4a2d9c80692245f295069260cff6fc Mon Sep 17 00:00:00 2001 -From: "Rob Herring (Arm)" -Date: Fri, 10 Jan 2025 15:50:29 -0600 -Subject: [PATCH] of/address: Fix WARN when attempting translating - non-translatable addresses - -The recently added WARN() for deprecated #address-cells and #size-cells -triggered a WARN when of_platform_populate() (which calls -of_address_to_resource()) is used on nodes with non-translatable -addresses. This case is expected to return an error. - -Rework the bus matching to allow no match and make the default require -an #address-cells property. That should be safe to do as any platform -missing #address-cells would have a warning already. - -Fixes: 045b14ca5c36 ("of: WARN on deprecated #address-cells/#size-cells handling") -Tested-by: Sean Anderson -Link: https://lore.kernel.org/r/20250110215030.3637845-2-robh@kernel.org -Signed-off-by: Rob Herring (Arm) ---- - drivers/of/address.c | 18 +++++++++++++++--- - 1 file changed, 15 insertions(+), 3 deletions(-) - ---- a/drivers/of/address.c -+++ b/drivers/of/address.c -@@ -338,6 +338,15 @@ static int of_bus_default_flags_match(st - return of_property_present(np, "#address-cells") && (of_bus_n_addr_cells(np) == 3); - } - -+static int of_bus_default_match(struct device_node *np) -+{ -+ /* -+ * Check for presence first since of_bus_n_addr_cells() will warn when -+ * walking parent nodes. -+ */ -+ return of_property_present(np, "#address-cells"); -+} -+ - /* - * Array of bus specific translators - */ -@@ -382,7 +391,7 @@ static struct of_bus of_busses[] = { - { - .name = "default", - .addresses = "reg", -- .match = NULL, -+ .match = of_bus_default_match, - .count_cells = of_bus_default_count_cells, - .map = of_bus_default_map, - .translate = of_bus_default_translate, -@@ -397,7 +406,6 @@ static struct of_bus *of_match_bus(struc - for (i = 0; i < ARRAY_SIZE(of_busses); i++) - if (!of_busses[i].match || of_busses[i].match(np)) - return &of_busses[i]; -- BUG(); - return NULL; - } - -@@ -519,6 +527,8 @@ static u64 __of_translate_address(struct - if (parent == NULL) - return OF_BAD_ADDR; - bus = of_match_bus(parent); -+ if (!bus) -+ return OF_BAD_ADDR; - - /* Count address cells & copy address locally */ - bus->count_cells(dev, &na, &ns); -@@ -562,6 +572,8 @@ static u64 __of_translate_address(struct - - /* Get new parent bus and counts */ - pbus = of_match_bus(parent); -+ if (!pbus) -+ return OF_BAD_ADDR; - pbus->count_cells(dev, &pna, &pns); - if (!OF_CHECK_COUNTS(pna, pns)) { - pr_err("Bad cell count for %pOF\n", dev); -@@ -701,7 +713,7 @@ const __be32 *__of_get_address(struct de - - /* match the parent's bus type */ - bus = of_match_bus(parent); -- if (strcmp(bus->name, "pci") && (bar_no >= 0)) -+ if (!bus || (strcmp(bus->name, "pci") && (bar_no >= 0))) - return NULL; - - /* Get "reg" or "assigned-addresses" property */ diff --git a/target/linux/generic/backport-6.18/205-v6.16-of-reserved_mem-Add-functions-to-parse-memory-region.patch b/target/linux/generic/backport-6.18/205-v6.16-of-reserved_mem-Add-functions-to-parse-memory-region.patch deleted file mode 100644 index b5bbb6e723..0000000000 --- a/target/linux/generic/backport-6.18/205-v6.16-of-reserved_mem-Add-functions-to-parse-memory-region.patch +++ /dev/null @@ -1,163 +0,0 @@ -From f4fcfdda2fd8834c62dcb9bfddcf1f89d190b70e Mon Sep 17 00:00:00 2001 -From: "Rob Herring (Arm)" -Date: Wed, 23 Apr 2025 14:42:13 -0500 -Subject: [PATCH] of: reserved_mem: Add functions to parse "memory-region" - -Drivers with "memory-region" properties currently have to do their own -parsing of "memory-region" properties. The result is all the drivers -have similar patterns of a call to parse "memory-region" and then get -the region's address and size. As this is a standard property, it should -have common functions for drivers to use. Add new functions to count the -number of regions and retrieve the region's address as a resource. - -Reviewed-by: Daniel Baluta -Acked-by: Arnaud Pouliquen -Link: https://lore.kernel.org/r/20250423-dt-memory-region-v2-v2-1-2fbd6ebd3c88@kernel.org -Signed-off-by: Rob Herring (Arm) ---- - drivers/of/of_reserved_mem.c | 80 +++++++++++++++++++++++++++++++++ - include/linux/of_reserved_mem.h | 26 +++++++++++ - 2 files changed, 106 insertions(+) - ---- a/drivers/of/of_reserved_mem.c -+++ b/drivers/of/of_reserved_mem.c -@@ -12,6 +12,7 @@ - #define pr_fmt(fmt) "OF: reserved mem: " fmt - - #include -+#include - #include - #include - #include -@@ -694,3 +695,82 @@ struct reserved_mem *of_reserved_mem_loo - return NULL; - } - EXPORT_SYMBOL_GPL(of_reserved_mem_lookup); -+ -+/** -+ * of_reserved_mem_region_to_resource() - Get a reserved memory region as a resource -+ * @np: node containing 'memory-region' property -+ * @idx: index of 'memory-region' property to lookup -+ * @res: Pointer to a struct resource to fill in with reserved region -+ * -+ * This function allows drivers to lookup a node's 'memory-region' property -+ * entries by index and return a struct resource for the entry. -+ * -+ * Returns 0 on success with @res filled in. Returns -ENODEV if 'memory-region' -+ * is missing or unavailable, -EINVAL for any other error. -+ */ -+int of_reserved_mem_region_to_resource(const struct device_node *np, -+ unsigned int idx, struct resource *res) -+{ -+ struct reserved_mem *rmem; -+ -+ if (!np) -+ return -EINVAL; -+ -+ struct device_node __free(device_node) *target = of_parse_phandle(np, "memory-region", idx); -+ if (!target || !of_device_is_available(target)) -+ return -ENODEV; -+ -+ rmem = of_reserved_mem_lookup(target); -+ if (!rmem) -+ return -EINVAL; -+ -+ resource_set_range(res, rmem->base, rmem->size); -+ res->name = rmem->name; -+ return 0; -+} -+EXPORT_SYMBOL_GPL(of_reserved_mem_region_to_resource); -+ -+/** -+ * of_reserved_mem_region_to_resource_byname() - Get a reserved memory region as a resource -+ * @np: node containing 'memory-region' property -+ * @name: name of 'memory-region' property entry to lookup -+ * @res: Pointer to a struct resource to fill in with reserved region -+ * -+ * This function allows drivers to lookup a node's 'memory-region' property -+ * entries by name and return a struct resource for the entry. -+ * -+ * Returns 0 on success with @res filled in, or a negative error-code on -+ * failure. -+ */ -+int of_reserved_mem_region_to_resource_byname(const struct device_node *np, -+ const char *name, -+ struct resource *res) -+{ -+ int idx; -+ -+ if (!name) -+ return -EINVAL; -+ -+ idx = of_property_match_string(np, "memory-region-names", name); -+ if (idx < 0) -+ return idx; -+ -+ return of_reserved_mem_region_to_resource(np, idx, res); -+} -+EXPORT_SYMBOL_GPL(of_reserved_mem_region_to_resource_byname); -+ -+/** -+ * of_reserved_mem_region_count() - Return the number of 'memory-region' entries -+ * @np: node containing 'memory-region' property -+ * -+ * This function allows drivers to retrieve the number of entries for a node's -+ * 'memory-region' property. -+ * -+ * Returns the number of entries on success, or negative error code on a -+ * malformed property. -+ */ -+int of_reserved_mem_region_count(const struct device_node *np) -+{ -+ return of_count_phandle_with_args(np, "memory-region", NULL); -+} -+EXPORT_SYMBOL_GPL(of_reserved_mem_region_count); ---- a/include/linux/of_reserved_mem.h -+++ b/include/linux/of_reserved_mem.h -@@ -7,6 +7,7 @@ - - struct of_phandle_args; - struct reserved_mem_ops; -+struct resource; - - struct reserved_mem { - const char *name; -@@ -39,6 +40,12 @@ int of_reserved_mem_device_init_by_name( - void of_reserved_mem_device_release(struct device *dev); - - struct reserved_mem *of_reserved_mem_lookup(struct device_node *np); -+int of_reserved_mem_region_to_resource(const struct device_node *np, -+ unsigned int idx, struct resource *res); -+int of_reserved_mem_region_to_resource_byname(const struct device_node *np, -+ const char *name, struct resource *res); -+int of_reserved_mem_region_count(const struct device_node *np); -+ - #else - - #define RESERVEDMEM_OF_DECLARE(name, compat, init) \ -@@ -63,6 +70,25 @@ static inline struct reserved_mem *of_re - { - return NULL; - } -+ -+static inline int of_reserved_mem_region_to_resource(const struct device_node *np, -+ unsigned int idx, -+ struct resource *res) -+{ -+ return -ENOSYS; -+} -+ -+static inline int of_reserved_mem_region_to_resource_byname(const struct device_node *np, -+ const char *name, -+ struct resource *res) -+{ -+ return -ENOSYS; -+} -+ -+static inline int of_reserved_mem_region_count(const struct device_node *np) -+{ -+ return 0; -+} - #endif - - /** diff --git a/target/linux/generic/backport-6.18/210-v6.13-fortify-Hide-run-time-copy-size-from-value-range-tracking.patch b/target/linux/generic/backport-6.18/210-v6.13-fortify-Hide-run-time-copy-size-from-value-range-tracking.patch deleted file mode 100644 index 8dca649866..0000000000 --- a/target/linux/generic/backport-6.18/210-v6.13-fortify-Hide-run-time-copy-size-from-value-range-tracking.patch +++ /dev/null @@ -1,155 +0,0 @@ -From 239d87327dcd361b0098038995f8908f3296864f Mon Sep 17 00:00:00 2001 -From: Kees Cook -Date: Thu, 12 Dec 2024 17:28:06 -0800 -Subject: fortify: Hide run-time copy size from value range tracking -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -GCC performs value range tracking for variables as a way to provide better -diagnostics. One place this is regularly seen is with warnings associated -with bounds-checking, e.g. -Wstringop-overflow, -Wstringop-overread, --Warray-bounds, etc. In order to keep the signal-to-noise ratio high, -warnings aren't emitted when a value range spans the entire value range -representable by a given variable. For example: - - unsigned int len; - char dst[8]; - ... - memcpy(dst, src, len); - -If len's value is unknown, it has the full "unsigned int" range of [0, -UINT_MAX], and GCC's compile-time bounds checks against memcpy() will -be ignored. However, when a code path has been able to narrow the range: - - if (len > 16) - return; - memcpy(dst, src, len); - -Then the range will be updated for the execution path. Above, len is -now [0, 16] when reading memcpy(), so depending on other optimizations, -we might see a -Wstringop-overflow warning like: - - error: '__builtin_memcpy' writing between 9 and 16 bytes into region of size 8 [-Werror=stringop-overflow] - -When building with CONFIG_FORTIFY_SOURCE, the fortified run-time bounds -checking can appear to narrow value ranges of lengths for memcpy(), -depending on how the compiler constructs the execution paths during -optimization passes, due to the checks against the field sizes. For -example: - - if (p_size_field != SIZE_MAX && - p_size != p_size_field && p_size_field < size) - -As intentionally designed, these checks only affect the kernel warnings -emitted at run-time and do not block the potentially overflowing memcpy(), -so GCC thinks it needs to produce a warning about the resulting value -range that might be reaching the memcpy(). - -We have seen this manifest a few times now, with the most recent being -with cpumasks: - -In function ‘bitmap_copy’, - inlined from ‘cpumask_copy’ at ./include/linux/cpumask.h:839:2, - inlined from ‘__padata_set_cpumasks’ at kernel/padata.c:730:2: -./include/linux/fortify-string.h:114:33: error: ‘__builtin_memcpy’ reading between 257 and 536870904 bytes from a region of size 256 [-Werror=stringop-overread] - 114 | #define __underlying_memcpy __builtin_memcpy - | ^ -./include/linux/fortify-string.h:633:9: note: in expansion of macro ‘__underlying_memcpy’ - 633 | __underlying_##op(p, q, __fortify_size); \ - | ^~~~~~~~~~~~~ -./include/linux/fortify-string.h:678:26: note: in expansion of macro ‘__fortify_memcpy_chk’ - 678 | #define memcpy(p, q, s) __fortify_memcpy_chk(p, q, s, \ - | ^~~~~~~~~~~~~~~~~~~~ -./include/linux/bitmap.h:259:17: note: in expansion of macro ‘memcpy’ - 259 | memcpy(dst, src, len); - | ^~~~~~ -kernel/padata.c: In function ‘__padata_set_cpumasks’: -kernel/padata.c:713:48: note: source object ‘pcpumask’ of size [0, 256] - 713 | cpumask_var_t pcpumask, - | ~~~~~~~~~~~~~~^~~~~~~~ - -This warning is _not_ emitted when CONFIG_FORTIFY_SOURCE is disabled, -and with the recent -fdiagnostics-details we can confirm the origin of -the warning is due to FORTIFY's bounds checking: - -../include/linux/bitmap.h:259:17: note: in expansion of macro 'memcpy' - 259 | memcpy(dst, src, len); - | ^~~~~~ - '__padata_set_cpumasks': events 1-2 -../include/linux/fortify-string.h:613:36: - 612 | if (p_size_field != SIZE_MAX && - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ - 613 | p_size != p_size_field && p_size_field < size) - | ~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~ - | | - | (1) when the condition is evaluated to false - | (2) when the condition is evaluated to true - '__padata_set_cpumasks': event 3 - 114 | #define __underlying_memcpy __builtin_memcpy - | ^ - | | - | (3) out of array bounds here - -Note that the cpumask warning started appearing since bitmap functions -were recently marked __always_inline in commit ed8cd2b3bd9f ("bitmap: -Switch from inline to __always_inline"), which allowed GCC to gain -visibility into the variables as they passed through the FORTIFY -implementation. - -In order to silence these false positives but keep otherwise deterministic -compile-time warnings intact, hide the length variable from GCC with -OPTIMIZE_HIDE_VAR() before calling the builtin memcpy. - -Additionally add a comment about why all the macro args have copies with -const storage. - -Reported-by: "Thomas Weißschuh" -Closes: https://lore.kernel.org/all/db7190c8-d17f-4a0d-bc2f-5903c79f36c2@t-8ch.de/ -Reported-by: Nilay Shroff -Closes: https://lore.kernel.org/all/20241112124127.1666300-1-nilay@linux.ibm.com/ -Tested-by: Nilay Shroff -Acked-by: Yury Norov -Acked-by: Greg Kroah-Hartman -Signed-off-by: Kees Cook ---- - include/linux/fortify-string.h | 14 +++++++++++++- - 1 file changed, 13 insertions(+), 1 deletion(-) - ---- a/include/linux/fortify-string.h -+++ b/include/linux/fortify-string.h -@@ -616,6 +616,12 @@ __FORTIFY_INLINE bool fortify_memcpy_chk - return false; - } - -+/* -+ * To work around what seems to be an optimizer bug, the macro arguments -+ * need to have const copies or the values end up changed by the time they -+ * reach fortify_warn_once(). See commit 6f7630b1b5bc ("fortify: Capture -+ * __bos() results in const temp vars") for more details. -+ */ - #define __fortify_memcpy_chk(p, q, size, p_size, q_size, \ - p_size_field, q_size_field, op) ({ \ - const size_t __fortify_size = (size_t)(size); \ -@@ -623,6 +629,8 @@ __FORTIFY_INLINE bool fortify_memcpy_chk - const size_t __q_size = (q_size); \ - const size_t __p_size_field = (p_size_field); \ - const size_t __q_size_field = (q_size_field); \ -+ /* Keep a mutable version of the size for the final copy. */ \ -+ size_t __copy_size = __fortify_size; \ - fortify_warn_once(fortify_memcpy_chk(__fortify_size, __p_size, \ - __q_size, __p_size_field, \ - __q_size_field, FORTIFY_FUNC_ ##op), \ -@@ -630,7 +638,11 @@ __FORTIFY_INLINE bool fortify_memcpy_chk - __fortify_size, \ - "field \"" #p "\" at " FILE_LINE, \ - __p_size_field); \ -- __underlying_##op(p, q, __fortify_size); \ -+ /* Hide only the run-time size from value range tracking to */ \ -+ /* silence compile-time false positive bounds warnings. */ \ -+ if (!__builtin_constant_p(__copy_size)) \ -+ OPTIMIZER_HIDE_VAR(__copy_size); \ -+ __underlying_##op(p, q, __copy_size); \ - }) - - /* diff --git a/target/linux/generic/backport-6.18/212-v6.17-of-reserved_mem-Add-missing-IORESOURCE_MEM-flag-on-r.patch b/target/linux/generic/backport-6.18/212-v6.17-of-reserved_mem-Add-missing-IORESOURCE_MEM-flag-on-r.patch deleted file mode 100644 index 1f2d52af9a..0000000000 --- a/target/linux/generic/backport-6.18/212-v6.17-of-reserved_mem-Add-missing-IORESOURCE_MEM-flag-on-r.patch +++ /dev/null @@ -1,32 +0,0 @@ -From aea70964b5a7ca491a3701f2dde6c9d05d51878d Mon Sep 17 00:00:00 2001 -From: "Rob Herring (Arm)" -Date: Wed, 20 Aug 2025 14:28:04 -0500 -Subject: of: reserved_mem: Add missing IORESOURCE_MEM flag on resources - -Commit f4fcfdda2fd8 ('of: reserved_mem: Add functions to parse -"memory-region"') failed to set IORESOURCE_MEM flag on the resources. -The result is functions such as devm_ioremap_resource_wc() will fail. -Add the missing flag. - -Fixes: f4fcfdda2fd8 ('of: reserved_mem: Add functions to parse "memory-region"') -Reported-by: Iuliana Prodan -Reported-by: Daniel Baluta -Tested-by: Iuliana Prodan -Reviewed-by: Iuliana Prodan -Reviewed-by: Saravana Kannan -Link: https://lore.kernel.org/r/20250820192805.565568-1-robh@kernel.org -Signed-off-by: Rob Herring (Arm) ---- - drivers/of/of_reserved_mem.c | 1 + - 1 file changed, 1 insertion(+) - ---- a/drivers/of/of_reserved_mem.c -+++ b/drivers/of/of_reserved_mem.c -@@ -725,6 +725,7 @@ int of_reserved_mem_region_to_resource(c - return -EINVAL; - - resource_set_range(res, rmem->base, rmem->size); -+ res->flags = IORESOURCE_MEM; - res->name = rmem->name; - return 0; - } diff --git a/target/linux/generic/backport-6.18/400-v6.14-mtd-spinand-add-support-for-FORESEE-F35SQA001G.patch b/target/linux/generic/backport-6.18/400-v6.14-mtd-spinand-add-support-for-FORESEE-F35SQA001G.patch deleted file mode 100644 index 84b3b2afee..0000000000 --- a/target/linux/generic/backport-6.18/400-v6.14-mtd-spinand-add-support-for-FORESEE-F35SQA001G.patch +++ /dev/null @@ -1,38 +0,0 @@ -From ae461cde5c559675fc4c0ba351c7c31ace705f56 Mon Sep 17 00:00:00 2001 -From: Bohdan Chubuk -Date: Sun, 10 Nov 2024 22:50:47 +0200 -Subject: [PATCH] mtd: spinand: add support for FORESEE F35SQA001G - -Add support for FORESEE F35SQA001G SPI NAND. - -Similar to F35SQA002G, but differs in capacity. -Datasheet: - - https://cdn.ozdisan.com/ETicaret_Dosya/704795_871495.pdf - -Tested on Xiaomi AX3000T flashed with OpenWRT. - -Signed-off-by: Bohdan Chubuk -Signed-off-by: Miquel Raynal ---- - drivers/mtd/nand/spi/foresee.c | 10 ++++++++++ - 1 file changed, 10 insertions(+) - ---- a/drivers/mtd/nand/spi/foresee.c -+++ b/drivers/mtd/nand/spi/foresee.c -@@ -81,6 +81,16 @@ static const struct spinand_info foresee - SPINAND_HAS_QE_BIT, - SPINAND_ECCINFO(&f35sqa002g_ooblayout, - f35sqa002g_ecc_get_status)), -+ SPINAND_INFO("F35SQA001G", -+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x71, 0x71), -+ NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1), -+ NAND_ECCREQ(1, 512), -+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants, -+ &write_cache_variants, -+ &update_cache_variants), -+ SPINAND_HAS_QE_BIT, -+ SPINAND_ECCINFO(&f35sqa002g_ooblayout, -+ f35sqa002g_ecc_get_status)), - }; - - static const struct spinand_manufacturer_ops foresee_spinand_manuf_ops = { diff --git a/target/linux/generic/backport-6.18/401-v6.17-mtd-spinand-add-support-for-FudanMicro-FM25S01A.patch b/target/linux/generic/backport-6.18/401-v6.17-mtd-spinand-add-support-for-FudanMicro-FM25S01A.patch deleted file mode 100644 index 0199fcbde9..0000000000 --- a/target/linux/generic/backport-6.18/401-v6.17-mtd-spinand-add-support-for-FudanMicro-FM25S01A.patch +++ /dev/null @@ -1,124 +0,0 @@ -From 5f284dc15ca8695d0394414045ac64616a3b0e69 Mon Sep 17 00:00:00 2001 -From: Tianling Shen -Date: Mon, 25 Aug 2025 01:00:13 +0800 -Subject: [PATCH] mtd: spinand: add support for FudanMicro FM25S01A - -Add support for FudanMicro FM25S01A SPI NAND. -Datasheet: http://eng.fmsh.com/nvm/FM25S01A_ds_eng.pdf - -Signed-off-by: Tianling Shen -Signed-off-by: Miquel Raynal -Link: https://lore.kernel.org/linux-mtd/20250824170013.3328777-1-cnsztl@gmail.com ---- - drivers/mtd/nand/spi/Makefile | 2 +- - drivers/mtd/nand/spi/core.c | 1 + - drivers/mtd/nand/spi/fmsh.c | 74 +++++++++++++++++++++++++++++++++++ - include/linux/mtd/spinand.h | 1 + - 4 files changed, 77 insertions(+), 1 deletion(-) - create mode 100644 drivers/mtd/nand/spi/fmsh.c - ---- a/drivers/mtd/nand/spi/Makefile -+++ b/drivers/mtd/nand/spi/Makefile -@@ -1,4 +1,4 @@ - # SPDX-License-Identifier: GPL-2.0 --spinand-objs := core.o alliancememory.o ato.o esmt.o foresee.o gigadevice.o macronix.o -+spinand-objs := core.o alliancememory.o ato.o esmt.o fmsh.o foresee.o gigadevice.o macronix.o - spinand-objs += micron.o paragon.o toshiba.o winbond.o xtx.o - obj-$(CONFIG_MTD_SPI_NAND) += spinand.o ---- a/drivers/mtd/nand/spi/core.c -+++ b/drivers/mtd/nand/spi/core.c -@@ -1123,6 +1123,7 @@ static const struct spinand_manufacturer - &alliancememory_spinand_manufacturer, - &ato_spinand_manufacturer, - &esmt_c8_spinand_manufacturer, -+ &fmsh_spinand_manufacturer, - &foresee_spinand_manufacturer, - &gigadevice_spinand_manufacturer, - ¯onix_spinand_manufacturer, ---- /dev/null -+++ b/drivers/mtd/nand/spi/fmsh.c -@@ -0,0 +1,74 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (c) 2020-2021 Rockchip Electronics Co., Ltd. -+ * -+ * Author: Dingqiang Lin -+ */ -+ -+#include -+#include -+#include -+ -+#define SPINAND_MFR_FMSH 0xA1 -+ -+static SPINAND_OP_VARIANTS(read_cache_variants, -+ SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 2, NULL, 0), -+ SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0), -+ SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 1, NULL, 0), -+ SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0), -+ SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0), -+ SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0)); -+ -+static SPINAND_OP_VARIANTS(write_cache_variants, -+ SPINAND_PROG_LOAD_X4(true, 0, NULL, 0), -+ SPINAND_PROG_LOAD(true, 0, NULL, 0)); -+ -+static SPINAND_OP_VARIANTS(update_cache_variants, -+ SPINAND_PROG_LOAD_X4(false, 0, NULL, 0), -+ SPINAND_PROG_LOAD(false, 0, NULL, 0)); -+ -+static int fm25s01a_ooblayout_ecc(struct mtd_info *mtd, int section, -+ struct mtd_oob_region *region) -+{ -+ return -ERANGE; -+} -+ -+static int fm25s01a_ooblayout_free(struct mtd_info *mtd, int section, -+ struct mtd_oob_region *region) -+{ -+ if (section) -+ return -ERANGE; -+ -+ region->offset = 2; -+ region->length = 62; -+ -+ return 0; -+} -+ -+static const struct mtd_ooblayout_ops fm25s01a_ooblayout = { -+ .ecc = fm25s01a_ooblayout_ecc, -+ .free = fm25s01a_ooblayout_free, -+}; -+ -+static const struct spinand_info fmsh_spinand_table[] = { -+ SPINAND_INFO("FM25S01A", -+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xE4), -+ NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1), -+ NAND_ECCREQ(1, 512), -+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants, -+ &write_cache_variants, -+ &update_cache_variants), -+ SPINAND_HAS_QE_BIT, -+ SPINAND_ECCINFO(&fm25s01a_ooblayout, NULL)), -+}; -+ -+static const struct spinand_manufacturer_ops fmsh_spinand_manuf_ops = { -+}; -+ -+const struct spinand_manufacturer fmsh_spinand_manufacturer = { -+ .id = SPINAND_MFR_FMSH, -+ .name = "Fudan Micro", -+ .chips = fmsh_spinand_table, -+ .nchips = ARRAY_SIZE(fmsh_spinand_table), -+ .ops = &fmsh_spinand_manuf_ops, -+}; ---- a/include/linux/mtd/spinand.h -+++ b/include/linux/mtd/spinand.h -@@ -263,6 +263,7 @@ struct spinand_manufacturer { - extern const struct spinand_manufacturer alliancememory_spinand_manufacturer; - extern const struct spinand_manufacturer ato_spinand_manufacturer; - extern const struct spinand_manufacturer esmt_c8_spinand_manufacturer; -+extern const struct spinand_manufacturer fmsh_spinand_manufacturer; - extern const struct spinand_manufacturer foresee_spinand_manufacturer; - extern const struct spinand_manufacturer gigadevice_spinand_manufacturer; - extern const struct spinand_manufacturer macronix_spinand_manufacturer; diff --git a/target/linux/generic/backport-6.18/402-v6.18-mtd-nand-move-chunk-to-core.patch b/target/linux/generic/backport-6.18/402-v6.18-mtd-nand-move-chunk-to-core.patch deleted file mode 100644 index 7933874d01..0000000000 --- a/target/linux/generic/backport-6.18/402-v6.18-mtd-nand-move-chunk-to-core.patch +++ /dev/null @@ -1,329 +0,0 @@ -From 6b88293aae7fb78872e5cc1ec36e2f750ae12e38 Mon Sep 17 00:00:00 2001 -From: Markus Stockhausen -Date: Wed, 10 Sep 2025 14:32:58 -0400 -Subject: mtd: nand: move nand_check_erased_ecc_chunk() to nand/core - -The check function for bitflips in erased blocks will be needed -by the Realtek ECC engine driver (which is currently under -development). Right now it is located in raw/nand_base.c. -While this is sufficient for the current usecases, there is -no real dependency for an ECC engine on the raw nand library. - -Move the function over to a more generic place in core library. - -Suggested-by: Miquel Raynal -Signed-off-by: Markus Stockhausen -Signed-off-by: Miquel Raynal ---- - drivers/mtd/nand/core.c | 131 +++++++++++++++++++++++++++++++++++++++ - drivers/mtd/nand/raw/nand_base.c | 131 --------------------------------------- - include/linux/mtd/nand.h | 5 ++ - include/linux/mtd/rawnand.h | 5 -- - 4 files changed, 136 insertions(+), 136 deletions(-) - ---- a/drivers/mtd/nand/core.c -+++ b/drivers/mtd/nand/core.c -@@ -13,6 +13,137 @@ - #include - - /** -+ * nand_check_erased_buf - check if a buffer contains (almost) only 0xff data -+ * @buf: buffer to test -+ * @len: buffer length -+ * @bitflips_threshold: maximum number of bitflips -+ * -+ * Check if a buffer contains only 0xff, which means the underlying region -+ * has been erased and is ready to be programmed. -+ * The bitflips_threshold specify the maximum number of bitflips before -+ * considering the region is not erased. -+ * Note: The logic of this function has been extracted from the memweight -+ * implementation, except that nand_check_erased_buf function exit before -+ * testing the whole buffer if the number of bitflips exceed the -+ * bitflips_threshold value. -+ * -+ * Returns a positive number of bitflips less than or equal to -+ * bitflips_threshold, or -ERROR_CODE for bitflips in excess of the -+ * threshold. -+ */ -+static int nand_check_erased_buf(void *buf, int len, int bitflips_threshold) -+{ -+ const unsigned char *bitmap = buf; -+ int bitflips = 0; -+ int weight; -+ -+ for (; len && ((uintptr_t)bitmap) % sizeof(long); -+ len--, bitmap++) { -+ weight = hweight8(*bitmap); -+ bitflips += BITS_PER_BYTE - weight; -+ if (unlikely(bitflips > bitflips_threshold)) -+ return -EBADMSG; -+ } -+ -+ for (; len >= sizeof(long); -+ len -= sizeof(long), bitmap += sizeof(long)) { -+ unsigned long d = *((unsigned long *)bitmap); -+ if (d == ~0UL) -+ continue; -+ weight = hweight_long(d); -+ bitflips += BITS_PER_LONG - weight; -+ if (unlikely(bitflips > bitflips_threshold)) -+ return -EBADMSG; -+ } -+ -+ for (; len > 0; len--, bitmap++) { -+ weight = hweight8(*bitmap); -+ bitflips += BITS_PER_BYTE - weight; -+ if (unlikely(bitflips > bitflips_threshold)) -+ return -EBADMSG; -+ } -+ -+ return bitflips; -+} -+ -+/** -+ * nand_check_erased_ecc_chunk - check if an ECC chunk contains (almost) only -+ * 0xff data -+ * @data: data buffer to test -+ * @datalen: data length -+ * @ecc: ECC buffer -+ * @ecclen: ECC length -+ * @extraoob: extra OOB buffer -+ * @extraooblen: extra OOB length -+ * @bitflips_threshold: maximum number of bitflips -+ * -+ * Check if a data buffer and its associated ECC and OOB data contains only -+ * 0xff pattern, which means the underlying region has been erased and is -+ * ready to be programmed. -+ * The bitflips_threshold specify the maximum number of bitflips before -+ * considering the region as not erased. -+ * -+ * Note: -+ * 1/ ECC algorithms are working on pre-defined block sizes which are usually -+ * different from the NAND page size. When fixing bitflips, ECC engines will -+ * report the number of errors per chunk, and the NAND core infrastructure -+ * expect you to return the maximum number of bitflips for the whole page. -+ * This is why you should always use this function on a single chunk and -+ * not on the whole page. After checking each chunk you should update your -+ * max_bitflips value accordingly. -+ * 2/ When checking for bitflips in erased pages you should not only check -+ * the payload data but also their associated ECC data, because a user might -+ * have programmed almost all bits to 1 but a few. In this case, we -+ * shouldn't consider the chunk as erased, and checking ECC bytes prevent -+ * this case. -+ * 3/ The extraoob argument is optional, and should be used if some of your OOB -+ * data are protected by the ECC engine. -+ * It could also be used if you support subpages and want to attach some -+ * extra OOB data to an ECC chunk. -+ * -+ * Returns a positive number of bitflips less than or equal to -+ * bitflips_threshold, or -ERROR_CODE for bitflips in excess of the -+ * threshold. In case of success, the passed buffers are filled with 0xff. -+ */ -+int nand_check_erased_ecc_chunk(void *data, int datalen, -+ void *ecc, int ecclen, -+ void *extraoob, int extraooblen, -+ int bitflips_threshold) -+{ -+ int data_bitflips = 0, ecc_bitflips = 0, extraoob_bitflips = 0; -+ -+ data_bitflips = nand_check_erased_buf(data, datalen, -+ bitflips_threshold); -+ if (data_bitflips < 0) -+ return data_bitflips; -+ -+ bitflips_threshold -= data_bitflips; -+ -+ ecc_bitflips = nand_check_erased_buf(ecc, ecclen, bitflips_threshold); -+ if (ecc_bitflips < 0) -+ return ecc_bitflips; -+ -+ bitflips_threshold -= ecc_bitflips; -+ -+ extraoob_bitflips = nand_check_erased_buf(extraoob, extraooblen, -+ bitflips_threshold); -+ if (extraoob_bitflips < 0) -+ return extraoob_bitflips; -+ -+ if (data_bitflips) -+ memset(data, 0xff, datalen); -+ -+ if (ecc_bitflips) -+ memset(ecc, 0xff, ecclen); -+ -+ if (extraoob_bitflips) -+ memset(extraoob, 0xff, extraooblen); -+ -+ return data_bitflips + ecc_bitflips + extraoob_bitflips; -+} -+EXPORT_SYMBOL(nand_check_erased_ecc_chunk); -+ -+/** - * nanddev_isbad() - Check if a block is bad - * @nand: NAND device - * @pos: position pointing to the block we want to check ---- a/drivers/mtd/nand/raw/nand_base.c -+++ b/drivers/mtd/nand/raw/nand_base.c -@@ -2784,137 +2784,6 @@ int nand_set_features(struct nand_chip * - } - - /** -- * nand_check_erased_buf - check if a buffer contains (almost) only 0xff data -- * @buf: buffer to test -- * @len: buffer length -- * @bitflips_threshold: maximum number of bitflips -- * -- * Check if a buffer contains only 0xff, which means the underlying region -- * has been erased and is ready to be programmed. -- * The bitflips_threshold specify the maximum number of bitflips before -- * considering the region is not erased. -- * Note: The logic of this function has been extracted from the memweight -- * implementation, except that nand_check_erased_buf function exit before -- * testing the whole buffer if the number of bitflips exceed the -- * bitflips_threshold value. -- * -- * Returns a positive number of bitflips less than or equal to -- * bitflips_threshold, or -ERROR_CODE for bitflips in excess of the -- * threshold. -- */ --static int nand_check_erased_buf(void *buf, int len, int bitflips_threshold) --{ -- const unsigned char *bitmap = buf; -- int bitflips = 0; -- int weight; -- -- for (; len && ((uintptr_t)bitmap) % sizeof(long); -- len--, bitmap++) { -- weight = hweight8(*bitmap); -- bitflips += BITS_PER_BYTE - weight; -- if (unlikely(bitflips > bitflips_threshold)) -- return -EBADMSG; -- } -- -- for (; len >= sizeof(long); -- len -= sizeof(long), bitmap += sizeof(long)) { -- unsigned long d = *((unsigned long *)bitmap); -- if (d == ~0UL) -- continue; -- weight = hweight_long(d); -- bitflips += BITS_PER_LONG - weight; -- if (unlikely(bitflips > bitflips_threshold)) -- return -EBADMSG; -- } -- -- for (; len > 0; len--, bitmap++) { -- weight = hweight8(*bitmap); -- bitflips += BITS_PER_BYTE - weight; -- if (unlikely(bitflips > bitflips_threshold)) -- return -EBADMSG; -- } -- -- return bitflips; --} -- --/** -- * nand_check_erased_ecc_chunk - check if an ECC chunk contains (almost) only -- * 0xff data -- * @data: data buffer to test -- * @datalen: data length -- * @ecc: ECC buffer -- * @ecclen: ECC length -- * @extraoob: extra OOB buffer -- * @extraooblen: extra OOB length -- * @bitflips_threshold: maximum number of bitflips -- * -- * Check if a data buffer and its associated ECC and OOB data contains only -- * 0xff pattern, which means the underlying region has been erased and is -- * ready to be programmed. -- * The bitflips_threshold specify the maximum number of bitflips before -- * considering the region as not erased. -- * -- * Note: -- * 1/ ECC algorithms are working on pre-defined block sizes which are usually -- * different from the NAND page size. When fixing bitflips, ECC engines will -- * report the number of errors per chunk, and the NAND core infrastructure -- * expect you to return the maximum number of bitflips for the whole page. -- * This is why you should always use this function on a single chunk and -- * not on the whole page. After checking each chunk you should update your -- * max_bitflips value accordingly. -- * 2/ When checking for bitflips in erased pages you should not only check -- * the payload data but also their associated ECC data, because a user might -- * have programmed almost all bits to 1 but a few. In this case, we -- * shouldn't consider the chunk as erased, and checking ECC bytes prevent -- * this case. -- * 3/ The extraoob argument is optional, and should be used if some of your OOB -- * data are protected by the ECC engine. -- * It could also be used if you support subpages and want to attach some -- * extra OOB data to an ECC chunk. -- * -- * Returns a positive number of bitflips less than or equal to -- * bitflips_threshold, or -ERROR_CODE for bitflips in excess of the -- * threshold. In case of success, the passed buffers are filled with 0xff. -- */ --int nand_check_erased_ecc_chunk(void *data, int datalen, -- void *ecc, int ecclen, -- void *extraoob, int extraooblen, -- int bitflips_threshold) --{ -- int data_bitflips = 0, ecc_bitflips = 0, extraoob_bitflips = 0; -- -- data_bitflips = nand_check_erased_buf(data, datalen, -- bitflips_threshold); -- if (data_bitflips < 0) -- return data_bitflips; -- -- bitflips_threshold -= data_bitflips; -- -- ecc_bitflips = nand_check_erased_buf(ecc, ecclen, bitflips_threshold); -- if (ecc_bitflips < 0) -- return ecc_bitflips; -- -- bitflips_threshold -= ecc_bitflips; -- -- extraoob_bitflips = nand_check_erased_buf(extraoob, extraooblen, -- bitflips_threshold); -- if (extraoob_bitflips < 0) -- return extraoob_bitflips; -- -- if (data_bitflips) -- memset(data, 0xff, datalen); -- -- if (ecc_bitflips) -- memset(ecc, 0xff, ecclen); -- -- if (extraoob_bitflips) -- memset(extraoob, 0xff, extraooblen); -- -- return data_bitflips + ecc_bitflips + extraoob_bitflips; --} --EXPORT_SYMBOL(nand_check_erased_ecc_chunk); -- --/** - * nand_read_page_raw_notsupp - dummy read raw page function - * @chip: nand chip info structure - * @buf: buffer to store read data ---- a/include/linux/mtd/nand.h -+++ b/include/linux/mtd/nand.h -@@ -1136,4 +1136,9 @@ static inline bool nanddev_bbt_is_initia - int nanddev_mtd_erase(struct mtd_info *mtd, struct erase_info *einfo); - int nanddev_mtd_max_bad_blocks(struct mtd_info *mtd, loff_t offs, size_t len); - -+int nand_check_erased_ecc_chunk(void *data, int datalen, -+ void *ecc, int ecclen, -+ void *extraoob, int extraooblen, -+ int threshold); -+ - #endif /* __LINUX_MTD_NAND_H */ ---- a/include/linux/mtd/rawnand.h -+++ b/include/linux/mtd/rawnand.h -@@ -1519,11 +1519,6 @@ int rawnand_sw_bch_correct(struct nand_c - unsigned char *read_ecc, unsigned char *calc_ecc); - void rawnand_sw_bch_cleanup(struct nand_chip *chip); - --int nand_check_erased_ecc_chunk(void *data, int datalen, -- void *ecc, int ecclen, -- void *extraoob, int extraooblen, -- int threshold); -- - int nand_ecc_choose_conf(struct nand_chip *chip, - const struct nand_ecc_caps *caps, int oobavail); - diff --git a/target/linux/generic/backport-6.18/404-v6.19-mtd-spinand-fmsh-remove-QE-bit-for-FM25S01A-flash.patch b/target/linux/generic/backport-6.18/404-v6.19-mtd-spinand-fmsh-remove-QE-bit-for-FM25S01A-flash.patch deleted file mode 100644 index 7f9ec6aca4..0000000000 --- a/target/linux/generic/backport-6.18/404-v6.19-mtd-spinand-fmsh-remove-QE-bit-for-FM25S01A-flash.patch +++ /dev/null @@ -1,28 +0,0 @@ -From a1d3bc606bf5c3b3ea811cc2019df6285d75b00f Mon Sep 17 00:00:00 2001 -From: Mikhail Kshevetskiy -Date: Mon, 3 Nov 2025 04:01:48 +0300 -Subject: [PATCH] mtd: spinand: fmsh: remove QE bit for FM25S01A flash - -According to datasheet (http://eng.fmsh.com/nvm/FM25S01A_ds_eng.pdf) -there is no QE (Quad Enable) bit for FM25S01A flash, so remove it. - -Fixes: 5f284dc15ca86 ("mtd: spinand: add support for FudanMicro FM25S01A") -Signed-off-by: Mikhail Kshevetskiy -Tested-by: Tianling Shen -Signed-off-by: Miquel Raynal -Link: Link: https://lore.kernel.org/linux-mtd/176216634975.908445.2776312239779833518.b4-ty@bootlin.com ---- - drivers/mtd/nand/spi/fmsh.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/mtd/nand/spi/fmsh.c -+++ b/drivers/mtd/nand/spi/fmsh.c -@@ -58,7 +58,7 @@ static const struct spinand_info fmsh_sp - SPINAND_INFO_OP_VARIANTS(&read_cache_variants, - &write_cache_variants, - &update_cache_variants), -- SPINAND_HAS_QE_BIT, -+ 0, - SPINAND_ECCINFO(&fm25s01a_ooblayout, NULL)), - }; - diff --git a/target/linux/generic/backport-6.18/410-01-v6.14-mtd-rawnand-qcom-cleanup-qcom_nandc-driver.patch b/target/linux/generic/backport-6.18/410-01-v6.14-mtd-rawnand-qcom-cleanup-qcom_nandc-driver.patch deleted file mode 100644 index 1d1288e832..0000000000 --- a/target/linux/generic/backport-6.18/410-01-v6.14-mtd-rawnand-qcom-cleanup-qcom_nandc-driver.patch +++ /dev/null @@ -1,1026 +0,0 @@ -From 8c52932da5e6756fa66f52f0720da283fba13aa6 Mon Sep 17 00:00:00 2001 -From: Md Sadre Alam -Date: Wed, 20 Nov 2024 14:45:00 +0530 -Subject: [PATCH 1/4] mtd: rawnand: qcom: cleanup qcom_nandc driver - -Perform a global cleanup of the Qualcomm NAND -controller driver with the following improvements: - -- Remove register value indirection API - -- Remove set_reg() API - -- Convert read_loc_first & read_loc_last macro to functions - -- Rename multiple variables - -Signed-off-by: Md Sadre Alam -Signed-off-by: Miquel Raynal ---- - drivers/mtd/nand/raw/qcom_nandc.c | 516 ++++++++++++++---------------- - 1 file changed, 234 insertions(+), 282 deletions(-) - ---- a/drivers/mtd/nand/raw/qcom_nandc.c -+++ b/drivers/mtd/nand/raw/qcom_nandc.c -@@ -189,17 +189,6 @@ - #define ECC_BCH_4BIT BIT(2) - #define ECC_BCH_8BIT BIT(3) - --#define nandc_set_read_loc_first(chip, reg, cw_offset, read_size, is_last_read_loc) \ --nandc_set_reg(chip, reg, \ -- ((cw_offset) << READ_LOCATION_OFFSET) | \ -- ((read_size) << READ_LOCATION_SIZE) | \ -- ((is_last_read_loc) << READ_LOCATION_LAST)) -- --#define nandc_set_read_loc_last(chip, reg, cw_offset, read_size, is_last_read_loc) \ --nandc_set_reg(chip, reg, \ -- ((cw_offset) << READ_LOCATION_OFFSET) | \ -- ((read_size) << READ_LOCATION_SIZE) | \ -- ((is_last_read_loc) << READ_LOCATION_LAST)) - /* - * Returns the actual register address for all NAND_DEV_ registers - * (i.e. NAND_DEV_CMD0, NAND_DEV_CMD1, NAND_DEV_CMD2 and NAND_DEV_CMD_VLD) -@@ -257,8 +246,6 @@ nandc_set_reg(chip, reg, \ - * @tx_sgl_start - start index in data sgl for tx. - * @rx_sgl_pos - current index in data sgl for rx. - * @rx_sgl_start - start index in data sgl for rx. -- * @wait_second_completion - wait for second DMA desc completion before making -- * the NAND transfer completion. - */ - struct bam_transaction { - struct bam_cmd_element *bam_ce; -@@ -275,7 +262,6 @@ struct bam_transaction { - u32 tx_sgl_start; - u32 rx_sgl_pos; - u32 rx_sgl_start; -- bool wait_second_completion; - }; - - /* -@@ -471,9 +457,9 @@ struct qcom_op { - unsigned int data_instr_idx; - unsigned int rdy_timeout_ms; - unsigned int rdy_delay_ns; -- u32 addr1_reg; -- u32 addr2_reg; -- u32 cmd_reg; -+ __le32 addr1_reg; -+ __le32 addr2_reg; -+ __le32 cmd_reg; - u8 flag; - }; - -@@ -549,17 +535,17 @@ struct qcom_nand_host { - * among different NAND controllers. - * @ecc_modes - ecc mode for NAND - * @dev_cmd_reg_start - NAND_DEV_CMD_* registers starting offset -- * @is_bam - whether NAND controller is using BAM -- * @is_qpic - whether NAND CTRL is part of qpic IP -- * @qpic_v2 - flag to indicate QPIC IP version 2 -+ * @supports_bam - whether NAND controller is using Bus Access Manager (BAM) -+ * @nandc_part_of_qpic - whether NAND controller is part of qpic IP -+ * @qpic_version2 - flag to indicate QPIC IP version 2 - * @use_codeword_fixup - whether NAND has different layout for boot partitions - */ - struct qcom_nandc_props { - u32 ecc_modes; - u32 dev_cmd_reg_start; -- bool is_bam; -- bool is_qpic; -- bool qpic_v2; -+ bool supports_bam; -+ bool nandc_part_of_qpic; -+ bool qpic_version2; - bool use_codeword_fixup; - }; - -@@ -613,19 +599,11 @@ static void clear_bam_transaction(struct - { - struct bam_transaction *bam_txn = nandc->bam_txn; - -- if (!nandc->props->is_bam) -+ if (!nandc->props->supports_bam) - return; - -- bam_txn->bam_ce_pos = 0; -- bam_txn->bam_ce_start = 0; -- bam_txn->cmd_sgl_pos = 0; -- bam_txn->cmd_sgl_start = 0; -- bam_txn->tx_sgl_pos = 0; -- bam_txn->tx_sgl_start = 0; -- bam_txn->rx_sgl_pos = 0; -- bam_txn->rx_sgl_start = 0; -+ memset(&bam_txn->bam_ce_pos, 0, sizeof(u32) * 8); - bam_txn->last_data_desc = NULL; -- bam_txn->wait_second_completion = false; - - sg_init_table(bam_txn->cmd_sgl, nandc->max_cwperpage * - QPIC_PER_CW_CMD_SGL); -@@ -640,46 +618,35 @@ static void qpic_bam_dma_done(void *data - { - struct bam_transaction *bam_txn = data; - -- /* -- * In case of data transfer with NAND, 2 callbacks will be generated. -- * One for command channel and another one for data channel. -- * If current transaction has data descriptors -- * (i.e. wait_second_completion is true), then set this to false -- * and wait for second DMA descriptor completion. -- */ -- if (bam_txn->wait_second_completion) -- bam_txn->wait_second_completion = false; -- else -- complete(&bam_txn->txn_done); -+ complete(&bam_txn->txn_done); - } - --static inline struct qcom_nand_host *to_qcom_nand_host(struct nand_chip *chip) -+static struct qcom_nand_host *to_qcom_nand_host(struct nand_chip *chip) - { - return container_of(chip, struct qcom_nand_host, chip); - } - --static inline struct qcom_nand_controller * -+static struct qcom_nand_controller * - get_qcom_nand_controller(struct nand_chip *chip) - { - return container_of(chip->controller, struct qcom_nand_controller, - controller); - } - --static inline u32 nandc_read(struct qcom_nand_controller *nandc, int offset) -+static u32 nandc_read(struct qcom_nand_controller *nandc, int offset) - { - return ioread32(nandc->base + offset); - } - --static inline void nandc_write(struct qcom_nand_controller *nandc, int offset, -- u32 val) -+static void nandc_write(struct qcom_nand_controller *nandc, int offset, -+ u32 val) - { - iowrite32(val, nandc->base + offset); - } - --static inline void nandc_read_buffer_sync(struct qcom_nand_controller *nandc, -- bool is_cpu) -+static void nandc_dev_to_mem(struct qcom_nand_controller *nandc, bool is_cpu) - { -- if (!nandc->props->is_bam) -+ if (!nandc->props->supports_bam) - return; - - if (is_cpu) -@@ -694,93 +661,90 @@ static inline void nandc_read_buffer_syn - DMA_FROM_DEVICE); - } - --static __le32 *offset_to_nandc_reg(struct nandc_regs *regs, int offset) --{ -- switch (offset) { -- case NAND_FLASH_CMD: -- return ®s->cmd; -- case NAND_ADDR0: -- return ®s->addr0; -- case NAND_ADDR1: -- return ®s->addr1; -- case NAND_FLASH_CHIP_SELECT: -- return ®s->chip_sel; -- case NAND_EXEC_CMD: -- return ®s->exec; -- case NAND_FLASH_STATUS: -- return ®s->clrflashstatus; -- case NAND_DEV0_CFG0: -- return ®s->cfg0; -- case NAND_DEV0_CFG1: -- return ®s->cfg1; -- case NAND_DEV0_ECC_CFG: -- return ®s->ecc_bch_cfg; -- case NAND_READ_STATUS: -- return ®s->clrreadstatus; -- case NAND_DEV_CMD1: -- return ®s->cmd1; -- case NAND_DEV_CMD1_RESTORE: -- return ®s->orig_cmd1; -- case NAND_DEV_CMD_VLD: -- return ®s->vld; -- case NAND_DEV_CMD_VLD_RESTORE: -- return ®s->orig_vld; -- case NAND_EBI2_ECC_BUF_CFG: -- return ®s->ecc_buf_cfg; -- case NAND_READ_LOCATION_0: -- return ®s->read_location0; -- case NAND_READ_LOCATION_1: -- return ®s->read_location1; -- case NAND_READ_LOCATION_2: -- return ®s->read_location2; -- case NAND_READ_LOCATION_3: -- return ®s->read_location3; -- case NAND_READ_LOCATION_LAST_CW_0: -- return ®s->read_location_last0; -- case NAND_READ_LOCATION_LAST_CW_1: -- return ®s->read_location_last1; -- case NAND_READ_LOCATION_LAST_CW_2: -- return ®s->read_location_last2; -- case NAND_READ_LOCATION_LAST_CW_3: -- return ®s->read_location_last3; -- default: -- return NULL; -- } --} -- --static void nandc_set_reg(struct nand_chip *chip, int offset, -- u32 val) --{ -- struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); -- struct nandc_regs *regs = nandc->regs; -- __le32 *reg; -- -- reg = offset_to_nandc_reg(regs, offset); -- -- if (reg) -- *reg = cpu_to_le32(val); --} -- --/* Helper to check the code word, whether it is last cw or not */ -+/* Helper to check whether this is the last CW or not */ - static bool qcom_nandc_is_last_cw(struct nand_ecc_ctrl *ecc, int cw) - { - return cw == (ecc->steps - 1); - } - -+/** -+ * nandc_set_read_loc_first() - to set read location first register -+ * @chip: NAND Private Flash Chip Data -+ * @reg_base: location register base -+ * @cw_offset: code word offset -+ * @read_size: code word read length -+ * @is_last_read_loc: is this the last read location -+ * -+ * This function will set location register value -+ */ -+static void nandc_set_read_loc_first(struct nand_chip *chip, -+ int reg_base, u32 cw_offset, -+ u32 read_size, u32 is_last_read_loc) -+{ -+ struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); -+ __le32 locreg_val; -+ u32 val = (((cw_offset) << READ_LOCATION_OFFSET) | -+ ((read_size) << READ_LOCATION_SIZE) | -+ ((is_last_read_loc) << READ_LOCATION_LAST)); -+ -+ locreg_val = cpu_to_le32(val); -+ -+ if (reg_base == NAND_READ_LOCATION_0) -+ nandc->regs->read_location0 = locreg_val; -+ else if (reg_base == NAND_READ_LOCATION_1) -+ nandc->regs->read_location1 = locreg_val; -+ else if (reg_base == NAND_READ_LOCATION_2) -+ nandc->regs->read_location2 = locreg_val; -+ else if (reg_base == NAND_READ_LOCATION_3) -+ nandc->regs->read_location3 = locreg_val; -+} -+ -+/** -+ * nandc_set_read_loc_last - to set read location last register -+ * @chip: NAND Private Flash Chip Data -+ * @reg_base: location register base -+ * @cw_offset: code word offset -+ * @read_size: code word read length -+ * @is_last_read_loc: is this the last read location -+ * -+ * This function will set location last register value -+ */ -+static void nandc_set_read_loc_last(struct nand_chip *chip, -+ int reg_base, u32 cw_offset, -+ u32 read_size, u32 is_last_read_loc) -+{ -+ struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); -+ __le32 locreg_val; -+ u32 val = (((cw_offset) << READ_LOCATION_OFFSET) | -+ ((read_size) << READ_LOCATION_SIZE) | -+ ((is_last_read_loc) << READ_LOCATION_LAST)); -+ -+ locreg_val = cpu_to_le32(val); -+ -+ if (reg_base == NAND_READ_LOCATION_LAST_CW_0) -+ nandc->regs->read_location_last0 = locreg_val; -+ else if (reg_base == NAND_READ_LOCATION_LAST_CW_1) -+ nandc->regs->read_location_last1 = locreg_val; -+ else if (reg_base == NAND_READ_LOCATION_LAST_CW_2) -+ nandc->regs->read_location_last2 = locreg_val; -+ else if (reg_base == NAND_READ_LOCATION_LAST_CW_3) -+ nandc->regs->read_location_last3 = locreg_val; -+} -+ - /* helper to configure location register values */ - static void nandc_set_read_loc(struct nand_chip *chip, int cw, int reg, -- int cw_offset, int read_size, int is_last_read_loc) -+ u32 cw_offset, u32 read_size, u32 is_last_read_loc) - { - struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); - struct nand_ecc_ctrl *ecc = &chip->ecc; - int reg_base = NAND_READ_LOCATION_0; - -- if (nandc->props->qpic_v2 && qcom_nandc_is_last_cw(ecc, cw)) -+ if (nandc->props->qpic_version2 && qcom_nandc_is_last_cw(ecc, cw)) - reg_base = NAND_READ_LOCATION_LAST_CW_0; - - reg_base += reg * 4; - -- if (nandc->props->qpic_v2 && qcom_nandc_is_last_cw(ecc, cw)) -+ if (nandc->props->qpic_version2 && qcom_nandc_is_last_cw(ecc, cw)) - return nandc_set_read_loc_last(chip, reg_base, cw_offset, - read_size, is_last_read_loc); - else -@@ -792,12 +756,13 @@ static void nandc_set_read_loc(struct na - static void set_address(struct qcom_nand_host *host, u16 column, int page) - { - struct nand_chip *chip = &host->chip; -+ struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); - - if (chip->options & NAND_BUSWIDTH_16) - column >>= 1; - -- nandc_set_reg(chip, NAND_ADDR0, page << 16 | column); -- nandc_set_reg(chip, NAND_ADDR1, page >> 16 & 0xff); -+ nandc->regs->addr0 = cpu_to_le32(page << 16 | column); -+ nandc->regs->addr1 = cpu_to_le32(page >> 16 & 0xff); - } - - /* -@@ -811,41 +776,43 @@ static void set_address(struct qcom_nand - static void update_rw_regs(struct qcom_nand_host *host, int num_cw, bool read, int cw) - { - struct nand_chip *chip = &host->chip; -- u32 cmd, cfg0, cfg1, ecc_bch_cfg; -+ __le32 cmd, cfg0, cfg1, ecc_bch_cfg; - struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); - - if (read) { - if (host->use_ecc) -- cmd = OP_PAGE_READ_WITH_ECC | PAGE_ACC | LAST_PAGE; -+ cmd = cpu_to_le32(OP_PAGE_READ_WITH_ECC | PAGE_ACC | LAST_PAGE); - else -- cmd = OP_PAGE_READ | PAGE_ACC | LAST_PAGE; -+ cmd = cpu_to_le32(OP_PAGE_READ | PAGE_ACC | LAST_PAGE); - } else { -- cmd = OP_PROGRAM_PAGE | PAGE_ACC | LAST_PAGE; -+ cmd = cpu_to_le32(OP_PROGRAM_PAGE | PAGE_ACC | LAST_PAGE); - } - - if (host->use_ecc) { -- cfg0 = (host->cfg0 & ~(7U << CW_PER_PAGE)) | -- (num_cw - 1) << CW_PER_PAGE; -+ cfg0 = cpu_to_le32((host->cfg0 & ~(7U << CW_PER_PAGE)) | -+ (num_cw - 1) << CW_PER_PAGE); - -- cfg1 = host->cfg1; -- ecc_bch_cfg = host->ecc_bch_cfg; -+ cfg1 = cpu_to_le32(host->cfg1); -+ ecc_bch_cfg = cpu_to_le32(host->ecc_bch_cfg); - } else { -- cfg0 = (host->cfg0_raw & ~(7U << CW_PER_PAGE)) | -- (num_cw - 1) << CW_PER_PAGE; -+ cfg0 = cpu_to_le32((host->cfg0_raw & ~(7U << CW_PER_PAGE)) | -+ (num_cw - 1) << CW_PER_PAGE); - -- cfg1 = host->cfg1_raw; -- ecc_bch_cfg = 1 << ECC_CFG_ECC_DISABLE; -+ cfg1 = cpu_to_le32(host->cfg1_raw); -+ ecc_bch_cfg = cpu_to_le32(1 << ECC_CFG_ECC_DISABLE); - } - -- nandc_set_reg(chip, NAND_FLASH_CMD, cmd); -- nandc_set_reg(chip, NAND_DEV0_CFG0, cfg0); -- nandc_set_reg(chip, NAND_DEV0_CFG1, cfg1); -- nandc_set_reg(chip, NAND_DEV0_ECC_CFG, ecc_bch_cfg); -- if (!nandc->props->qpic_v2) -- nandc_set_reg(chip, NAND_EBI2_ECC_BUF_CFG, host->ecc_buf_cfg); -- nandc_set_reg(chip, NAND_FLASH_STATUS, host->clrflashstatus); -- nandc_set_reg(chip, NAND_READ_STATUS, host->clrreadstatus); -- nandc_set_reg(chip, NAND_EXEC_CMD, 1); -+ nandc->regs->cmd = cmd; -+ nandc->regs->cfg0 = cfg0; -+ nandc->regs->cfg1 = cfg1; -+ nandc->regs->ecc_bch_cfg = ecc_bch_cfg; -+ -+ if (!nandc->props->qpic_version2) -+ nandc->regs->ecc_buf_cfg = cpu_to_le32(host->ecc_buf_cfg); -+ -+ nandc->regs->clrflashstatus = cpu_to_le32(host->clrflashstatus); -+ nandc->regs->clrreadstatus = cpu_to_le32(host->clrreadstatus); -+ nandc->regs->exec = cpu_to_le32(1); - - if (read) - nandc_set_read_loc(chip, cw, 0, 0, host->use_ecc ? -@@ -1121,7 +1088,7 @@ static int read_reg_dma(struct qcom_nand - if (first == NAND_DEV_CMD_VLD || first == NAND_DEV_CMD1) - first = dev_cmd_reg_addr(nandc, first); - -- if (nandc->props->is_bam) -+ if (nandc->props->supports_bam) - return prep_bam_dma_desc_cmd(nandc, true, first, vaddr, - num_regs, flags); - -@@ -1136,25 +1103,16 @@ static int read_reg_dma(struct qcom_nand - * write_reg_dma: prepares a descriptor to write a given number of - * contiguous registers - * -+ * @vaddr: contiguous memory from where register value will -+ * be written - * @first: offset of the first register in the contiguous block - * @num_regs: number of registers to write - * @flags: flags to control DMA descriptor preparation - */ --static int write_reg_dma(struct qcom_nand_controller *nandc, int first, -- int num_regs, unsigned int flags) -+static int write_reg_dma(struct qcom_nand_controller *nandc, __le32 *vaddr, -+ int first, int num_regs, unsigned int flags) - { - bool flow_control = false; -- struct nandc_regs *regs = nandc->regs; -- void *vaddr; -- -- vaddr = offset_to_nandc_reg(regs, first); -- -- if (first == NAND_ERASED_CW_DETECT_CFG) { -- if (flags & NAND_ERASED_CW_SET) -- vaddr = ®s->erased_cw_detect_cfg_set; -- else -- vaddr = ®s->erased_cw_detect_cfg_clr; -- } - - if (first == NAND_EXEC_CMD) - flags |= NAND_BAM_NWD; -@@ -1165,7 +1123,7 @@ static int write_reg_dma(struct qcom_nan - if (first == NAND_DEV_CMD_VLD_RESTORE || first == NAND_DEV_CMD_VLD) - first = dev_cmd_reg_addr(nandc, NAND_DEV_CMD_VLD); - -- if (nandc->props->is_bam) -+ if (nandc->props->supports_bam) - return prep_bam_dma_desc_cmd(nandc, false, first, vaddr, - num_regs, flags); - -@@ -1188,7 +1146,7 @@ static int write_reg_dma(struct qcom_nan - static int read_data_dma(struct qcom_nand_controller *nandc, int reg_off, - const u8 *vaddr, int size, unsigned int flags) - { -- if (nandc->props->is_bam) -+ if (nandc->props->supports_bam) - return prep_bam_dma_desc_data(nandc, true, vaddr, size, flags); - - return prep_adm_dma_desc(nandc, true, reg_off, vaddr, size, false); -@@ -1206,7 +1164,7 @@ static int read_data_dma(struct qcom_nan - static int write_data_dma(struct qcom_nand_controller *nandc, int reg_off, - const u8 *vaddr, int size, unsigned int flags) - { -- if (nandc->props->is_bam) -+ if (nandc->props->supports_bam) - return prep_bam_dma_desc_data(nandc, false, vaddr, size, flags); - - return prep_adm_dma_desc(nandc, false, reg_off, vaddr, size, false); -@@ -1220,13 +1178,14 @@ static void config_nand_page_read(struct - { - struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); - -- write_reg_dma(nandc, NAND_ADDR0, 2, 0); -- write_reg_dma(nandc, NAND_DEV0_CFG0, 3, 0); -- if (!nandc->props->qpic_v2) -- write_reg_dma(nandc, NAND_EBI2_ECC_BUF_CFG, 1, 0); -- write_reg_dma(nandc, NAND_ERASED_CW_DETECT_CFG, 1, 0); -- write_reg_dma(nandc, NAND_ERASED_CW_DETECT_CFG, 1, -- NAND_ERASED_CW_SET | NAND_BAM_NEXT_SGL); -+ write_reg_dma(nandc, &nandc->regs->addr0, NAND_ADDR0, 2, 0); -+ write_reg_dma(nandc, &nandc->regs->cfg0, NAND_DEV0_CFG0, 3, 0); -+ if (!nandc->props->qpic_version2) -+ write_reg_dma(nandc, &nandc->regs->ecc_buf_cfg, NAND_EBI2_ECC_BUF_CFG, 1, 0); -+ write_reg_dma(nandc, &nandc->regs->erased_cw_detect_cfg_clr, -+ NAND_ERASED_CW_DETECT_CFG, 1, 0); -+ write_reg_dma(nandc, &nandc->regs->erased_cw_detect_cfg_set, -+ NAND_ERASED_CW_DETECT_CFG, 1, NAND_ERASED_CW_SET | NAND_BAM_NEXT_SGL); - } - - /* -@@ -1239,16 +1198,16 @@ config_nand_cw_read(struct nand_chip *ch - struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); - struct nand_ecc_ctrl *ecc = &chip->ecc; - -- int reg = NAND_READ_LOCATION_0; -+ __le32 *reg = &nandc->regs->read_location0; - -- if (nandc->props->qpic_v2 && qcom_nandc_is_last_cw(ecc, cw)) -- reg = NAND_READ_LOCATION_LAST_CW_0; -+ if (nandc->props->qpic_version2 && qcom_nandc_is_last_cw(ecc, cw)) -+ reg = &nandc->regs->read_location_last0; - -- if (nandc->props->is_bam) -- write_reg_dma(nandc, reg, 4, NAND_BAM_NEXT_SGL); -+ if (nandc->props->supports_bam) -+ write_reg_dma(nandc, reg, NAND_READ_LOCATION_0, 4, NAND_BAM_NEXT_SGL); - -- write_reg_dma(nandc, NAND_FLASH_CMD, 1, NAND_BAM_NEXT_SGL); -- write_reg_dma(nandc, NAND_EXEC_CMD, 1, NAND_BAM_NEXT_SGL); -+ write_reg_dma(nandc, &nandc->regs->cmd, NAND_FLASH_CMD, 1, NAND_BAM_NEXT_SGL); -+ write_reg_dma(nandc, &nandc->regs->exec, NAND_EXEC_CMD, 1, NAND_BAM_NEXT_SGL); - - if (use_ecc) { - read_reg_dma(nandc, NAND_FLASH_STATUS, 2, 0); -@@ -1279,10 +1238,10 @@ static void config_nand_page_write(struc - { - struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); - -- write_reg_dma(nandc, NAND_ADDR0, 2, 0); -- write_reg_dma(nandc, NAND_DEV0_CFG0, 3, 0); -- if (!nandc->props->qpic_v2) -- write_reg_dma(nandc, NAND_EBI2_ECC_BUF_CFG, 1, -+ write_reg_dma(nandc, &nandc->regs->addr0, NAND_ADDR0, 2, 0); -+ write_reg_dma(nandc, &nandc->regs->cfg0, NAND_DEV0_CFG0, 3, 0); -+ if (!nandc->props->qpic_version2) -+ write_reg_dma(nandc, &nandc->regs->ecc_buf_cfg, NAND_EBI2_ECC_BUF_CFG, 1, - NAND_BAM_NEXT_SGL); - } - -@@ -1294,13 +1253,13 @@ static void config_nand_cw_write(struct - { - struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); - -- write_reg_dma(nandc, NAND_FLASH_CMD, 1, NAND_BAM_NEXT_SGL); -- write_reg_dma(nandc, NAND_EXEC_CMD, 1, NAND_BAM_NEXT_SGL); -+ write_reg_dma(nandc, &nandc->regs->cmd, NAND_FLASH_CMD, 1, NAND_BAM_NEXT_SGL); -+ write_reg_dma(nandc, &nandc->regs->exec, NAND_EXEC_CMD, 1, NAND_BAM_NEXT_SGL); - - read_reg_dma(nandc, NAND_FLASH_STATUS, 1, NAND_BAM_NEXT_SGL); - -- write_reg_dma(nandc, NAND_FLASH_STATUS, 1, 0); -- write_reg_dma(nandc, NAND_READ_STATUS, 1, NAND_BAM_NEXT_SGL); -+ write_reg_dma(nandc, &nandc->regs->clrflashstatus, NAND_FLASH_STATUS, 1, 0); -+ write_reg_dma(nandc, &nandc->regs->clrreadstatus, NAND_READ_STATUS, 1, NAND_BAM_NEXT_SGL); - } - - /* helpers to submit/free our list of dma descriptors */ -@@ -1311,7 +1270,7 @@ static int submit_descs(struct qcom_nand - struct bam_transaction *bam_txn = nandc->bam_txn; - int ret = 0; - -- if (nandc->props->is_bam) { -+ if (nandc->props->supports_bam) { - if (bam_txn->rx_sgl_pos > bam_txn->rx_sgl_start) { - ret = prepare_bam_async_desc(nandc, nandc->rx_chan, 0); - if (ret) -@@ -1336,14 +1295,9 @@ static int submit_descs(struct qcom_nand - list_for_each_entry(desc, &nandc->desc_list, node) - cookie = dmaengine_submit(desc->dma_desc); - -- if (nandc->props->is_bam) { -+ if (nandc->props->supports_bam) { - bam_txn->last_cmd_desc->callback = qpic_bam_dma_done; - bam_txn->last_cmd_desc->callback_param = bam_txn; -- if (bam_txn->last_data_desc) { -- bam_txn->last_data_desc->callback = qpic_bam_dma_done; -- bam_txn->last_data_desc->callback_param = bam_txn; -- bam_txn->wait_second_completion = true; -- } - - dma_async_issue_pending(nandc->tx_chan); - dma_async_issue_pending(nandc->rx_chan); -@@ -1365,7 +1319,7 @@ err_unmap_free_desc: - list_for_each_entry_safe(desc, n, &nandc->desc_list, node) { - list_del(&desc->node); - -- if (nandc->props->is_bam) -+ if (nandc->props->supports_bam) - dma_unmap_sg(nandc->dev, desc->bam_sgl, - desc->sgl_cnt, desc->dir); - else -@@ -1382,7 +1336,7 @@ err_unmap_free_desc: - static void clear_read_regs(struct qcom_nand_controller *nandc) - { - nandc->reg_read_pos = 0; -- nandc_read_buffer_sync(nandc, false); -+ nandc_dev_to_mem(nandc, false); - } - - /* -@@ -1446,7 +1400,7 @@ static int check_flash_errors(struct qco - struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); - int i; - -- nandc_read_buffer_sync(nandc, true); -+ nandc_dev_to_mem(nandc, true); - - for (i = 0; i < cw_cnt; i++) { - u32 flash = le32_to_cpu(nandc->reg_read_buf[i]); -@@ -1476,7 +1430,7 @@ qcom_nandc_read_cw_raw(struct mtd_info * - clear_read_regs(nandc); - host->use_ecc = false; - -- if (nandc->props->qpic_v2) -+ if (nandc->props->qpic_version2) - raw_cw = ecc->steps - 1; - - clear_bam_transaction(nandc); -@@ -1497,7 +1451,7 @@ qcom_nandc_read_cw_raw(struct mtd_info * - oob_size2 = host->ecc_bytes_hw + host->spare_bytes; - } - -- if (nandc->props->is_bam) { -+ if (nandc->props->supports_bam) { - nandc_set_read_loc(chip, cw, 0, read_loc, data_size1, 0); - read_loc += data_size1; - -@@ -1621,7 +1575,7 @@ static int parse_read_errors(struct qcom - u8 *data_buf_start = data_buf, *oob_buf_start = oob_buf; - - buf = (struct read_stats *)nandc->reg_read_buf; -- nandc_read_buffer_sync(nandc, true); -+ nandc_dev_to_mem(nandc, true); - - for (i = 0; i < ecc->steps; i++, buf++) { - u32 flash, buffer, erased_cw; -@@ -1734,7 +1688,7 @@ static int read_page_ecc(struct qcom_nan - oob_size = host->ecc_bytes_hw + host->spare_bytes; - } - -- if (nandc->props->is_bam) { -+ if (nandc->props->supports_bam) { - if (data_buf && oob_buf) { - nandc_set_read_loc(chip, i, 0, 0, data_size, 0); - nandc_set_read_loc(chip, i, 1, data_size, -@@ -2455,14 +2409,14 @@ static int qcom_nand_attach_chip(struct - - mtd_set_ooblayout(mtd, &qcom_nand_ooblayout_ops); - /* Free the initially allocated BAM transaction for reading the ONFI params */ -- if (nandc->props->is_bam) -+ if (nandc->props->supports_bam) - free_bam_transaction(nandc); - - nandc->max_cwperpage = max_t(unsigned int, nandc->max_cwperpage, - cwperpage); - - /* Now allocate the BAM transaction based on updated max_cwperpage */ -- if (nandc->props->is_bam) { -+ if (nandc->props->supports_bam) { - nandc->bam_txn = alloc_bam_transaction(nandc); - if (!nandc->bam_txn) { - dev_err(nandc->dev, -@@ -2522,7 +2476,7 @@ static int qcom_nand_attach_chip(struct - | ecc_mode << ECC_MODE - | host->ecc_bytes_hw << ECC_PARITY_SIZE_BYTES_BCH; - -- if (!nandc->props->qpic_v2) -+ if (!nandc->props->qpic_version2) - host->ecc_buf_cfg = 0x203 << NUM_STEPS; - - host->clrflashstatus = FS_READY_BSY_N; -@@ -2556,7 +2510,7 @@ static int qcom_op_cmd_mapping(struct na - cmd = OP_FETCH_ID; - break; - case NAND_CMD_PARAM: -- if (nandc->props->qpic_v2) -+ if (nandc->props->qpic_version2) - cmd = OP_PAGE_READ_ONFI_READ; - else - cmd = OP_PAGE_READ; -@@ -2609,7 +2563,7 @@ static int qcom_parse_instructions(struc - if (ret < 0) - return ret; - -- q_op->cmd_reg = ret; -+ q_op->cmd_reg = cpu_to_le32(ret); - q_op->rdy_delay_ns = instr->delay_ns; - break; - -@@ -2619,10 +2573,10 @@ static int qcom_parse_instructions(struc - addrs = &instr->ctx.addr.addrs[offset]; - - for (i = 0; i < min_t(unsigned int, 4, naddrs); i++) -- q_op->addr1_reg |= addrs[i] << (i * 8); -+ q_op->addr1_reg |= cpu_to_le32(addrs[i] << (i * 8)); - - if (naddrs > 4) -- q_op->addr2_reg |= addrs[4]; -+ q_op->addr2_reg |= cpu_to_le32(addrs[4]); - - q_op->rdy_delay_ns = instr->delay_ns; - break; -@@ -2663,7 +2617,7 @@ static int qcom_wait_rdy_poll(struct nan - unsigned long start = jiffies + msecs_to_jiffies(time_ms); - u32 flash; - -- nandc_read_buffer_sync(nandc, true); -+ nandc_dev_to_mem(nandc, true); - - do { - flash = le32_to_cpu(nandc->reg_read_buf[0]); -@@ -2706,11 +2660,11 @@ static int qcom_read_status_exec(struct - clear_read_regs(nandc); - clear_bam_transaction(nandc); - -- nandc_set_reg(chip, NAND_FLASH_CMD, q_op.cmd_reg); -- nandc_set_reg(chip, NAND_EXEC_CMD, 1); -+ nandc->regs->cmd = q_op.cmd_reg; -+ nandc->regs->exec = cpu_to_le32(1); - -- write_reg_dma(nandc, NAND_FLASH_CMD, 1, NAND_BAM_NEXT_SGL); -- write_reg_dma(nandc, NAND_EXEC_CMD, 1, NAND_BAM_NEXT_SGL); -+ write_reg_dma(nandc, &nandc->regs->cmd, NAND_FLASH_CMD, 1, NAND_BAM_NEXT_SGL); -+ write_reg_dma(nandc, &nandc->regs->exec, NAND_EXEC_CMD, 1, NAND_BAM_NEXT_SGL); - read_reg_dma(nandc, NAND_FLASH_STATUS, 1, NAND_BAM_NEXT_SGL); - - ret = submit_descs(nandc); -@@ -2719,7 +2673,7 @@ static int qcom_read_status_exec(struct - goto err_out; - } - -- nandc_read_buffer_sync(nandc, true); -+ nandc_dev_to_mem(nandc, true); - - for (i = 0; i < num_cw; i++) { - flash_status = le32_to_cpu(nandc->reg_read_buf[i]); -@@ -2763,16 +2717,14 @@ static int qcom_read_id_type_exec(struct - clear_read_regs(nandc); - clear_bam_transaction(nandc); - -- nandc_set_reg(chip, NAND_FLASH_CMD, q_op.cmd_reg); -- nandc_set_reg(chip, NAND_ADDR0, q_op.addr1_reg); -- nandc_set_reg(chip, NAND_ADDR1, q_op.addr2_reg); -- nandc_set_reg(chip, NAND_FLASH_CHIP_SELECT, -- nandc->props->is_bam ? 0 : DM_EN); -+ nandc->regs->cmd = q_op.cmd_reg; -+ nandc->regs->addr0 = q_op.addr1_reg; -+ nandc->regs->addr1 = q_op.addr2_reg; -+ nandc->regs->chip_sel = cpu_to_le32(nandc->props->supports_bam ? 0 : DM_EN); -+ nandc->regs->exec = cpu_to_le32(1); - -- nandc_set_reg(chip, NAND_EXEC_CMD, 1); -- -- write_reg_dma(nandc, NAND_FLASH_CMD, 4, NAND_BAM_NEXT_SGL); -- write_reg_dma(nandc, NAND_EXEC_CMD, 1, NAND_BAM_NEXT_SGL); -+ write_reg_dma(nandc, &nandc->regs->cmd, NAND_FLASH_CMD, 4, NAND_BAM_NEXT_SGL); -+ write_reg_dma(nandc, &nandc->regs->exec, NAND_EXEC_CMD, 1, NAND_BAM_NEXT_SGL); - - read_reg_dma(nandc, NAND_READ_ID, 1, NAND_BAM_NEXT_SGL); - -@@ -2786,7 +2738,7 @@ static int qcom_read_id_type_exec(struct - op_id = q_op.data_instr_idx; - len = nand_subop_get_data_len(subop, op_id); - -- nandc_read_buffer_sync(nandc, true); -+ nandc_dev_to_mem(nandc, true); - memcpy(instr->ctx.data.buf.in, nandc->reg_read_buf, len); - - err_out: -@@ -2807,15 +2759,14 @@ static int qcom_misc_cmd_type_exec(struc - - if (q_op.flag == OP_PROGRAM_PAGE) { - goto wait_rdy; -- } else if (q_op.cmd_reg == OP_BLOCK_ERASE) { -- q_op.cmd_reg |= PAGE_ACC | LAST_PAGE; -- nandc_set_reg(chip, NAND_ADDR0, q_op.addr1_reg); -- nandc_set_reg(chip, NAND_ADDR1, q_op.addr2_reg); -- nandc_set_reg(chip, NAND_DEV0_CFG0, -- host->cfg0_raw & ~(7 << CW_PER_PAGE)); -- nandc_set_reg(chip, NAND_DEV0_CFG1, host->cfg1_raw); -+ } else if (q_op.cmd_reg == cpu_to_le32(OP_BLOCK_ERASE)) { -+ q_op.cmd_reg |= cpu_to_le32(PAGE_ACC | LAST_PAGE); -+ nandc->regs->addr0 = q_op.addr1_reg; -+ nandc->regs->addr1 = q_op.addr2_reg; -+ nandc->regs->cfg0 = cpu_to_le32(host->cfg0_raw & ~(7 << CW_PER_PAGE)); -+ nandc->regs->cfg1 = cpu_to_le32(host->cfg1_raw); - instrs = 3; -- } else if (q_op.cmd_reg != OP_RESET_DEVICE) { -+ } else if (q_op.cmd_reg != cpu_to_le32(OP_RESET_DEVICE)) { - return 0; - } - -@@ -2826,14 +2777,14 @@ static int qcom_misc_cmd_type_exec(struc - clear_read_regs(nandc); - clear_bam_transaction(nandc); - -- nandc_set_reg(chip, NAND_FLASH_CMD, q_op.cmd_reg); -- nandc_set_reg(chip, NAND_EXEC_CMD, 1); -+ nandc->regs->cmd = q_op.cmd_reg; -+ nandc->regs->exec = cpu_to_le32(1); - -- write_reg_dma(nandc, NAND_FLASH_CMD, instrs, NAND_BAM_NEXT_SGL); -- if (q_op.cmd_reg == OP_BLOCK_ERASE) -- write_reg_dma(nandc, NAND_DEV0_CFG0, 2, NAND_BAM_NEXT_SGL); -+ write_reg_dma(nandc, &nandc->regs->cmd, NAND_FLASH_CMD, instrs, NAND_BAM_NEXT_SGL); -+ if (q_op.cmd_reg == cpu_to_le32(OP_BLOCK_ERASE)) -+ write_reg_dma(nandc, &nandc->regs->cfg0, NAND_DEV0_CFG0, 2, NAND_BAM_NEXT_SGL); - -- write_reg_dma(nandc, NAND_EXEC_CMD, 1, NAND_BAM_NEXT_SGL); -+ write_reg_dma(nandc, &nandc->regs->exec, NAND_EXEC_CMD, 1, NAND_BAM_NEXT_SGL); - read_reg_dma(nandc, NAND_FLASH_STATUS, 1, NAND_BAM_NEXT_SGL); - - ret = submit_descs(nandc); -@@ -2862,14 +2813,14 @@ static int qcom_param_page_type_exec(str - - reg_base = NAND_READ_LOCATION_0; - -- if (nandc->props->qpic_v2) -+ if (nandc->props->qpic_version2) - reg_base = NAND_READ_LOCATION_LAST_CW_0; - - ret = qcom_parse_instructions(chip, subop, &q_op); - if (ret) - return ret; - -- q_op.cmd_reg |= PAGE_ACC | LAST_PAGE; -+ q_op.cmd_reg |= cpu_to_le32(PAGE_ACC | LAST_PAGE); - - nandc->buf_count = 0; - nandc->buf_start = 0; -@@ -2877,52 +2828,52 @@ static int qcom_param_page_type_exec(str - clear_read_regs(nandc); - clear_bam_transaction(nandc); - -- nandc_set_reg(chip, NAND_FLASH_CMD, q_op.cmd_reg); -+ nandc->regs->cmd = q_op.cmd_reg; -+ nandc->regs->addr0 = 0; -+ nandc->regs->addr1 = 0; -+ -+ nandc->regs->cfg0 = cpu_to_le32(0 << CW_PER_PAGE | -+ 512 << UD_SIZE_BYTES | -+ 5 << NUM_ADDR_CYCLES | -+ 0 << SPARE_SIZE_BYTES); -+ -+ nandc->regs->cfg1 = cpu_to_le32(7 << NAND_RECOVERY_CYCLES | -+ 0 << CS_ACTIVE_BSY | -+ 17 << BAD_BLOCK_BYTE_NUM | -+ 1 << BAD_BLOCK_IN_SPARE_AREA | -+ 2 << WR_RD_BSY_GAP | -+ 0 << WIDE_FLASH | -+ 1 << DEV0_CFG1_ECC_DISABLE); - -- nandc_set_reg(chip, NAND_ADDR0, 0); -- nandc_set_reg(chip, NAND_ADDR1, 0); -- nandc_set_reg(chip, NAND_DEV0_CFG0, 0 << CW_PER_PAGE -- | 512 << UD_SIZE_BYTES -- | 5 << NUM_ADDR_CYCLES -- | 0 << SPARE_SIZE_BYTES); -- nandc_set_reg(chip, NAND_DEV0_CFG1, 7 << NAND_RECOVERY_CYCLES -- | 0 << CS_ACTIVE_BSY -- | 17 << BAD_BLOCK_BYTE_NUM -- | 1 << BAD_BLOCK_IN_SPARE_AREA -- | 2 << WR_RD_BSY_GAP -- | 0 << WIDE_FLASH -- | 1 << DEV0_CFG1_ECC_DISABLE); -- if (!nandc->props->qpic_v2) -- nandc_set_reg(chip, NAND_EBI2_ECC_BUF_CFG, 1 << ECC_CFG_ECC_DISABLE); -+ if (!nandc->props->qpic_version2) -+ nandc->regs->ecc_buf_cfg = cpu_to_le32(1 << ECC_CFG_ECC_DISABLE); - - /* configure CMD1 and VLD for ONFI param probing in QPIC v1 */ -- if (!nandc->props->qpic_v2) { -- nandc_set_reg(chip, NAND_DEV_CMD_VLD, -- (nandc->vld & ~READ_START_VLD)); -- nandc_set_reg(chip, NAND_DEV_CMD1, -- (nandc->cmd1 & ~(0xFF << READ_ADDR)) -- | NAND_CMD_PARAM << READ_ADDR); -+ if (!nandc->props->qpic_version2) { -+ nandc->regs->vld = cpu_to_le32((nandc->vld & ~READ_START_VLD)); -+ nandc->regs->cmd1 = cpu_to_le32((nandc->cmd1 & ~(0xFF << READ_ADDR)) -+ | NAND_CMD_PARAM << READ_ADDR); - } - -- nandc_set_reg(chip, NAND_EXEC_CMD, 1); -- -- if (!nandc->props->qpic_v2) { -- nandc_set_reg(chip, NAND_DEV_CMD1_RESTORE, nandc->cmd1); -- nandc_set_reg(chip, NAND_DEV_CMD_VLD_RESTORE, nandc->vld); -+ nandc->regs->exec = cpu_to_le32(1); -+ -+ if (!nandc->props->qpic_version2) { -+ nandc->regs->orig_cmd1 = cpu_to_le32(nandc->cmd1); -+ nandc->regs->orig_vld = cpu_to_le32(nandc->vld); - } - - instr = q_op.data_instr; - op_id = q_op.data_instr_idx; - len = nand_subop_get_data_len(subop, op_id); - -- if (nandc->props->qpic_v2) -+ if (nandc->props->qpic_version2) - nandc_set_read_loc_last(chip, reg_base, 0, len, 1); - else - nandc_set_read_loc_first(chip, reg_base, 0, len, 1); - -- if (!nandc->props->qpic_v2) { -- write_reg_dma(nandc, NAND_DEV_CMD_VLD, 1, 0); -- write_reg_dma(nandc, NAND_DEV_CMD1, 1, NAND_BAM_NEXT_SGL); -+ if (!nandc->props->qpic_version2) { -+ write_reg_dma(nandc, &nandc->regs->vld, NAND_DEV_CMD_VLD, 1, 0); -+ write_reg_dma(nandc, &nandc->regs->cmd1, NAND_DEV_CMD1, 1, NAND_BAM_NEXT_SGL); - } - - nandc->buf_count = 512; -@@ -2934,9 +2885,10 @@ static int qcom_param_page_type_exec(str - nandc->buf_count, 0); - - /* restore CMD1 and VLD regs */ -- if (!nandc->props->qpic_v2) { -- write_reg_dma(nandc, NAND_DEV_CMD1_RESTORE, 1, 0); -- write_reg_dma(nandc, NAND_DEV_CMD_VLD_RESTORE, 1, NAND_BAM_NEXT_SGL); -+ if (!nandc->props->qpic_version2) { -+ write_reg_dma(nandc, &nandc->regs->orig_cmd1, NAND_DEV_CMD1_RESTORE, 1, 0); -+ write_reg_dma(nandc, &nandc->regs->orig_vld, NAND_DEV_CMD_VLD_RESTORE, 1, -+ NAND_BAM_NEXT_SGL); - } - - ret = submit_descs(nandc); -@@ -3025,7 +2977,7 @@ static const struct nand_controller_ops - - static void qcom_nandc_unalloc(struct qcom_nand_controller *nandc) - { -- if (nandc->props->is_bam) { -+ if (nandc->props->supports_bam) { - if (!dma_mapping_error(nandc->dev, nandc->reg_read_dma)) - dma_unmap_single(nandc->dev, nandc->reg_read_dma, - MAX_REG_RD * -@@ -3078,7 +3030,7 @@ static int qcom_nandc_alloc(struct qcom_ - if (!nandc->reg_read_buf) - return -ENOMEM; - -- if (nandc->props->is_bam) { -+ if (nandc->props->supports_bam) { - nandc->reg_read_dma = - dma_map_single(nandc->dev, nandc->reg_read_buf, - MAX_REG_RD * -@@ -3159,15 +3111,15 @@ static int qcom_nandc_setup(struct qcom_ - u32 nand_ctrl; - - /* kill onenand */ -- if (!nandc->props->is_qpic) -+ if (!nandc->props->nandc_part_of_qpic) - nandc_write(nandc, SFLASHC_BURST_CFG, 0); - -- if (!nandc->props->qpic_v2) -+ if (!nandc->props->qpic_version2) - nandc_write(nandc, dev_cmd_reg_addr(nandc, NAND_DEV_CMD_VLD), - NAND_DEV_CMD_VLD_VAL); - - /* enable ADM or BAM DMA */ -- if (nandc->props->is_bam) { -+ if (nandc->props->supports_bam) { - nand_ctrl = nandc_read(nandc, NAND_CTRL); - - /* -@@ -3184,7 +3136,7 @@ static int qcom_nandc_setup(struct qcom_ - } - - /* save the original values of these registers */ -- if (!nandc->props->qpic_v2) { -+ if (!nandc->props->qpic_version2) { - nandc->cmd1 = nandc_read(nandc, dev_cmd_reg_addr(nandc, NAND_DEV_CMD1)); - nandc->vld = NAND_DEV_CMD_VLD_VAL; - } -@@ -3357,7 +3309,7 @@ static int qcom_nandc_parse_dt(struct pl - struct device_node *np = nandc->dev->of_node; - int ret; - -- if (!nandc->props->is_bam) { -+ if (!nandc->props->supports_bam) { - ret = of_property_read_u32(np, "qcom,cmd-crci", - &nandc->cmd_crci); - if (ret) { -@@ -3482,30 +3434,30 @@ static void qcom_nandc_remove(struct pla - - static const struct qcom_nandc_props ipq806x_nandc_props = { - .ecc_modes = (ECC_RS_4BIT | ECC_BCH_8BIT), -- .is_bam = false, -+ .supports_bam = false, - .use_codeword_fixup = true, - .dev_cmd_reg_start = 0x0, - }; - - static const struct qcom_nandc_props ipq4019_nandc_props = { - .ecc_modes = (ECC_BCH_4BIT | ECC_BCH_8BIT), -- .is_bam = true, -- .is_qpic = true, -+ .supports_bam = true, -+ .nandc_part_of_qpic = true, - .dev_cmd_reg_start = 0x0, - }; - - static const struct qcom_nandc_props ipq8074_nandc_props = { - .ecc_modes = (ECC_BCH_4BIT | ECC_BCH_8BIT), -- .is_bam = true, -- .is_qpic = true, -+ .supports_bam = true, -+ .nandc_part_of_qpic = true, - .dev_cmd_reg_start = 0x7000, - }; - - static const struct qcom_nandc_props sdx55_nandc_props = { - .ecc_modes = (ECC_BCH_4BIT | ECC_BCH_8BIT), -- .is_bam = true, -- .is_qpic = true, -- .qpic_v2 = true, -+ .supports_bam = true, -+ .nandc_part_of_qpic = true, -+ .qpic_version2 = true, - .dev_cmd_reg_start = 0x7000, - }; - diff --git a/target/linux/generic/backport-6.18/410-02-v6.14-mtd-rawnand-qcom-Add-qcom-prefix-to-common-api.patch b/target/linux/generic/backport-6.18/410-02-v6.14-mtd-rawnand-qcom-Add-qcom-prefix-to-common-api.patch deleted file mode 100644 index 23ef86f807..0000000000 --- a/target/linux/generic/backport-6.18/410-02-v6.14-mtd-rawnand-qcom-Add-qcom-prefix-to-common-api.patch +++ /dev/null @@ -1,880 +0,0 @@ -From 1d479f5b345e0c3650fec4dddeef9fc6fab30c8b Mon Sep 17 00:00:00 2001 -From: Md Sadre Alam -Date: Wed, 20 Nov 2024 14:45:01 +0530 -Subject: [PATCH 2/4] mtd: rawnand: qcom: Add qcom prefix to common api - -Add qcom prefix to all the api which will be commonly -used by spi nand driver and raw nand driver. - -Reviewed-by: Konrad Dybcio -Signed-off-by: Md Sadre Alam -Signed-off-by: Miquel Raynal ---- - drivers/mtd/nand/raw/qcom_nandc.c | 320 +++++++++++++++--------------- - 1 file changed, 160 insertions(+), 160 deletions(-) - ---- a/drivers/mtd/nand/raw/qcom_nandc.c -+++ b/drivers/mtd/nand/raw/qcom_nandc.c -@@ -53,7 +53,7 @@ - #define NAND_READ_LOCATION_LAST_CW_2 0xf48 - #define NAND_READ_LOCATION_LAST_CW_3 0xf4c - --/* dummy register offsets, used by write_reg_dma */ -+/* dummy register offsets, used by qcom_write_reg_dma */ - #define NAND_DEV_CMD1_RESTORE 0xdead - #define NAND_DEV_CMD_VLD_RESTORE 0xbeef - -@@ -211,7 +211,7 @@ - - /* - * Flags used in DMA descriptor preparation helper functions -- * (i.e. read_reg_dma/write_reg_dma/read_data_dma/write_data_dma) -+ * (i.e. qcom_read_reg_dma/qcom_write_reg_dma/qcom_read_data_dma/qcom_write_data_dma) - */ - /* Don't set the EOT in current tx BAM sgl */ - #define NAND_BAM_NO_EOT BIT(0) -@@ -550,7 +550,7 @@ struct qcom_nandc_props { - }; - - /* Frees the BAM transaction memory */ --static void free_bam_transaction(struct qcom_nand_controller *nandc) -+static void qcom_free_bam_transaction(struct qcom_nand_controller *nandc) - { - struct bam_transaction *bam_txn = nandc->bam_txn; - -@@ -559,7 +559,7 @@ static void free_bam_transaction(struct - - /* Allocates and Initializes the BAM transaction */ - static struct bam_transaction * --alloc_bam_transaction(struct qcom_nand_controller *nandc) -+qcom_alloc_bam_transaction(struct qcom_nand_controller *nandc) - { - struct bam_transaction *bam_txn; - size_t bam_txn_size; -@@ -595,7 +595,7 @@ alloc_bam_transaction(struct qcom_nand_c - } - - /* Clears the BAM transaction indexes */ --static void clear_bam_transaction(struct qcom_nand_controller *nandc) -+static void qcom_clear_bam_transaction(struct qcom_nand_controller *nandc) - { - struct bam_transaction *bam_txn = nandc->bam_txn; - -@@ -614,7 +614,7 @@ static void clear_bam_transaction(struct - } - - /* Callback for DMA descriptor completion */ --static void qpic_bam_dma_done(void *data) -+static void qcom_qpic_bam_dma_done(void *data) - { - struct bam_transaction *bam_txn = data; - -@@ -644,7 +644,7 @@ static void nandc_write(struct qcom_nand - iowrite32(val, nandc->base + offset); - } - --static void nandc_dev_to_mem(struct qcom_nand_controller *nandc, bool is_cpu) -+static void qcom_nandc_dev_to_mem(struct qcom_nand_controller *nandc, bool is_cpu) - { - if (!nandc->props->supports_bam) - return; -@@ -824,9 +824,9 @@ static void update_rw_regs(struct qcom_n - * for BAM. This descriptor will be added in the NAND DMA descriptor queue - * which will be submitted to DMA engine. - */ --static int prepare_bam_async_desc(struct qcom_nand_controller *nandc, -- struct dma_chan *chan, -- unsigned long flags) -+static int qcom_prepare_bam_async_desc(struct qcom_nand_controller *nandc, -+ struct dma_chan *chan, -+ unsigned long flags) - { - struct desc_info *desc; - struct scatterlist *sgl; -@@ -903,9 +903,9 @@ static int prepare_bam_async_desc(struct - * NAND_BAM_NEXT_SGL will be used for starting the separate SGL - * after the current command element. - */ --static int prep_bam_dma_desc_cmd(struct qcom_nand_controller *nandc, bool read, -- int reg_off, const void *vaddr, -- int size, unsigned int flags) -+static int qcom_prep_bam_dma_desc_cmd(struct qcom_nand_controller *nandc, bool read, -+ int reg_off, const void *vaddr, -+ int size, unsigned int flags) - { - int bam_ce_size; - int i, ret; -@@ -943,9 +943,9 @@ static int prep_bam_dma_desc_cmd(struct - bam_txn->bam_ce_start = bam_txn->bam_ce_pos; - - if (flags & NAND_BAM_NWD) { -- ret = prepare_bam_async_desc(nandc, nandc->cmd_chan, -- DMA_PREP_FENCE | -- DMA_PREP_CMD); -+ ret = qcom_prepare_bam_async_desc(nandc, nandc->cmd_chan, -+ DMA_PREP_FENCE | -+ DMA_PREP_CMD); - if (ret) - return ret; - } -@@ -958,9 +958,8 @@ static int prep_bam_dma_desc_cmd(struct - * Prepares the data descriptor for BAM DMA which will be used for NAND - * data reads and writes. - */ --static int prep_bam_dma_desc_data(struct qcom_nand_controller *nandc, bool read, -- const void *vaddr, -- int size, unsigned int flags) -+static int qcom_prep_bam_dma_desc_data(struct qcom_nand_controller *nandc, bool read, -+ const void *vaddr, int size, unsigned int flags) - { - int ret; - struct bam_transaction *bam_txn = nandc->bam_txn; -@@ -979,8 +978,8 @@ static int prep_bam_dma_desc_data(struct - * is not set, form the DMA descriptor - */ - if (!(flags & NAND_BAM_NO_EOT)) { -- ret = prepare_bam_async_desc(nandc, nandc->tx_chan, -- DMA_PREP_INTERRUPT); -+ ret = qcom_prepare_bam_async_desc(nandc, nandc->tx_chan, -+ DMA_PREP_INTERRUPT); - if (ret) - return ret; - } -@@ -989,9 +988,9 @@ static int prep_bam_dma_desc_data(struct - return 0; - } - --static int prep_adm_dma_desc(struct qcom_nand_controller *nandc, bool read, -- int reg_off, const void *vaddr, int size, -- bool flow_control) -+static int qcom_prep_adm_dma_desc(struct qcom_nand_controller *nandc, bool read, -+ int reg_off, const void *vaddr, int size, -+ bool flow_control) - { - struct desc_info *desc; - struct dma_async_tx_descriptor *dma_desc; -@@ -1069,15 +1068,15 @@ err: - } - - /* -- * read_reg_dma: prepares a descriptor to read a given number of -+ * qcom_read_reg_dma: prepares a descriptor to read a given number of - * contiguous registers to the reg_read_buf pointer - * - * @first: offset of the first register in the contiguous block - * @num_regs: number of registers to read - * @flags: flags to control DMA descriptor preparation - */ --static int read_reg_dma(struct qcom_nand_controller *nandc, int first, -- int num_regs, unsigned int flags) -+static int qcom_read_reg_dma(struct qcom_nand_controller *nandc, int first, -+ int num_regs, unsigned int flags) - { - bool flow_control = false; - void *vaddr; -@@ -1089,18 +1088,18 @@ static int read_reg_dma(struct qcom_nand - first = dev_cmd_reg_addr(nandc, first); - - if (nandc->props->supports_bam) -- return prep_bam_dma_desc_cmd(nandc, true, first, vaddr, -+ return qcom_prep_bam_dma_desc_cmd(nandc, true, first, vaddr, - num_regs, flags); - - if (first == NAND_READ_ID || first == NAND_FLASH_STATUS) - flow_control = true; - -- return prep_adm_dma_desc(nandc, true, first, vaddr, -+ return qcom_prep_adm_dma_desc(nandc, true, first, vaddr, - num_regs * sizeof(u32), flow_control); - } - - /* -- * write_reg_dma: prepares a descriptor to write a given number of -+ * qcom_write_reg_dma: prepares a descriptor to write a given number of - * contiguous registers - * - * @vaddr: contiguous memory from where register value will -@@ -1109,8 +1108,8 @@ static int read_reg_dma(struct qcom_nand - * @num_regs: number of registers to write - * @flags: flags to control DMA descriptor preparation - */ --static int write_reg_dma(struct qcom_nand_controller *nandc, __le32 *vaddr, -- int first, int num_regs, unsigned int flags) -+static int qcom_write_reg_dma(struct qcom_nand_controller *nandc, __le32 *vaddr, -+ int first, int num_regs, unsigned int flags) - { - bool flow_control = false; - -@@ -1124,18 +1123,18 @@ static int write_reg_dma(struct qcom_nan - first = dev_cmd_reg_addr(nandc, NAND_DEV_CMD_VLD); - - if (nandc->props->supports_bam) -- return prep_bam_dma_desc_cmd(nandc, false, first, vaddr, -+ return qcom_prep_bam_dma_desc_cmd(nandc, false, first, vaddr, - num_regs, flags); - - if (first == NAND_FLASH_CMD) - flow_control = true; - -- return prep_adm_dma_desc(nandc, false, first, vaddr, -+ return qcom_prep_adm_dma_desc(nandc, false, first, vaddr, - num_regs * sizeof(u32), flow_control); - } - - /* -- * read_data_dma: prepares a DMA descriptor to transfer data from the -+ * qcom_read_data_dma: prepares a DMA descriptor to transfer data from the - * controller's internal buffer to the buffer 'vaddr' - * - * @reg_off: offset within the controller's data buffer -@@ -1143,17 +1142,17 @@ static int write_reg_dma(struct qcom_nan - * @size: DMA transaction size in bytes - * @flags: flags to control DMA descriptor preparation - */ --static int read_data_dma(struct qcom_nand_controller *nandc, int reg_off, -- const u8 *vaddr, int size, unsigned int flags) -+static int qcom_read_data_dma(struct qcom_nand_controller *nandc, int reg_off, -+ const u8 *vaddr, int size, unsigned int flags) - { - if (nandc->props->supports_bam) -- return prep_bam_dma_desc_data(nandc, true, vaddr, size, flags); -+ return qcom_prep_bam_dma_desc_data(nandc, true, vaddr, size, flags); - -- return prep_adm_dma_desc(nandc, true, reg_off, vaddr, size, false); -+ return qcom_prep_adm_dma_desc(nandc, true, reg_off, vaddr, size, false); - } - - /* -- * write_data_dma: prepares a DMA descriptor to transfer data from -+ * qcom_write_data_dma: prepares a DMA descriptor to transfer data from - * 'vaddr' to the controller's internal buffer - * - * @reg_off: offset within the controller's data buffer -@@ -1161,13 +1160,13 @@ static int read_data_dma(struct qcom_nan - * @size: DMA transaction size in bytes - * @flags: flags to control DMA descriptor preparation - */ --static int write_data_dma(struct qcom_nand_controller *nandc, int reg_off, -- const u8 *vaddr, int size, unsigned int flags) -+static int qcom_write_data_dma(struct qcom_nand_controller *nandc, int reg_off, -+ const u8 *vaddr, int size, unsigned int flags) - { - if (nandc->props->supports_bam) -- return prep_bam_dma_desc_data(nandc, false, vaddr, size, flags); -+ return qcom_prep_bam_dma_desc_data(nandc, false, vaddr, size, flags); - -- return prep_adm_dma_desc(nandc, false, reg_off, vaddr, size, false); -+ return qcom_prep_adm_dma_desc(nandc, false, reg_off, vaddr, size, false); - } - - /* -@@ -1178,14 +1177,14 @@ static void config_nand_page_read(struct - { - struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); - -- write_reg_dma(nandc, &nandc->regs->addr0, NAND_ADDR0, 2, 0); -- write_reg_dma(nandc, &nandc->regs->cfg0, NAND_DEV0_CFG0, 3, 0); -+ qcom_write_reg_dma(nandc, &nandc->regs->addr0, NAND_ADDR0, 2, 0); -+ qcom_write_reg_dma(nandc, &nandc->regs->cfg0, NAND_DEV0_CFG0, 3, 0); - if (!nandc->props->qpic_version2) -- write_reg_dma(nandc, &nandc->regs->ecc_buf_cfg, NAND_EBI2_ECC_BUF_CFG, 1, 0); -- write_reg_dma(nandc, &nandc->regs->erased_cw_detect_cfg_clr, -- NAND_ERASED_CW_DETECT_CFG, 1, 0); -- write_reg_dma(nandc, &nandc->regs->erased_cw_detect_cfg_set, -- NAND_ERASED_CW_DETECT_CFG, 1, NAND_ERASED_CW_SET | NAND_BAM_NEXT_SGL); -+ qcom_write_reg_dma(nandc, &nandc->regs->ecc_buf_cfg, NAND_EBI2_ECC_BUF_CFG, 1, 0); -+ qcom_write_reg_dma(nandc, &nandc->regs->erased_cw_detect_cfg_clr, -+ NAND_ERASED_CW_DETECT_CFG, 1, 0); -+ qcom_write_reg_dma(nandc, &nandc->regs->erased_cw_detect_cfg_set, -+ NAND_ERASED_CW_DETECT_CFG, 1, NAND_ERASED_CW_SET | NAND_BAM_NEXT_SGL); - } - - /* -@@ -1204,17 +1203,17 @@ config_nand_cw_read(struct nand_chip *ch - reg = &nandc->regs->read_location_last0; - - if (nandc->props->supports_bam) -- write_reg_dma(nandc, reg, NAND_READ_LOCATION_0, 4, NAND_BAM_NEXT_SGL); -+ qcom_write_reg_dma(nandc, reg, NAND_READ_LOCATION_0, 4, NAND_BAM_NEXT_SGL); - -- write_reg_dma(nandc, &nandc->regs->cmd, NAND_FLASH_CMD, 1, NAND_BAM_NEXT_SGL); -- write_reg_dma(nandc, &nandc->regs->exec, NAND_EXEC_CMD, 1, NAND_BAM_NEXT_SGL); -+ qcom_write_reg_dma(nandc, &nandc->regs->cmd, NAND_FLASH_CMD, 1, NAND_BAM_NEXT_SGL); -+ qcom_write_reg_dma(nandc, &nandc->regs->exec, NAND_EXEC_CMD, 1, NAND_BAM_NEXT_SGL); - - if (use_ecc) { -- read_reg_dma(nandc, NAND_FLASH_STATUS, 2, 0); -- read_reg_dma(nandc, NAND_ERASED_CW_DETECT_STATUS, 1, -- NAND_BAM_NEXT_SGL); -+ qcom_read_reg_dma(nandc, NAND_FLASH_STATUS, 2, 0); -+ qcom_read_reg_dma(nandc, NAND_ERASED_CW_DETECT_STATUS, 1, -+ NAND_BAM_NEXT_SGL); - } else { -- read_reg_dma(nandc, NAND_FLASH_STATUS, 1, NAND_BAM_NEXT_SGL); -+ qcom_read_reg_dma(nandc, NAND_FLASH_STATUS, 1, NAND_BAM_NEXT_SGL); - } - } - -@@ -1238,11 +1237,11 @@ static void config_nand_page_write(struc - { - struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); - -- write_reg_dma(nandc, &nandc->regs->addr0, NAND_ADDR0, 2, 0); -- write_reg_dma(nandc, &nandc->regs->cfg0, NAND_DEV0_CFG0, 3, 0); -+ qcom_write_reg_dma(nandc, &nandc->regs->addr0, NAND_ADDR0, 2, 0); -+ qcom_write_reg_dma(nandc, &nandc->regs->cfg0, NAND_DEV0_CFG0, 3, 0); - if (!nandc->props->qpic_version2) -- write_reg_dma(nandc, &nandc->regs->ecc_buf_cfg, NAND_EBI2_ECC_BUF_CFG, 1, -- NAND_BAM_NEXT_SGL); -+ qcom_write_reg_dma(nandc, &nandc->regs->ecc_buf_cfg, NAND_EBI2_ECC_BUF_CFG, 1, -+ NAND_BAM_NEXT_SGL); - } - - /* -@@ -1253,17 +1252,18 @@ static void config_nand_cw_write(struct - { - struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); - -- write_reg_dma(nandc, &nandc->regs->cmd, NAND_FLASH_CMD, 1, NAND_BAM_NEXT_SGL); -- write_reg_dma(nandc, &nandc->regs->exec, NAND_EXEC_CMD, 1, NAND_BAM_NEXT_SGL); -+ qcom_write_reg_dma(nandc, &nandc->regs->cmd, NAND_FLASH_CMD, 1, NAND_BAM_NEXT_SGL); -+ qcom_write_reg_dma(nandc, &nandc->regs->exec, NAND_EXEC_CMD, 1, NAND_BAM_NEXT_SGL); - -- read_reg_dma(nandc, NAND_FLASH_STATUS, 1, NAND_BAM_NEXT_SGL); -+ qcom_read_reg_dma(nandc, NAND_FLASH_STATUS, 1, NAND_BAM_NEXT_SGL); - -- write_reg_dma(nandc, &nandc->regs->clrflashstatus, NAND_FLASH_STATUS, 1, 0); -- write_reg_dma(nandc, &nandc->regs->clrreadstatus, NAND_READ_STATUS, 1, NAND_BAM_NEXT_SGL); -+ qcom_write_reg_dma(nandc, &nandc->regs->clrflashstatus, NAND_FLASH_STATUS, 1, 0); -+ qcom_write_reg_dma(nandc, &nandc->regs->clrreadstatus, NAND_READ_STATUS, 1, -+ NAND_BAM_NEXT_SGL); - } - - /* helpers to submit/free our list of dma descriptors */ --static int submit_descs(struct qcom_nand_controller *nandc) -+static int qcom_submit_descs(struct qcom_nand_controller *nandc) - { - struct desc_info *desc, *n; - dma_cookie_t cookie = 0; -@@ -1272,21 +1272,21 @@ static int submit_descs(struct qcom_nand - - if (nandc->props->supports_bam) { - if (bam_txn->rx_sgl_pos > bam_txn->rx_sgl_start) { -- ret = prepare_bam_async_desc(nandc, nandc->rx_chan, 0); -+ ret = qcom_prepare_bam_async_desc(nandc, nandc->rx_chan, 0); - if (ret) - goto err_unmap_free_desc; - } - - if (bam_txn->tx_sgl_pos > bam_txn->tx_sgl_start) { -- ret = prepare_bam_async_desc(nandc, nandc->tx_chan, -- DMA_PREP_INTERRUPT); -+ ret = qcom_prepare_bam_async_desc(nandc, nandc->tx_chan, -+ DMA_PREP_INTERRUPT); - if (ret) - goto err_unmap_free_desc; - } - - if (bam_txn->cmd_sgl_pos > bam_txn->cmd_sgl_start) { -- ret = prepare_bam_async_desc(nandc, nandc->cmd_chan, -- DMA_PREP_CMD); -+ ret = qcom_prepare_bam_async_desc(nandc, nandc->cmd_chan, -+ DMA_PREP_CMD); - if (ret) - goto err_unmap_free_desc; - } -@@ -1296,7 +1296,7 @@ static int submit_descs(struct qcom_nand - cookie = dmaengine_submit(desc->dma_desc); - - if (nandc->props->supports_bam) { -- bam_txn->last_cmd_desc->callback = qpic_bam_dma_done; -+ bam_txn->last_cmd_desc->callback = qcom_qpic_bam_dma_done; - bam_txn->last_cmd_desc->callback_param = bam_txn; - - dma_async_issue_pending(nandc->tx_chan); -@@ -1314,7 +1314,7 @@ static int submit_descs(struct qcom_nand - err_unmap_free_desc: - /* - * Unmap the dma sg_list and free the desc allocated by both -- * prepare_bam_async_desc() and prep_adm_dma_desc() functions. -+ * qcom_prepare_bam_async_desc() and qcom_prep_adm_dma_desc() functions. - */ - list_for_each_entry_safe(desc, n, &nandc->desc_list, node) { - list_del(&desc->node); -@@ -1333,10 +1333,10 @@ err_unmap_free_desc: - } - - /* reset the register read buffer for next NAND operation */ --static void clear_read_regs(struct qcom_nand_controller *nandc) -+static void qcom_clear_read_regs(struct qcom_nand_controller *nandc) - { - nandc->reg_read_pos = 0; -- nandc_dev_to_mem(nandc, false); -+ qcom_nandc_dev_to_mem(nandc, false); - } - - /* -@@ -1400,7 +1400,7 @@ static int check_flash_errors(struct qco - struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); - int i; - -- nandc_dev_to_mem(nandc, true); -+ qcom_nandc_dev_to_mem(nandc, true); - - for (i = 0; i < cw_cnt; i++) { - u32 flash = le32_to_cpu(nandc->reg_read_buf[i]); -@@ -1427,13 +1427,13 @@ qcom_nandc_read_cw_raw(struct mtd_info * - nand_read_page_op(chip, page, 0, NULL, 0); - nandc->buf_count = 0; - nandc->buf_start = 0; -- clear_read_regs(nandc); -+ qcom_clear_read_regs(nandc); - host->use_ecc = false; - - if (nandc->props->qpic_version2) - raw_cw = ecc->steps - 1; - -- clear_bam_transaction(nandc); -+ qcom_clear_bam_transaction(nandc); - set_address(host, host->cw_size * cw, page); - update_rw_regs(host, 1, true, raw_cw); - config_nand_page_read(chip); -@@ -1466,18 +1466,18 @@ qcom_nandc_read_cw_raw(struct mtd_info * - - config_nand_cw_read(chip, false, raw_cw); - -- read_data_dma(nandc, reg_off, data_buf, data_size1, 0); -+ qcom_read_data_dma(nandc, reg_off, data_buf, data_size1, 0); - reg_off += data_size1; - -- read_data_dma(nandc, reg_off, oob_buf, oob_size1, 0); -+ qcom_read_data_dma(nandc, reg_off, oob_buf, oob_size1, 0); - reg_off += oob_size1; - -- read_data_dma(nandc, reg_off, data_buf + data_size1, data_size2, 0); -+ qcom_read_data_dma(nandc, reg_off, data_buf + data_size1, data_size2, 0); - reg_off += data_size2; - -- read_data_dma(nandc, reg_off, oob_buf + oob_size1, oob_size2, 0); -+ qcom_read_data_dma(nandc, reg_off, oob_buf + oob_size1, oob_size2, 0); - -- ret = submit_descs(nandc); -+ ret = qcom_submit_descs(nandc); - if (ret) { - dev_err(nandc->dev, "failure to read raw cw %d\n", cw); - return ret; -@@ -1575,7 +1575,7 @@ static int parse_read_errors(struct qcom - u8 *data_buf_start = data_buf, *oob_buf_start = oob_buf; - - buf = (struct read_stats *)nandc->reg_read_buf; -- nandc_dev_to_mem(nandc, true); -+ qcom_nandc_dev_to_mem(nandc, true); - - for (i = 0; i < ecc->steps; i++, buf++) { - u32 flash, buffer, erased_cw; -@@ -1704,8 +1704,8 @@ static int read_page_ecc(struct qcom_nan - config_nand_cw_read(chip, true, i); - - if (data_buf) -- read_data_dma(nandc, FLASH_BUF_ACC, data_buf, -- data_size, 0); -+ qcom_read_data_dma(nandc, FLASH_BUF_ACC, data_buf, -+ data_size, 0); - - /* - * when ecc is enabled, the controller doesn't read the real -@@ -1720,8 +1720,8 @@ static int read_page_ecc(struct qcom_nan - for (j = 0; j < host->bbm_size; j++) - *oob_buf++ = 0xff; - -- read_data_dma(nandc, FLASH_BUF_ACC + data_size, -- oob_buf, oob_size, 0); -+ qcom_read_data_dma(nandc, FLASH_BUF_ACC + data_size, -+ oob_buf, oob_size, 0); - } - - if (data_buf) -@@ -1730,7 +1730,7 @@ static int read_page_ecc(struct qcom_nan - oob_buf += oob_size; - } - -- ret = submit_descs(nandc); -+ ret = qcom_submit_descs(nandc); - if (ret) { - dev_err(nandc->dev, "failure to read page/oob\n"); - return ret; -@@ -1751,7 +1751,7 @@ static int copy_last_cw(struct qcom_nand - int size; - int ret; - -- clear_read_regs(nandc); -+ qcom_clear_read_regs(nandc); - - size = host->use_ecc ? host->cw_data : host->cw_size; - -@@ -1763,9 +1763,9 @@ static int copy_last_cw(struct qcom_nand - - config_nand_single_cw_page_read(chip, host->use_ecc, ecc->steps - 1); - -- read_data_dma(nandc, FLASH_BUF_ACC, nandc->data_buffer, size, 0); -+ qcom_read_data_dma(nandc, FLASH_BUF_ACC, nandc->data_buffer, size, 0); - -- ret = submit_descs(nandc); -+ ret = qcom_submit_descs(nandc); - if (ret) - dev_err(nandc->dev, "failed to copy last codeword\n"); - -@@ -1851,14 +1851,14 @@ static int qcom_nandc_read_page(struct n - nandc->buf_count = 0; - nandc->buf_start = 0; - host->use_ecc = true; -- clear_read_regs(nandc); -+ qcom_clear_read_regs(nandc); - set_address(host, 0, page); - update_rw_regs(host, ecc->steps, true, 0); - - data_buf = buf; - oob_buf = oob_required ? chip->oob_poi : NULL; - -- clear_bam_transaction(nandc); -+ qcom_clear_bam_transaction(nandc); - - return read_page_ecc(host, data_buf, oob_buf, page); - } -@@ -1899,8 +1899,8 @@ static int qcom_nandc_read_oob(struct na - if (host->nr_boot_partitions) - qcom_nandc_codeword_fixup(host, page); - -- clear_read_regs(nandc); -- clear_bam_transaction(nandc); -+ qcom_clear_read_regs(nandc); -+ qcom_clear_bam_transaction(nandc); - - host->use_ecc = true; - set_address(host, 0, page); -@@ -1927,8 +1927,8 @@ static int qcom_nandc_write_page(struct - set_address(host, 0, page); - nandc->buf_count = 0; - nandc->buf_start = 0; -- clear_read_regs(nandc); -- clear_bam_transaction(nandc); -+ qcom_clear_read_regs(nandc); -+ qcom_clear_bam_transaction(nandc); - - data_buf = (u8 *)buf; - oob_buf = chip->oob_poi; -@@ -1949,8 +1949,8 @@ static int qcom_nandc_write_page(struct - oob_size = ecc->bytes; - } - -- write_data_dma(nandc, FLASH_BUF_ACC, data_buf, data_size, -- i == (ecc->steps - 1) ? NAND_BAM_NO_EOT : 0); -+ qcom_write_data_dma(nandc, FLASH_BUF_ACC, data_buf, data_size, -+ i == (ecc->steps - 1) ? NAND_BAM_NO_EOT : 0); - - /* - * when ECC is enabled, we don't really need to write anything -@@ -1962,8 +1962,8 @@ static int qcom_nandc_write_page(struct - if (qcom_nandc_is_last_cw(ecc, i)) { - oob_buf += host->bbm_size; - -- write_data_dma(nandc, FLASH_BUF_ACC + data_size, -- oob_buf, oob_size, 0); -+ qcom_write_data_dma(nandc, FLASH_BUF_ACC + data_size, -+ oob_buf, oob_size, 0); - } - - config_nand_cw_write(chip); -@@ -1972,7 +1972,7 @@ static int qcom_nandc_write_page(struct - oob_buf += oob_size; - } - -- ret = submit_descs(nandc); -+ ret = qcom_submit_descs(nandc); - if (ret) { - dev_err(nandc->dev, "failure to write page\n"); - return ret; -@@ -1997,8 +1997,8 @@ static int qcom_nandc_write_page_raw(str - qcom_nandc_codeword_fixup(host, page); - - nand_prog_page_begin_op(chip, page, 0, NULL, 0); -- clear_read_regs(nandc); -- clear_bam_transaction(nandc); -+ qcom_clear_read_regs(nandc); -+ qcom_clear_bam_transaction(nandc); - - data_buf = (u8 *)buf; - oob_buf = chip->oob_poi; -@@ -2024,28 +2024,28 @@ static int qcom_nandc_write_page_raw(str - oob_size2 = host->ecc_bytes_hw + host->spare_bytes; - } - -- write_data_dma(nandc, reg_off, data_buf, data_size1, -- NAND_BAM_NO_EOT); -+ qcom_write_data_dma(nandc, reg_off, data_buf, data_size1, -+ NAND_BAM_NO_EOT); - reg_off += data_size1; - data_buf += data_size1; - -- write_data_dma(nandc, reg_off, oob_buf, oob_size1, -- NAND_BAM_NO_EOT); -+ qcom_write_data_dma(nandc, reg_off, oob_buf, oob_size1, -+ NAND_BAM_NO_EOT); - reg_off += oob_size1; - oob_buf += oob_size1; - -- write_data_dma(nandc, reg_off, data_buf, data_size2, -- NAND_BAM_NO_EOT); -+ qcom_write_data_dma(nandc, reg_off, data_buf, data_size2, -+ NAND_BAM_NO_EOT); - reg_off += data_size2; - data_buf += data_size2; - -- write_data_dma(nandc, reg_off, oob_buf, oob_size2, 0); -+ qcom_write_data_dma(nandc, reg_off, oob_buf, oob_size2, 0); - oob_buf += oob_size2; - - config_nand_cw_write(chip); - } - -- ret = submit_descs(nandc); -+ ret = qcom_submit_descs(nandc); - if (ret) { - dev_err(nandc->dev, "failure to write raw page\n"); - return ret; -@@ -2075,7 +2075,7 @@ static int qcom_nandc_write_oob(struct n - qcom_nandc_codeword_fixup(host, page); - - host->use_ecc = true; -- clear_bam_transaction(nandc); -+ qcom_clear_bam_transaction(nandc); - - /* calculate the data and oob size for the last codeword/step */ - data_size = ecc->size - ((ecc->steps - 1) << 2); -@@ -2090,11 +2090,11 @@ static int qcom_nandc_write_oob(struct n - update_rw_regs(host, 1, false, 0); - - config_nand_page_write(chip); -- write_data_dma(nandc, FLASH_BUF_ACC, -- nandc->data_buffer, data_size + oob_size, 0); -+ qcom_write_data_dma(nandc, FLASH_BUF_ACC, -+ nandc->data_buffer, data_size + oob_size, 0); - config_nand_cw_write(chip); - -- ret = submit_descs(nandc); -+ ret = qcom_submit_descs(nandc); - if (ret) { - dev_err(nandc->dev, "failure to write oob\n"); - return ret; -@@ -2121,7 +2121,7 @@ static int qcom_nandc_block_bad(struct n - */ - host->use_ecc = false; - -- clear_bam_transaction(nandc); -+ qcom_clear_bam_transaction(nandc); - ret = copy_last_cw(host, page); - if (ret) - goto err; -@@ -2148,8 +2148,8 @@ static int qcom_nandc_block_markbad(stru - struct nand_ecc_ctrl *ecc = &chip->ecc; - int page, ret; - -- clear_read_regs(nandc); -- clear_bam_transaction(nandc); -+ qcom_clear_read_regs(nandc); -+ qcom_clear_bam_transaction(nandc); - - /* - * to mark the BBM as bad, we flash the entire last codeword with 0s. -@@ -2166,11 +2166,11 @@ static int qcom_nandc_block_markbad(stru - update_rw_regs(host, 1, false, ecc->steps - 1); - - config_nand_page_write(chip); -- write_data_dma(nandc, FLASH_BUF_ACC, -- nandc->data_buffer, host->cw_size, 0); -+ qcom_write_data_dma(nandc, FLASH_BUF_ACC, -+ nandc->data_buffer, host->cw_size, 0); - config_nand_cw_write(chip); - -- ret = submit_descs(nandc); -+ ret = qcom_submit_descs(nandc); - if (ret) { - dev_err(nandc->dev, "failure to update BBM\n"); - return ret; -@@ -2410,14 +2410,14 @@ static int qcom_nand_attach_chip(struct - mtd_set_ooblayout(mtd, &qcom_nand_ooblayout_ops); - /* Free the initially allocated BAM transaction for reading the ONFI params */ - if (nandc->props->supports_bam) -- free_bam_transaction(nandc); -+ qcom_free_bam_transaction(nandc); - - nandc->max_cwperpage = max_t(unsigned int, nandc->max_cwperpage, - cwperpage); - - /* Now allocate the BAM transaction based on updated max_cwperpage */ - if (nandc->props->supports_bam) { -- nandc->bam_txn = alloc_bam_transaction(nandc); -+ nandc->bam_txn = qcom_alloc_bam_transaction(nandc); - if (!nandc->bam_txn) { - dev_err(nandc->dev, - "failed to allocate bam transaction\n"); -@@ -2617,7 +2617,7 @@ static int qcom_wait_rdy_poll(struct nan - unsigned long start = jiffies + msecs_to_jiffies(time_ms); - u32 flash; - -- nandc_dev_to_mem(nandc, true); -+ qcom_nandc_dev_to_mem(nandc, true); - - do { - flash = le32_to_cpu(nandc->reg_read_buf[0]); -@@ -2657,23 +2657,23 @@ static int qcom_read_status_exec(struct - nandc->buf_start = 0; - host->use_ecc = false; - -- clear_read_regs(nandc); -- clear_bam_transaction(nandc); -+ qcom_clear_read_regs(nandc); -+ qcom_clear_bam_transaction(nandc); - - nandc->regs->cmd = q_op.cmd_reg; - nandc->regs->exec = cpu_to_le32(1); - -- write_reg_dma(nandc, &nandc->regs->cmd, NAND_FLASH_CMD, 1, NAND_BAM_NEXT_SGL); -- write_reg_dma(nandc, &nandc->regs->exec, NAND_EXEC_CMD, 1, NAND_BAM_NEXT_SGL); -- read_reg_dma(nandc, NAND_FLASH_STATUS, 1, NAND_BAM_NEXT_SGL); -+ qcom_write_reg_dma(nandc, &nandc->regs->cmd, NAND_FLASH_CMD, 1, NAND_BAM_NEXT_SGL); -+ qcom_write_reg_dma(nandc, &nandc->regs->exec, NAND_EXEC_CMD, 1, NAND_BAM_NEXT_SGL); -+ qcom_read_reg_dma(nandc, NAND_FLASH_STATUS, 1, NAND_BAM_NEXT_SGL); - -- ret = submit_descs(nandc); -+ ret = qcom_submit_descs(nandc); - if (ret) { - dev_err(nandc->dev, "failure in submitting status descriptor\n"); - goto err_out; - } - -- nandc_dev_to_mem(nandc, true); -+ qcom_nandc_dev_to_mem(nandc, true); - - for (i = 0; i < num_cw; i++) { - flash_status = le32_to_cpu(nandc->reg_read_buf[i]); -@@ -2714,8 +2714,8 @@ static int qcom_read_id_type_exec(struct - nandc->buf_start = 0; - host->use_ecc = false; - -- clear_read_regs(nandc); -- clear_bam_transaction(nandc); -+ qcom_clear_read_regs(nandc); -+ qcom_clear_bam_transaction(nandc); - - nandc->regs->cmd = q_op.cmd_reg; - nandc->regs->addr0 = q_op.addr1_reg; -@@ -2723,12 +2723,12 @@ static int qcom_read_id_type_exec(struct - nandc->regs->chip_sel = cpu_to_le32(nandc->props->supports_bam ? 0 : DM_EN); - nandc->regs->exec = cpu_to_le32(1); - -- write_reg_dma(nandc, &nandc->regs->cmd, NAND_FLASH_CMD, 4, NAND_BAM_NEXT_SGL); -- write_reg_dma(nandc, &nandc->regs->exec, NAND_EXEC_CMD, 1, NAND_BAM_NEXT_SGL); -+ qcom_write_reg_dma(nandc, &nandc->regs->cmd, NAND_FLASH_CMD, 4, NAND_BAM_NEXT_SGL); -+ qcom_write_reg_dma(nandc, &nandc->regs->exec, NAND_EXEC_CMD, 1, NAND_BAM_NEXT_SGL); - -- read_reg_dma(nandc, NAND_READ_ID, 1, NAND_BAM_NEXT_SGL); -+ qcom_read_reg_dma(nandc, NAND_READ_ID, 1, NAND_BAM_NEXT_SGL); - -- ret = submit_descs(nandc); -+ ret = qcom_submit_descs(nandc); - if (ret) { - dev_err(nandc->dev, "failure in submitting read id descriptor\n"); - goto err_out; -@@ -2738,7 +2738,7 @@ static int qcom_read_id_type_exec(struct - op_id = q_op.data_instr_idx; - len = nand_subop_get_data_len(subop, op_id); - -- nandc_dev_to_mem(nandc, true); -+ qcom_nandc_dev_to_mem(nandc, true); - memcpy(instr->ctx.data.buf.in, nandc->reg_read_buf, len); - - err_out: -@@ -2774,20 +2774,20 @@ static int qcom_misc_cmd_type_exec(struc - nandc->buf_start = 0; - host->use_ecc = false; - -- clear_read_regs(nandc); -- clear_bam_transaction(nandc); -+ qcom_clear_read_regs(nandc); -+ qcom_clear_bam_transaction(nandc); - - nandc->regs->cmd = q_op.cmd_reg; - nandc->regs->exec = cpu_to_le32(1); - -- write_reg_dma(nandc, &nandc->regs->cmd, NAND_FLASH_CMD, instrs, NAND_BAM_NEXT_SGL); -+ qcom_write_reg_dma(nandc, &nandc->regs->cmd, NAND_FLASH_CMD, instrs, NAND_BAM_NEXT_SGL); - if (q_op.cmd_reg == cpu_to_le32(OP_BLOCK_ERASE)) -- write_reg_dma(nandc, &nandc->regs->cfg0, NAND_DEV0_CFG0, 2, NAND_BAM_NEXT_SGL); -+ qcom_write_reg_dma(nandc, &nandc->regs->cfg0, NAND_DEV0_CFG0, 2, NAND_BAM_NEXT_SGL); - -- write_reg_dma(nandc, &nandc->regs->exec, NAND_EXEC_CMD, 1, NAND_BAM_NEXT_SGL); -- read_reg_dma(nandc, NAND_FLASH_STATUS, 1, NAND_BAM_NEXT_SGL); -+ qcom_write_reg_dma(nandc, &nandc->regs->exec, NAND_EXEC_CMD, 1, NAND_BAM_NEXT_SGL); -+ qcom_read_reg_dma(nandc, NAND_FLASH_STATUS, 1, NAND_BAM_NEXT_SGL); - -- ret = submit_descs(nandc); -+ ret = qcom_submit_descs(nandc); - if (ret) { - dev_err(nandc->dev, "failure in submitting misc descriptor\n"); - goto err_out; -@@ -2825,8 +2825,8 @@ static int qcom_param_page_type_exec(str - nandc->buf_count = 0; - nandc->buf_start = 0; - host->use_ecc = false; -- clear_read_regs(nandc); -- clear_bam_transaction(nandc); -+ qcom_clear_read_regs(nandc); -+ qcom_clear_bam_transaction(nandc); - - nandc->regs->cmd = q_op.cmd_reg; - nandc->regs->addr0 = 0; -@@ -2872,8 +2872,8 @@ static int qcom_param_page_type_exec(str - nandc_set_read_loc_first(chip, reg_base, 0, len, 1); - - if (!nandc->props->qpic_version2) { -- write_reg_dma(nandc, &nandc->regs->vld, NAND_DEV_CMD_VLD, 1, 0); -- write_reg_dma(nandc, &nandc->regs->cmd1, NAND_DEV_CMD1, 1, NAND_BAM_NEXT_SGL); -+ qcom_write_reg_dma(nandc, &nandc->regs->vld, NAND_DEV_CMD_VLD, 1, 0); -+ qcom_write_reg_dma(nandc, &nandc->regs->cmd1, NAND_DEV_CMD1, 1, NAND_BAM_NEXT_SGL); - } - - nandc->buf_count = 512; -@@ -2881,17 +2881,17 @@ static int qcom_param_page_type_exec(str - - config_nand_single_cw_page_read(chip, false, 0); - -- read_data_dma(nandc, FLASH_BUF_ACC, nandc->data_buffer, -- nandc->buf_count, 0); -+ qcom_read_data_dma(nandc, FLASH_BUF_ACC, nandc->data_buffer, -+ nandc->buf_count, 0); - - /* restore CMD1 and VLD regs */ - if (!nandc->props->qpic_version2) { -- write_reg_dma(nandc, &nandc->regs->orig_cmd1, NAND_DEV_CMD1_RESTORE, 1, 0); -- write_reg_dma(nandc, &nandc->regs->orig_vld, NAND_DEV_CMD_VLD_RESTORE, 1, -- NAND_BAM_NEXT_SGL); -+ qcom_write_reg_dma(nandc, &nandc->regs->orig_cmd1, NAND_DEV_CMD1_RESTORE, 1, 0); -+ qcom_write_reg_dma(nandc, &nandc->regs->orig_vld, NAND_DEV_CMD_VLD_RESTORE, 1, -+ NAND_BAM_NEXT_SGL); - } - -- ret = submit_descs(nandc); -+ ret = qcom_submit_descs(nandc); - if (ret) { - dev_err(nandc->dev, "failure in submitting param page descriptor\n"); - goto err_out; -@@ -3075,7 +3075,7 @@ static int qcom_nandc_alloc(struct qcom_ - * maximum codeword size - */ - nandc->max_cwperpage = 1; -- nandc->bam_txn = alloc_bam_transaction(nandc); -+ nandc->bam_txn = qcom_alloc_bam_transaction(nandc); - if (!nandc->bam_txn) { - dev_err(nandc->dev, - "failed to allocate bam transaction\n"); diff --git a/target/linux/generic/backport-6.18/410-03-v6.14-mtd-nand-Add-qpic_common-API-file.patch b/target/linux/generic/backport-6.18/410-03-v6.14-mtd-nand-Add-qpic_common-API-file.patch deleted file mode 100644 index 9272f98862..0000000000 --- a/target/linux/generic/backport-6.18/410-03-v6.14-mtd-nand-Add-qpic_common-API-file.patch +++ /dev/null @@ -1,2436 +0,0 @@ -From fdf3ee5c6e5278dab4f60b998b47ed2d510bf80f Mon Sep 17 00:00:00 2001 -From: Md Sadre Alam -Date: Wed, 20 Nov 2024 14:45:02 +0530 -Subject: [PATCH 3/4] mtd: nand: Add qpic_common API file - -Add qpic_common.c file which hold all the common -qpic APIs which will be used by both qpic raw nand -driver and qpic spi nand driver. - -Signed-off-by: Md Sadre Alam -Signed-off-by: Miquel Raynal ---- - drivers/mtd/nand/Makefile | 2 +- - drivers/mtd/nand/qpic_common.c | 759 ++++++++++++++++++ - drivers/mtd/nand/raw/qcom_nandc.c | 1092 +------------------------- - include/linux/mtd/nand-qpic-common.h | 468 +++++++++++ - 4 files changed, 1240 insertions(+), 1081 deletions(-) - create mode 100644 drivers/mtd/nand/qpic_common.c - create mode 100644 include/linux/mtd/nand-qpic-common.h - ---- a/drivers/mtd/nand/Makefile -+++ b/drivers/mtd/nand/Makefile -@@ -3,7 +3,7 @@ - nandcore-objs := core.o bbt.o - obj-$(CONFIG_MTD_NAND_CORE) += nandcore.o - obj-$(CONFIG_MTD_NAND_ECC_MEDIATEK) += ecc-mtk.o -- -+obj-$(CONFIG_MTD_NAND_QCOM) += qpic_common.o - obj-y += onenand/ - obj-y += raw/ - obj-y += spi/ ---- /dev/null -+++ b/drivers/mtd/nand/qpic_common.c -@@ -0,0 +1,759 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* -+ * Copyright (c) 2016, The Linux Foundation. All rights reserved. -+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/** -+ * qcom_free_bam_transaction() - Frees the BAM transaction memory -+ * @nandc: qpic nand controller -+ * -+ * This function frees the bam transaction memory -+ */ -+void qcom_free_bam_transaction(struct qcom_nand_controller *nandc) -+{ -+ struct bam_transaction *bam_txn = nandc->bam_txn; -+ -+ kfree(bam_txn); -+} -+EXPORT_SYMBOL(qcom_free_bam_transaction); -+ -+/** -+ * qcom_alloc_bam_transaction() - allocate BAM transaction -+ * @nandc: qpic nand controller -+ * -+ * This function will allocate and initialize the BAM transaction structure -+ */ -+struct bam_transaction * -+qcom_alloc_bam_transaction(struct qcom_nand_controller *nandc) -+{ -+ struct bam_transaction *bam_txn; -+ size_t bam_txn_size; -+ unsigned int num_cw = nandc->max_cwperpage; -+ void *bam_txn_buf; -+ -+ bam_txn_size = -+ sizeof(*bam_txn) + num_cw * -+ ((sizeof(*bam_txn->bam_ce) * QPIC_PER_CW_CMD_ELEMENTS) + -+ (sizeof(*bam_txn->cmd_sgl) * QPIC_PER_CW_CMD_SGL) + -+ (sizeof(*bam_txn->data_sgl) * QPIC_PER_CW_DATA_SGL)); -+ -+ bam_txn_buf = kzalloc(bam_txn_size, GFP_KERNEL); -+ if (!bam_txn_buf) -+ return NULL; -+ -+ bam_txn = bam_txn_buf; -+ bam_txn_buf += sizeof(*bam_txn); -+ -+ bam_txn->bam_ce = bam_txn_buf; -+ bam_txn_buf += -+ sizeof(*bam_txn->bam_ce) * QPIC_PER_CW_CMD_ELEMENTS * num_cw; -+ -+ bam_txn->cmd_sgl = bam_txn_buf; -+ bam_txn_buf += -+ sizeof(*bam_txn->cmd_sgl) * QPIC_PER_CW_CMD_SGL * num_cw; -+ -+ bam_txn->data_sgl = bam_txn_buf; -+ -+ init_completion(&bam_txn->txn_done); -+ -+ return bam_txn; -+} -+EXPORT_SYMBOL(qcom_alloc_bam_transaction); -+ -+/** -+ * qcom_clear_bam_transaction() - Clears the BAM transaction -+ * @nandc: qpic nand controller -+ * -+ * This function will clear the BAM transaction indexes. -+ */ -+void qcom_clear_bam_transaction(struct qcom_nand_controller *nandc) -+{ -+ struct bam_transaction *bam_txn = nandc->bam_txn; -+ -+ if (!nandc->props->supports_bam) -+ return; -+ -+ memset(&bam_txn->bam_ce_pos, 0, sizeof(u32) * 8); -+ bam_txn->last_data_desc = NULL; -+ -+ sg_init_table(bam_txn->cmd_sgl, nandc->max_cwperpage * -+ QPIC_PER_CW_CMD_SGL); -+ sg_init_table(bam_txn->data_sgl, nandc->max_cwperpage * -+ QPIC_PER_CW_DATA_SGL); -+ -+ reinit_completion(&bam_txn->txn_done); -+} -+EXPORT_SYMBOL(qcom_clear_bam_transaction); -+ -+/** -+ * qcom_qpic_bam_dma_done() - Callback for DMA descriptor completion -+ * @data: data pointer -+ * -+ * This function is a callback for DMA descriptor completion -+ */ -+void qcom_qpic_bam_dma_done(void *data) -+{ -+ struct bam_transaction *bam_txn = data; -+ -+ complete(&bam_txn->txn_done); -+} -+EXPORT_SYMBOL(qcom_qpic_bam_dma_done); -+ -+/** -+ * qcom_nandc_dev_to_mem() - Check for dma sync for cpu or device -+ * @nandc: qpic nand controller -+ * @is_cpu: cpu or Device -+ * -+ * This function will check for dma sync for cpu or device -+ */ -+inline void qcom_nandc_dev_to_mem(struct qcom_nand_controller *nandc, bool is_cpu) -+{ -+ if (!nandc->props->supports_bam) -+ return; -+ -+ if (is_cpu) -+ dma_sync_single_for_cpu(nandc->dev, nandc->reg_read_dma, -+ MAX_REG_RD * -+ sizeof(*nandc->reg_read_buf), -+ DMA_FROM_DEVICE); -+ else -+ dma_sync_single_for_device(nandc->dev, nandc->reg_read_dma, -+ MAX_REG_RD * -+ sizeof(*nandc->reg_read_buf), -+ DMA_FROM_DEVICE); -+} -+EXPORT_SYMBOL(qcom_nandc_dev_to_mem); -+ -+/** -+ * qcom_prepare_bam_async_desc() - Prepare DMA descriptor -+ * @nandc: qpic nand controller -+ * @chan: dma channel -+ * @flags: flags to control DMA descriptor preparation -+ * -+ * This function maps the scatter gather list for DMA transfer and forms the -+ * DMA descriptor for BAM.This descriptor will be added in the NAND DMA -+ * descriptor queue which will be submitted to DMA engine. -+ */ -+int qcom_prepare_bam_async_desc(struct qcom_nand_controller *nandc, -+ struct dma_chan *chan, unsigned long flags) -+{ -+ struct desc_info *desc; -+ struct scatterlist *sgl; -+ unsigned int sgl_cnt; -+ int ret; -+ struct bam_transaction *bam_txn = nandc->bam_txn; -+ enum dma_transfer_direction dir_eng; -+ struct dma_async_tx_descriptor *dma_desc; -+ -+ desc = kzalloc(sizeof(*desc), GFP_KERNEL); -+ if (!desc) -+ return -ENOMEM; -+ -+ if (chan == nandc->cmd_chan) { -+ sgl = &bam_txn->cmd_sgl[bam_txn->cmd_sgl_start]; -+ sgl_cnt = bam_txn->cmd_sgl_pos - bam_txn->cmd_sgl_start; -+ bam_txn->cmd_sgl_start = bam_txn->cmd_sgl_pos; -+ dir_eng = DMA_MEM_TO_DEV; -+ desc->dir = DMA_TO_DEVICE; -+ } else if (chan == nandc->tx_chan) { -+ sgl = &bam_txn->data_sgl[bam_txn->tx_sgl_start]; -+ sgl_cnt = bam_txn->tx_sgl_pos - bam_txn->tx_sgl_start; -+ bam_txn->tx_sgl_start = bam_txn->tx_sgl_pos; -+ dir_eng = DMA_MEM_TO_DEV; -+ desc->dir = DMA_TO_DEVICE; -+ } else { -+ sgl = &bam_txn->data_sgl[bam_txn->rx_sgl_start]; -+ sgl_cnt = bam_txn->rx_sgl_pos - bam_txn->rx_sgl_start; -+ bam_txn->rx_sgl_start = bam_txn->rx_sgl_pos; -+ dir_eng = DMA_DEV_TO_MEM; -+ desc->dir = DMA_FROM_DEVICE; -+ } -+ -+ sg_mark_end(sgl + sgl_cnt - 1); -+ ret = dma_map_sg(nandc->dev, sgl, sgl_cnt, desc->dir); -+ if (ret == 0) { -+ dev_err(nandc->dev, "failure in mapping desc\n"); -+ kfree(desc); -+ return -ENOMEM; -+ } -+ -+ desc->sgl_cnt = sgl_cnt; -+ desc->bam_sgl = sgl; -+ -+ dma_desc = dmaengine_prep_slave_sg(chan, sgl, sgl_cnt, dir_eng, -+ flags); -+ -+ if (!dma_desc) { -+ dev_err(nandc->dev, "failure in prep desc\n"); -+ dma_unmap_sg(nandc->dev, sgl, sgl_cnt, desc->dir); -+ kfree(desc); -+ return -EINVAL; -+ } -+ -+ desc->dma_desc = dma_desc; -+ -+ /* update last data/command descriptor */ -+ if (chan == nandc->cmd_chan) -+ bam_txn->last_cmd_desc = dma_desc; -+ else -+ bam_txn->last_data_desc = dma_desc; -+ -+ list_add_tail(&desc->node, &nandc->desc_list); -+ -+ return 0; -+} -+EXPORT_SYMBOL(qcom_prepare_bam_async_desc); -+ -+/** -+ * qcom_prep_bam_dma_desc_cmd() - Prepares the command descriptor for BAM DMA -+ * @nandc: qpic nand controller -+ * @read: read or write type -+ * @reg_off: offset within the controller's data buffer -+ * @vaddr: virtual address of the buffer we want to write to -+ * @size: DMA transaction size in bytes -+ * @flags: flags to control DMA descriptor preparation -+ * -+ * This function will prepares the command descriptor for BAM DMA -+ * which will be used for NAND register reads and writes. -+ */ -+int qcom_prep_bam_dma_desc_cmd(struct qcom_nand_controller *nandc, bool read, -+ int reg_off, const void *vaddr, -+ int size, unsigned int flags) -+{ -+ int bam_ce_size; -+ int i, ret; -+ struct bam_cmd_element *bam_ce_buffer; -+ struct bam_transaction *bam_txn = nandc->bam_txn; -+ -+ bam_ce_buffer = &bam_txn->bam_ce[bam_txn->bam_ce_pos]; -+ -+ /* fill the command desc */ -+ for (i = 0; i < size; i++) { -+ if (read) -+ bam_prep_ce(&bam_ce_buffer[i], -+ nandc_reg_phys(nandc, reg_off + 4 * i), -+ BAM_READ_COMMAND, -+ reg_buf_dma_addr(nandc, -+ (__le32 *)vaddr + i)); -+ else -+ bam_prep_ce_le32(&bam_ce_buffer[i], -+ nandc_reg_phys(nandc, reg_off + 4 * i), -+ BAM_WRITE_COMMAND, -+ *((__le32 *)vaddr + i)); -+ } -+ -+ bam_txn->bam_ce_pos += size; -+ -+ /* use the separate sgl after this command */ -+ if (flags & NAND_BAM_NEXT_SGL) { -+ bam_ce_buffer = &bam_txn->bam_ce[bam_txn->bam_ce_start]; -+ bam_ce_size = (bam_txn->bam_ce_pos - -+ bam_txn->bam_ce_start) * -+ sizeof(struct bam_cmd_element); -+ sg_set_buf(&bam_txn->cmd_sgl[bam_txn->cmd_sgl_pos], -+ bam_ce_buffer, bam_ce_size); -+ bam_txn->cmd_sgl_pos++; -+ bam_txn->bam_ce_start = bam_txn->bam_ce_pos; -+ -+ if (flags & NAND_BAM_NWD) { -+ ret = qcom_prepare_bam_async_desc(nandc, nandc->cmd_chan, -+ DMA_PREP_FENCE | DMA_PREP_CMD); -+ if (ret) -+ return ret; -+ } -+ } -+ -+ return 0; -+} -+EXPORT_SYMBOL(qcom_prep_bam_dma_desc_cmd); -+ -+/** -+ * qcom_prep_bam_dma_desc_data() - Prepares the data descriptor for BAM DMA -+ * @nandc: qpic nand controller -+ * @read: read or write type -+ * @vaddr: virtual address of the buffer we want to write to -+ * @size: DMA transaction size in bytes -+ * @flags: flags to control DMA descriptor preparation -+ * -+ * This function will prepares the data descriptor for BAM DMA which -+ * will be used for NAND data reads and writes. -+ */ -+int qcom_prep_bam_dma_desc_data(struct qcom_nand_controller *nandc, bool read, -+ const void *vaddr, int size, unsigned int flags) -+{ -+ int ret; -+ struct bam_transaction *bam_txn = nandc->bam_txn; -+ -+ if (read) { -+ sg_set_buf(&bam_txn->data_sgl[bam_txn->rx_sgl_pos], -+ vaddr, size); -+ bam_txn->rx_sgl_pos++; -+ } else { -+ sg_set_buf(&bam_txn->data_sgl[bam_txn->tx_sgl_pos], -+ vaddr, size); -+ bam_txn->tx_sgl_pos++; -+ -+ /* -+ * BAM will only set EOT for DMA_PREP_INTERRUPT so if this flag -+ * is not set, form the DMA descriptor -+ */ -+ if (!(flags & NAND_BAM_NO_EOT)) { -+ ret = qcom_prepare_bam_async_desc(nandc, nandc->tx_chan, -+ DMA_PREP_INTERRUPT); -+ if (ret) -+ return ret; -+ } -+ } -+ -+ return 0; -+} -+EXPORT_SYMBOL(qcom_prep_bam_dma_desc_data); -+ -+/** -+ * qcom_prep_adm_dma_desc() - Prepare descriptor for adma -+ * @nandc: qpic nand controller -+ * @read: read or write type -+ * @reg_off: offset within the controller's data buffer -+ * @vaddr: virtual address of the buffer we want to write to -+ * @size: adm dma transaction size in bytes -+ * @flow_control: flow controller -+ * -+ * This function will prepare descriptor for adma -+ */ -+int qcom_prep_adm_dma_desc(struct qcom_nand_controller *nandc, bool read, -+ int reg_off, const void *vaddr, int size, -+ bool flow_control) -+{ -+ struct qcom_adm_peripheral_config periph_conf = {}; -+ struct dma_async_tx_descriptor *dma_desc; -+ struct dma_slave_config slave_conf = {0}; -+ enum dma_transfer_direction dir_eng; -+ struct desc_info *desc; -+ struct scatterlist *sgl; -+ int ret; -+ -+ desc = kzalloc(sizeof(*desc), GFP_KERNEL); -+ if (!desc) -+ return -ENOMEM; -+ -+ sgl = &desc->adm_sgl; -+ -+ sg_init_one(sgl, vaddr, size); -+ -+ if (read) { -+ dir_eng = DMA_DEV_TO_MEM; -+ desc->dir = DMA_FROM_DEVICE; -+ } else { -+ dir_eng = DMA_MEM_TO_DEV; -+ desc->dir = DMA_TO_DEVICE; -+ } -+ -+ ret = dma_map_sg(nandc->dev, sgl, 1, desc->dir); -+ if (!ret) { -+ ret = -ENOMEM; -+ goto err; -+ } -+ -+ slave_conf.device_fc = flow_control; -+ if (read) { -+ slave_conf.src_maxburst = 16; -+ slave_conf.src_addr = nandc->base_dma + reg_off; -+ if (nandc->data_crci) { -+ periph_conf.crci = nandc->data_crci; -+ slave_conf.peripheral_config = &periph_conf; -+ slave_conf.peripheral_size = sizeof(periph_conf); -+ } -+ } else { -+ slave_conf.dst_maxburst = 16; -+ slave_conf.dst_addr = nandc->base_dma + reg_off; -+ if (nandc->cmd_crci) { -+ periph_conf.crci = nandc->cmd_crci; -+ slave_conf.peripheral_config = &periph_conf; -+ slave_conf.peripheral_size = sizeof(periph_conf); -+ } -+ } -+ -+ ret = dmaengine_slave_config(nandc->chan, &slave_conf); -+ if (ret) { -+ dev_err(nandc->dev, "failed to configure dma channel\n"); -+ goto err; -+ } -+ -+ dma_desc = dmaengine_prep_slave_sg(nandc->chan, sgl, 1, dir_eng, 0); -+ if (!dma_desc) { -+ dev_err(nandc->dev, "failed to prepare desc\n"); -+ ret = -EINVAL; -+ goto err; -+ } -+ -+ desc->dma_desc = dma_desc; -+ -+ list_add_tail(&desc->node, &nandc->desc_list); -+ -+ return 0; -+err: -+ kfree(desc); -+ -+ return ret; -+} -+EXPORT_SYMBOL(qcom_prep_adm_dma_desc); -+ -+/** -+ * qcom_read_reg_dma() - read a given number of registers to the reg_read_buf pointer -+ * @nandc: qpic nand controller -+ * @first: offset of the first register in the contiguous block -+ * @num_regs: number of registers to read -+ * @flags: flags to control DMA descriptor preparation -+ * -+ * This function will prepares a descriptor to read a given number of -+ * contiguous registers to the reg_read_buf pointer. -+ */ -+int qcom_read_reg_dma(struct qcom_nand_controller *nandc, int first, -+ int num_regs, unsigned int flags) -+{ -+ bool flow_control = false; -+ void *vaddr; -+ -+ vaddr = nandc->reg_read_buf + nandc->reg_read_pos; -+ nandc->reg_read_pos += num_regs; -+ -+ if (first == NAND_DEV_CMD_VLD || first == NAND_DEV_CMD1) -+ first = dev_cmd_reg_addr(nandc, first); -+ -+ if (nandc->props->supports_bam) -+ return qcom_prep_bam_dma_desc_cmd(nandc, true, first, vaddr, -+ num_regs, flags); -+ -+ if (first == NAND_READ_ID || first == NAND_FLASH_STATUS) -+ flow_control = true; -+ -+ return qcom_prep_adm_dma_desc(nandc, true, first, vaddr, -+ num_regs * sizeof(u32), flow_control); -+} -+EXPORT_SYMBOL(qcom_read_reg_dma); -+ -+/** -+ * qcom_write_reg_dma() - write a given number of registers -+ * @nandc: qpic nand controller -+ * @vaddr: contiguous memory from where register value will -+ * be written -+ * @first: offset of the first register in the contiguous block -+ * @num_regs: number of registers to write -+ * @flags: flags to control DMA descriptor preparation -+ * -+ * This function will prepares a descriptor to write a given number of -+ * contiguous registers -+ */ -+int qcom_write_reg_dma(struct qcom_nand_controller *nandc, __le32 *vaddr, -+ int first, int num_regs, unsigned int flags) -+{ -+ bool flow_control = false; -+ -+ if (first == NAND_EXEC_CMD) -+ flags |= NAND_BAM_NWD; -+ -+ if (first == NAND_DEV_CMD1_RESTORE || first == NAND_DEV_CMD1) -+ first = dev_cmd_reg_addr(nandc, NAND_DEV_CMD1); -+ -+ if (first == NAND_DEV_CMD_VLD_RESTORE || first == NAND_DEV_CMD_VLD) -+ first = dev_cmd_reg_addr(nandc, NAND_DEV_CMD_VLD); -+ -+ if (nandc->props->supports_bam) -+ return qcom_prep_bam_dma_desc_cmd(nandc, false, first, vaddr, -+ num_regs, flags); -+ -+ if (first == NAND_FLASH_CMD) -+ flow_control = true; -+ -+ return qcom_prep_adm_dma_desc(nandc, false, first, vaddr, -+ num_regs * sizeof(u32), flow_control); -+} -+EXPORT_SYMBOL(qcom_write_reg_dma); -+ -+/** -+ * qcom_read_data_dma() - transfer data -+ * @nandc: qpic nand controller -+ * @reg_off: offset within the controller's data buffer -+ * @vaddr: virtual address of the buffer we want to write to -+ * @size: DMA transaction size in bytes -+ * @flags: flags to control DMA descriptor preparation -+ * -+ * This function will prepares a DMA descriptor to transfer data from the -+ * controller's internal buffer to the buffer 'vaddr' -+ */ -+int qcom_read_data_dma(struct qcom_nand_controller *nandc, int reg_off, -+ const u8 *vaddr, int size, unsigned int flags) -+{ -+ if (nandc->props->supports_bam) -+ return qcom_prep_bam_dma_desc_data(nandc, true, vaddr, size, flags); -+ -+ return qcom_prep_adm_dma_desc(nandc, true, reg_off, vaddr, size, false); -+} -+EXPORT_SYMBOL(qcom_read_data_dma); -+ -+/** -+ * qcom_write_data_dma() - transfer data -+ * @nandc: qpic nand controller -+ * @reg_off: offset within the controller's data buffer -+ * @vaddr: virtual address of the buffer we want to read from -+ * @size: DMA transaction size in bytes -+ * @flags: flags to control DMA descriptor preparation -+ * -+ * This function will prepares a DMA descriptor to transfer data from -+ * 'vaddr' to the controller's internal buffer -+ */ -+int qcom_write_data_dma(struct qcom_nand_controller *nandc, int reg_off, -+ const u8 *vaddr, int size, unsigned int flags) -+{ -+ if (nandc->props->supports_bam) -+ return qcom_prep_bam_dma_desc_data(nandc, false, vaddr, size, flags); -+ -+ return qcom_prep_adm_dma_desc(nandc, false, reg_off, vaddr, size, false); -+} -+EXPORT_SYMBOL(qcom_write_data_dma); -+ -+/** -+ * qcom_submit_descs() - submit dma descriptor -+ * @nandc: qpic nand controller -+ * -+ * This function will submit all the prepared dma descriptor -+ * cmd or data descriptor -+ */ -+int qcom_submit_descs(struct qcom_nand_controller *nandc) -+{ -+ struct desc_info *desc, *n; -+ dma_cookie_t cookie = 0; -+ struct bam_transaction *bam_txn = nandc->bam_txn; -+ int ret = 0; -+ -+ if (nandc->props->supports_bam) { -+ if (bam_txn->rx_sgl_pos > bam_txn->rx_sgl_start) { -+ ret = qcom_prepare_bam_async_desc(nandc, nandc->rx_chan, 0); -+ if (ret) -+ goto err_unmap_free_desc; -+ } -+ -+ if (bam_txn->tx_sgl_pos > bam_txn->tx_sgl_start) { -+ ret = qcom_prepare_bam_async_desc(nandc, nandc->tx_chan, -+ DMA_PREP_INTERRUPT); -+ if (ret) -+ goto err_unmap_free_desc; -+ } -+ -+ if (bam_txn->cmd_sgl_pos > bam_txn->cmd_sgl_start) { -+ ret = qcom_prepare_bam_async_desc(nandc, nandc->cmd_chan, -+ DMA_PREP_CMD); -+ if (ret) -+ goto err_unmap_free_desc; -+ } -+ } -+ -+ list_for_each_entry(desc, &nandc->desc_list, node) -+ cookie = dmaengine_submit(desc->dma_desc); -+ -+ if (nandc->props->supports_bam) { -+ bam_txn->last_cmd_desc->callback = qcom_qpic_bam_dma_done; -+ bam_txn->last_cmd_desc->callback_param = bam_txn; -+ -+ dma_async_issue_pending(nandc->tx_chan); -+ dma_async_issue_pending(nandc->rx_chan); -+ dma_async_issue_pending(nandc->cmd_chan); -+ -+ if (!wait_for_completion_timeout(&bam_txn->txn_done, -+ QPIC_NAND_COMPLETION_TIMEOUT)) -+ ret = -ETIMEDOUT; -+ } else { -+ if (dma_sync_wait(nandc->chan, cookie) != DMA_COMPLETE) -+ ret = -ETIMEDOUT; -+ } -+ -+err_unmap_free_desc: -+ /* -+ * Unmap the dma sg_list and free the desc allocated by both -+ * qcom_prepare_bam_async_desc() and qcom_prep_adm_dma_desc() functions. -+ */ -+ list_for_each_entry_safe(desc, n, &nandc->desc_list, node) { -+ list_del(&desc->node); -+ -+ if (nandc->props->supports_bam) -+ dma_unmap_sg(nandc->dev, desc->bam_sgl, -+ desc->sgl_cnt, desc->dir); -+ else -+ dma_unmap_sg(nandc->dev, &desc->adm_sgl, 1, -+ desc->dir); -+ -+ kfree(desc); -+ } -+ -+ return ret; -+} -+EXPORT_SYMBOL(qcom_submit_descs); -+ -+/** -+ * qcom_clear_read_regs() - reset the read register buffer -+ * @nandc: qpic nand controller -+ * -+ * This function reset the register read buffer for next NAND operation -+ */ -+void qcom_clear_read_regs(struct qcom_nand_controller *nandc) -+{ -+ nandc->reg_read_pos = 0; -+ qcom_nandc_dev_to_mem(nandc, false); -+} -+EXPORT_SYMBOL(qcom_clear_read_regs); -+ -+/** -+ * qcom_nandc_unalloc() - unallocate qpic nand controller -+ * @nandc: qpic nand controller -+ * -+ * This function will unallocate memory alloacted for qpic nand controller -+ */ -+void qcom_nandc_unalloc(struct qcom_nand_controller *nandc) -+{ -+ if (nandc->props->supports_bam) { -+ if (!dma_mapping_error(nandc->dev, nandc->reg_read_dma)) -+ dma_unmap_single(nandc->dev, nandc->reg_read_dma, -+ MAX_REG_RD * -+ sizeof(*nandc->reg_read_buf), -+ DMA_FROM_DEVICE); -+ -+ if (nandc->tx_chan) -+ dma_release_channel(nandc->tx_chan); -+ -+ if (nandc->rx_chan) -+ dma_release_channel(nandc->rx_chan); -+ -+ if (nandc->cmd_chan) -+ dma_release_channel(nandc->cmd_chan); -+ } else { -+ if (nandc->chan) -+ dma_release_channel(nandc->chan); -+ } -+} -+EXPORT_SYMBOL(qcom_nandc_unalloc); -+ -+/** -+ * qcom_nandc_alloc() - Allocate qpic nand controller -+ * @nandc: qpic nand controller -+ * -+ * This function will allocate memory for qpic nand controller -+ */ -+int qcom_nandc_alloc(struct qcom_nand_controller *nandc) -+{ -+ int ret; -+ -+ ret = dma_set_coherent_mask(nandc->dev, DMA_BIT_MASK(32)); -+ if (ret) { -+ dev_err(nandc->dev, "failed to set DMA mask\n"); -+ return ret; -+ } -+ -+ /* -+ * we use the internal buffer for reading ONFI params, reading small -+ * data like ID and status, and preforming read-copy-write operations -+ * when writing to a codeword partially. 532 is the maximum possible -+ * size of a codeword for our nand controller -+ */ -+ nandc->buf_size = 532; -+ -+ nandc->data_buffer = devm_kzalloc(nandc->dev, nandc->buf_size, GFP_KERNEL); -+ if (!nandc->data_buffer) -+ return -ENOMEM; -+ -+ nandc->regs = devm_kzalloc(nandc->dev, sizeof(*nandc->regs), GFP_KERNEL); -+ if (!nandc->regs) -+ return -ENOMEM; -+ -+ nandc->reg_read_buf = devm_kcalloc(nandc->dev, MAX_REG_RD, -+ sizeof(*nandc->reg_read_buf), -+ GFP_KERNEL); -+ if (!nandc->reg_read_buf) -+ return -ENOMEM; -+ -+ if (nandc->props->supports_bam) { -+ nandc->reg_read_dma = -+ dma_map_single(nandc->dev, nandc->reg_read_buf, -+ MAX_REG_RD * -+ sizeof(*nandc->reg_read_buf), -+ DMA_FROM_DEVICE); -+ if (dma_mapping_error(nandc->dev, nandc->reg_read_dma)) { -+ dev_err(nandc->dev, "failed to DMA MAP reg buffer\n"); -+ return -EIO; -+ } -+ -+ nandc->tx_chan = dma_request_chan(nandc->dev, "tx"); -+ if (IS_ERR(nandc->tx_chan)) { -+ ret = PTR_ERR(nandc->tx_chan); -+ nandc->tx_chan = NULL; -+ dev_err_probe(nandc->dev, ret, -+ "tx DMA channel request failed\n"); -+ goto unalloc; -+ } -+ -+ nandc->rx_chan = dma_request_chan(nandc->dev, "rx"); -+ if (IS_ERR(nandc->rx_chan)) { -+ ret = PTR_ERR(nandc->rx_chan); -+ nandc->rx_chan = NULL; -+ dev_err_probe(nandc->dev, ret, -+ "rx DMA channel request failed\n"); -+ goto unalloc; -+ } -+ -+ nandc->cmd_chan = dma_request_chan(nandc->dev, "cmd"); -+ if (IS_ERR(nandc->cmd_chan)) { -+ ret = PTR_ERR(nandc->cmd_chan); -+ nandc->cmd_chan = NULL; -+ dev_err_probe(nandc->dev, ret, -+ "cmd DMA channel request failed\n"); -+ goto unalloc; -+ } -+ -+ /* -+ * Initially allocate BAM transaction to read ONFI param page. -+ * After detecting all the devices, this BAM transaction will -+ * be freed and the next BAM transaction will be allocated with -+ * maximum codeword size -+ */ -+ nandc->max_cwperpage = 1; -+ nandc->bam_txn = qcom_alloc_bam_transaction(nandc); -+ if (!nandc->bam_txn) { -+ dev_err(nandc->dev, -+ "failed to allocate bam transaction\n"); -+ ret = -ENOMEM; -+ goto unalloc; -+ } -+ } else { -+ nandc->chan = dma_request_chan(nandc->dev, "rxtx"); -+ if (IS_ERR(nandc->chan)) { -+ ret = PTR_ERR(nandc->chan); -+ nandc->chan = NULL; -+ dev_err_probe(nandc->dev, ret, -+ "rxtx DMA channel request failed\n"); -+ return ret; -+ } -+ } -+ -+ INIT_LIST_HEAD(&nandc->desc_list); -+ INIT_LIST_HEAD(&nandc->host_list); -+ -+ return 0; -+unalloc: -+ qcom_nandc_unalloc(nandc); -+ return ret; -+} -+EXPORT_SYMBOL(qcom_nandc_alloc); -+ -+MODULE_DESCRIPTION("QPIC controller common api"); -+MODULE_LICENSE("GPL"); ---- a/drivers/mtd/nand/raw/qcom_nandc.c -+++ b/drivers/mtd/nand/raw/qcom_nandc.c -@@ -15,417 +15,7 @@ - #include - #include - #include -- --/* NANDc reg offsets */ --#define NAND_FLASH_CMD 0x00 --#define NAND_ADDR0 0x04 --#define NAND_ADDR1 0x08 --#define NAND_FLASH_CHIP_SELECT 0x0c --#define NAND_EXEC_CMD 0x10 --#define NAND_FLASH_STATUS 0x14 --#define NAND_BUFFER_STATUS 0x18 --#define NAND_DEV0_CFG0 0x20 --#define NAND_DEV0_CFG1 0x24 --#define NAND_DEV0_ECC_CFG 0x28 --#define NAND_AUTO_STATUS_EN 0x2c --#define NAND_DEV1_CFG0 0x30 --#define NAND_DEV1_CFG1 0x34 --#define NAND_READ_ID 0x40 --#define NAND_READ_STATUS 0x44 --#define NAND_DEV_CMD0 0xa0 --#define NAND_DEV_CMD1 0xa4 --#define NAND_DEV_CMD2 0xa8 --#define NAND_DEV_CMD_VLD 0xac --#define SFLASHC_BURST_CFG 0xe0 --#define NAND_ERASED_CW_DETECT_CFG 0xe8 --#define NAND_ERASED_CW_DETECT_STATUS 0xec --#define NAND_EBI2_ECC_BUF_CFG 0xf0 --#define FLASH_BUF_ACC 0x100 -- --#define NAND_CTRL 0xf00 --#define NAND_VERSION 0xf08 --#define NAND_READ_LOCATION_0 0xf20 --#define NAND_READ_LOCATION_1 0xf24 --#define NAND_READ_LOCATION_2 0xf28 --#define NAND_READ_LOCATION_3 0xf2c --#define NAND_READ_LOCATION_LAST_CW_0 0xf40 --#define NAND_READ_LOCATION_LAST_CW_1 0xf44 --#define NAND_READ_LOCATION_LAST_CW_2 0xf48 --#define NAND_READ_LOCATION_LAST_CW_3 0xf4c -- --/* dummy register offsets, used by qcom_write_reg_dma */ --#define NAND_DEV_CMD1_RESTORE 0xdead --#define NAND_DEV_CMD_VLD_RESTORE 0xbeef -- --/* NAND_FLASH_CMD bits */ --#define PAGE_ACC BIT(4) --#define LAST_PAGE BIT(5) -- --/* NAND_FLASH_CHIP_SELECT bits */ --#define NAND_DEV_SEL 0 --#define DM_EN BIT(2) -- --/* NAND_FLASH_STATUS bits */ --#define FS_OP_ERR BIT(4) --#define FS_READY_BSY_N BIT(5) --#define FS_MPU_ERR BIT(8) --#define FS_DEVICE_STS_ERR BIT(16) --#define FS_DEVICE_WP BIT(23) -- --/* NAND_BUFFER_STATUS bits */ --#define BS_UNCORRECTABLE_BIT BIT(8) --#define BS_CORRECTABLE_ERR_MSK 0x1f -- --/* NAND_DEVn_CFG0 bits */ --#define DISABLE_STATUS_AFTER_WRITE 4 --#define CW_PER_PAGE 6 --#define UD_SIZE_BYTES 9 --#define UD_SIZE_BYTES_MASK GENMASK(18, 9) --#define ECC_PARITY_SIZE_BYTES_RS 19 --#define SPARE_SIZE_BYTES 23 --#define SPARE_SIZE_BYTES_MASK GENMASK(26, 23) --#define NUM_ADDR_CYCLES 27 --#define STATUS_BFR_READ 30 --#define SET_RD_MODE_AFTER_STATUS 31 -- --/* NAND_DEVn_CFG0 bits */ --#define DEV0_CFG1_ECC_DISABLE 0 --#define WIDE_FLASH 1 --#define NAND_RECOVERY_CYCLES 2 --#define CS_ACTIVE_BSY 5 --#define BAD_BLOCK_BYTE_NUM 6 --#define BAD_BLOCK_IN_SPARE_AREA 16 --#define WR_RD_BSY_GAP 17 --#define ENABLE_BCH_ECC 27 -- --/* NAND_DEV0_ECC_CFG bits */ --#define ECC_CFG_ECC_DISABLE 0 --#define ECC_SW_RESET 1 --#define ECC_MODE 4 --#define ECC_PARITY_SIZE_BYTES_BCH 8 --#define ECC_NUM_DATA_BYTES 16 --#define ECC_NUM_DATA_BYTES_MASK GENMASK(25, 16) --#define ECC_FORCE_CLK_OPEN 30 -- --/* NAND_DEV_CMD1 bits */ --#define READ_ADDR 0 -- --/* NAND_DEV_CMD_VLD bits */ --#define READ_START_VLD BIT(0) --#define READ_STOP_VLD BIT(1) --#define WRITE_START_VLD BIT(2) --#define ERASE_START_VLD BIT(3) --#define SEQ_READ_START_VLD BIT(4) -- --/* NAND_EBI2_ECC_BUF_CFG bits */ --#define NUM_STEPS 0 -- --/* NAND_ERASED_CW_DETECT_CFG bits */ --#define ERASED_CW_ECC_MASK 1 --#define AUTO_DETECT_RES 0 --#define MASK_ECC BIT(ERASED_CW_ECC_MASK) --#define RESET_ERASED_DET BIT(AUTO_DETECT_RES) --#define ACTIVE_ERASED_DET (0 << AUTO_DETECT_RES) --#define CLR_ERASED_PAGE_DET (RESET_ERASED_DET | MASK_ECC) --#define SET_ERASED_PAGE_DET (ACTIVE_ERASED_DET | MASK_ECC) -- --/* NAND_ERASED_CW_DETECT_STATUS bits */ --#define PAGE_ALL_ERASED BIT(7) --#define CODEWORD_ALL_ERASED BIT(6) --#define PAGE_ERASED BIT(5) --#define CODEWORD_ERASED BIT(4) --#define ERASED_PAGE (PAGE_ALL_ERASED | PAGE_ERASED) --#define ERASED_CW (CODEWORD_ALL_ERASED | CODEWORD_ERASED) -- --/* NAND_READ_LOCATION_n bits */ --#define READ_LOCATION_OFFSET 0 --#define READ_LOCATION_SIZE 16 --#define READ_LOCATION_LAST 31 -- --/* Version Mask */ --#define NAND_VERSION_MAJOR_MASK 0xf0000000 --#define NAND_VERSION_MAJOR_SHIFT 28 --#define NAND_VERSION_MINOR_MASK 0x0fff0000 --#define NAND_VERSION_MINOR_SHIFT 16 -- --/* NAND OP_CMDs */ --#define OP_PAGE_READ 0x2 --#define OP_PAGE_READ_WITH_ECC 0x3 --#define OP_PAGE_READ_WITH_ECC_SPARE 0x4 --#define OP_PAGE_READ_ONFI_READ 0x5 --#define OP_PROGRAM_PAGE 0x6 --#define OP_PAGE_PROGRAM_WITH_ECC 0x7 --#define OP_PROGRAM_PAGE_SPARE 0x9 --#define OP_BLOCK_ERASE 0xa --#define OP_CHECK_STATUS 0xc --#define OP_FETCH_ID 0xb --#define OP_RESET_DEVICE 0xd -- --/* Default Value for NAND_DEV_CMD_VLD */ --#define NAND_DEV_CMD_VLD_VAL (READ_START_VLD | WRITE_START_VLD | \ -- ERASE_START_VLD | SEQ_READ_START_VLD) -- --/* NAND_CTRL bits */ --#define BAM_MODE_EN BIT(0) -- --/* -- * the NAND controller performs reads/writes with ECC in 516 byte chunks. -- * the driver calls the chunks 'step' or 'codeword' interchangeably -- */ --#define NANDC_STEP_SIZE 512 -- --/* -- * the largest page size we support is 8K, this will have 16 steps/codewords -- * of 512 bytes each -- */ --#define MAX_NUM_STEPS (SZ_8K / NANDC_STEP_SIZE) -- --/* we read at most 3 registers per codeword scan */ --#define MAX_REG_RD (3 * MAX_NUM_STEPS) -- --/* ECC modes supported by the controller */ --#define ECC_NONE BIT(0) --#define ECC_RS_4BIT BIT(1) --#define ECC_BCH_4BIT BIT(2) --#define ECC_BCH_8BIT BIT(3) -- --/* -- * Returns the actual register address for all NAND_DEV_ registers -- * (i.e. NAND_DEV_CMD0, NAND_DEV_CMD1, NAND_DEV_CMD2 and NAND_DEV_CMD_VLD) -- */ --#define dev_cmd_reg_addr(nandc, reg) ((nandc)->props->dev_cmd_reg_start + (reg)) -- --/* Returns the NAND register physical address */ --#define nandc_reg_phys(chip, offset) ((chip)->base_phys + (offset)) -- --/* Returns the dma address for reg read buffer */ --#define reg_buf_dma_addr(chip, vaddr) \ -- ((chip)->reg_read_dma + \ -- ((u8 *)(vaddr) - (u8 *)(chip)->reg_read_buf)) -- --#define QPIC_PER_CW_CMD_ELEMENTS 32 --#define QPIC_PER_CW_CMD_SGL 32 --#define QPIC_PER_CW_DATA_SGL 8 -- --#define QPIC_NAND_COMPLETION_TIMEOUT msecs_to_jiffies(2000) -- --/* -- * Flags used in DMA descriptor preparation helper functions -- * (i.e. qcom_read_reg_dma/qcom_write_reg_dma/qcom_read_data_dma/qcom_write_data_dma) -- */ --/* Don't set the EOT in current tx BAM sgl */ --#define NAND_BAM_NO_EOT BIT(0) --/* Set the NWD flag in current BAM sgl */ --#define NAND_BAM_NWD BIT(1) --/* Finish writing in the current BAM sgl and start writing in another BAM sgl */ --#define NAND_BAM_NEXT_SGL BIT(2) --/* -- * Erased codeword status is being used two times in single transfer so this -- * flag will determine the current value of erased codeword status register -- */ --#define NAND_ERASED_CW_SET BIT(4) -- --#define MAX_ADDRESS_CYCLE 5 -- --/* -- * This data type corresponds to the BAM transaction which will be used for all -- * NAND transfers. -- * @bam_ce - the array of BAM command elements -- * @cmd_sgl - sgl for NAND BAM command pipe -- * @data_sgl - sgl for NAND BAM consumer/producer pipe -- * @last_data_desc - last DMA desc in data channel (tx/rx). -- * @last_cmd_desc - last DMA desc in command channel. -- * @txn_done - completion for NAND transfer. -- * @bam_ce_pos - the index in bam_ce which is available for next sgl -- * @bam_ce_start - the index in bam_ce which marks the start position ce -- * for current sgl. It will be used for size calculation -- * for current sgl -- * @cmd_sgl_pos - current index in command sgl. -- * @cmd_sgl_start - start index in command sgl. -- * @tx_sgl_pos - current index in data sgl for tx. -- * @tx_sgl_start - start index in data sgl for tx. -- * @rx_sgl_pos - current index in data sgl for rx. -- * @rx_sgl_start - start index in data sgl for rx. -- */ --struct bam_transaction { -- struct bam_cmd_element *bam_ce; -- struct scatterlist *cmd_sgl; -- struct scatterlist *data_sgl; -- struct dma_async_tx_descriptor *last_data_desc; -- struct dma_async_tx_descriptor *last_cmd_desc; -- struct completion txn_done; -- u32 bam_ce_pos; -- u32 bam_ce_start; -- u32 cmd_sgl_pos; -- u32 cmd_sgl_start; -- u32 tx_sgl_pos; -- u32 tx_sgl_start; -- u32 rx_sgl_pos; -- u32 rx_sgl_start; --}; -- --/* -- * This data type corresponds to the nand dma descriptor -- * @dma_desc - low level DMA engine descriptor -- * @list - list for desc_info -- * -- * @adm_sgl - sgl which will be used for single sgl dma descriptor. Only used by -- * ADM -- * @bam_sgl - sgl which will be used for dma descriptor. Only used by BAM -- * @sgl_cnt - number of SGL in bam_sgl. Only used by BAM -- * @dir - DMA transfer direction -- */ --struct desc_info { -- struct dma_async_tx_descriptor *dma_desc; -- struct list_head node; -- -- union { -- struct scatterlist adm_sgl; -- struct { -- struct scatterlist *bam_sgl; -- int sgl_cnt; -- }; -- }; -- enum dma_data_direction dir; --}; -- --/* -- * holds the current register values that we want to write. acts as a contiguous -- * chunk of memory which we use to write the controller registers through DMA. -- */ --struct nandc_regs { -- __le32 cmd; -- __le32 addr0; -- __le32 addr1; -- __le32 chip_sel; -- __le32 exec; -- -- __le32 cfg0; -- __le32 cfg1; -- __le32 ecc_bch_cfg; -- -- __le32 clrflashstatus; -- __le32 clrreadstatus; -- -- __le32 cmd1; -- __le32 vld; -- -- __le32 orig_cmd1; -- __le32 orig_vld; -- -- __le32 ecc_buf_cfg; -- __le32 read_location0; -- __le32 read_location1; -- __le32 read_location2; -- __le32 read_location3; -- __le32 read_location_last0; -- __le32 read_location_last1; -- __le32 read_location_last2; -- __le32 read_location_last3; -- -- __le32 erased_cw_detect_cfg_clr; -- __le32 erased_cw_detect_cfg_set; --}; -- --/* -- * NAND controller data struct -- * -- * @dev: parent device -- * -- * @base: MMIO base -- * -- * @core_clk: controller clock -- * @aon_clk: another controller clock -- * -- * @regs: a contiguous chunk of memory for DMA register -- * writes. contains the register values to be -- * written to controller -- * -- * @props: properties of current NAND controller, -- * initialized via DT match data -- * -- * @controller: base controller structure -- * @host_list: list containing all the chips attached to the -- * controller -- * -- * @chan: dma channel -- * @cmd_crci: ADM DMA CRCI for command flow control -- * @data_crci: ADM DMA CRCI for data flow control -- * -- * @desc_list: DMA descriptor list (list of desc_infos) -- * -- * @data_buffer: our local DMA buffer for page read/writes, -- * used when we can't use the buffer provided -- * by upper layers directly -- * @reg_read_buf: local buffer for reading back registers via DMA -- * -- * @base_phys: physical base address of controller registers -- * @base_dma: dma base address of controller registers -- * @reg_read_dma: contains dma address for register read buffer -- * -- * @buf_size/count/start: markers for chip->legacy.read_buf/write_buf -- * functions -- * @max_cwperpage: maximum QPIC codewords required. calculated -- * from all connected NAND devices pagesize -- * -- * @reg_read_pos: marker for data read in reg_read_buf -- * -- * @cmd1/vld: some fixed controller register values -- * -- * @exec_opwrite: flag to select correct number of code word -- * while reading status -- */ --struct qcom_nand_controller { -- struct device *dev; -- -- void __iomem *base; -- -- struct clk *core_clk; -- struct clk *aon_clk; -- -- struct nandc_regs *regs; -- struct bam_transaction *bam_txn; -- -- const struct qcom_nandc_props *props; -- -- struct nand_controller controller; -- struct list_head host_list; -- -- union { -- /* will be used only by QPIC for BAM DMA */ -- struct { -- struct dma_chan *tx_chan; -- struct dma_chan *rx_chan; -- struct dma_chan *cmd_chan; -- }; -- -- /* will be used only by EBI2 for ADM DMA */ -- struct { -- struct dma_chan *chan; -- unsigned int cmd_crci; -- unsigned int data_crci; -- }; -- }; -- -- struct list_head desc_list; -- -- u8 *data_buffer; -- __le32 *reg_read_buf; -- -- phys_addr_t base_phys; -- dma_addr_t base_dma; -- dma_addr_t reg_read_dma; -- -- int buf_size; -- int buf_count; -- int buf_start; -- unsigned int max_cwperpage; -- -- int reg_read_pos; -- -- u32 cmd1, vld; -- bool exec_opwrite; --}; -+#include - - /* - * NAND special boot partitions -@@ -530,97 +120,6 @@ struct qcom_nand_host { - bool bch_enabled; - }; - --/* -- * This data type corresponds to the NAND controller properties which varies -- * among different NAND controllers. -- * @ecc_modes - ecc mode for NAND -- * @dev_cmd_reg_start - NAND_DEV_CMD_* registers starting offset -- * @supports_bam - whether NAND controller is using Bus Access Manager (BAM) -- * @nandc_part_of_qpic - whether NAND controller is part of qpic IP -- * @qpic_version2 - flag to indicate QPIC IP version 2 -- * @use_codeword_fixup - whether NAND has different layout for boot partitions -- */ --struct qcom_nandc_props { -- u32 ecc_modes; -- u32 dev_cmd_reg_start; -- bool supports_bam; -- bool nandc_part_of_qpic; -- bool qpic_version2; -- bool use_codeword_fixup; --}; -- --/* Frees the BAM transaction memory */ --static void qcom_free_bam_transaction(struct qcom_nand_controller *nandc) --{ -- struct bam_transaction *bam_txn = nandc->bam_txn; -- -- devm_kfree(nandc->dev, bam_txn); --} -- --/* Allocates and Initializes the BAM transaction */ --static struct bam_transaction * --qcom_alloc_bam_transaction(struct qcom_nand_controller *nandc) --{ -- struct bam_transaction *bam_txn; -- size_t bam_txn_size; -- unsigned int num_cw = nandc->max_cwperpage; -- void *bam_txn_buf; -- -- bam_txn_size = -- sizeof(*bam_txn) + num_cw * -- ((sizeof(*bam_txn->bam_ce) * QPIC_PER_CW_CMD_ELEMENTS) + -- (sizeof(*bam_txn->cmd_sgl) * QPIC_PER_CW_CMD_SGL) + -- (sizeof(*bam_txn->data_sgl) * QPIC_PER_CW_DATA_SGL)); -- -- bam_txn_buf = devm_kzalloc(nandc->dev, bam_txn_size, GFP_KERNEL); -- if (!bam_txn_buf) -- return NULL; -- -- bam_txn = bam_txn_buf; -- bam_txn_buf += sizeof(*bam_txn); -- -- bam_txn->bam_ce = bam_txn_buf; -- bam_txn_buf += -- sizeof(*bam_txn->bam_ce) * QPIC_PER_CW_CMD_ELEMENTS * num_cw; -- -- bam_txn->cmd_sgl = bam_txn_buf; -- bam_txn_buf += -- sizeof(*bam_txn->cmd_sgl) * QPIC_PER_CW_CMD_SGL * num_cw; -- -- bam_txn->data_sgl = bam_txn_buf; -- -- init_completion(&bam_txn->txn_done); -- -- return bam_txn; --} -- --/* Clears the BAM transaction indexes */ --static void qcom_clear_bam_transaction(struct qcom_nand_controller *nandc) --{ -- struct bam_transaction *bam_txn = nandc->bam_txn; -- -- if (!nandc->props->supports_bam) -- return; -- -- memset(&bam_txn->bam_ce_pos, 0, sizeof(u32) * 8); -- bam_txn->last_data_desc = NULL; -- -- sg_init_table(bam_txn->cmd_sgl, nandc->max_cwperpage * -- QPIC_PER_CW_CMD_SGL); -- sg_init_table(bam_txn->data_sgl, nandc->max_cwperpage * -- QPIC_PER_CW_DATA_SGL); -- -- reinit_completion(&bam_txn->txn_done); --} -- --/* Callback for DMA descriptor completion */ --static void qcom_qpic_bam_dma_done(void *data) --{ -- struct bam_transaction *bam_txn = data; -- -- complete(&bam_txn->txn_done); --} -- - static struct qcom_nand_host *to_qcom_nand_host(struct nand_chip *chip) - { - return container_of(chip, struct qcom_nand_host, chip); -@@ -629,8 +128,8 @@ static struct qcom_nand_host *to_qcom_na - static struct qcom_nand_controller * - get_qcom_nand_controller(struct nand_chip *chip) - { -- return container_of(chip->controller, struct qcom_nand_controller, -- controller); -+ return (struct qcom_nand_controller *) -+ ((u8 *)chip->controller - sizeof(struct qcom_nand_controller)); - } - - static u32 nandc_read(struct qcom_nand_controller *nandc, int offset) -@@ -644,23 +143,6 @@ static void nandc_write(struct qcom_nand - iowrite32(val, nandc->base + offset); - } - --static void qcom_nandc_dev_to_mem(struct qcom_nand_controller *nandc, bool is_cpu) --{ -- if (!nandc->props->supports_bam) -- return; -- -- if (is_cpu) -- dma_sync_single_for_cpu(nandc->dev, nandc->reg_read_dma, -- MAX_REG_RD * -- sizeof(*nandc->reg_read_buf), -- DMA_FROM_DEVICE); -- else -- dma_sync_single_for_device(nandc->dev, nandc->reg_read_dma, -- MAX_REG_RD * -- sizeof(*nandc->reg_read_buf), -- DMA_FROM_DEVICE); --} -- - /* Helper to check whether this is the last CW or not */ - static bool qcom_nandc_is_last_cw(struct nand_ecc_ctrl *ecc, int cw) - { -@@ -820,356 +302,6 @@ static void update_rw_regs(struct qcom_n - } - - /* -- * Maps the scatter gather list for DMA transfer and forms the DMA descriptor -- * for BAM. This descriptor will be added in the NAND DMA descriptor queue -- * which will be submitted to DMA engine. -- */ --static int qcom_prepare_bam_async_desc(struct qcom_nand_controller *nandc, -- struct dma_chan *chan, -- unsigned long flags) --{ -- struct desc_info *desc; -- struct scatterlist *sgl; -- unsigned int sgl_cnt; -- int ret; -- struct bam_transaction *bam_txn = nandc->bam_txn; -- enum dma_transfer_direction dir_eng; -- struct dma_async_tx_descriptor *dma_desc; -- -- desc = kzalloc(sizeof(*desc), GFP_KERNEL); -- if (!desc) -- return -ENOMEM; -- -- if (chan == nandc->cmd_chan) { -- sgl = &bam_txn->cmd_sgl[bam_txn->cmd_sgl_start]; -- sgl_cnt = bam_txn->cmd_sgl_pos - bam_txn->cmd_sgl_start; -- bam_txn->cmd_sgl_start = bam_txn->cmd_sgl_pos; -- dir_eng = DMA_MEM_TO_DEV; -- desc->dir = DMA_TO_DEVICE; -- } else if (chan == nandc->tx_chan) { -- sgl = &bam_txn->data_sgl[bam_txn->tx_sgl_start]; -- sgl_cnt = bam_txn->tx_sgl_pos - bam_txn->tx_sgl_start; -- bam_txn->tx_sgl_start = bam_txn->tx_sgl_pos; -- dir_eng = DMA_MEM_TO_DEV; -- desc->dir = DMA_TO_DEVICE; -- } else { -- sgl = &bam_txn->data_sgl[bam_txn->rx_sgl_start]; -- sgl_cnt = bam_txn->rx_sgl_pos - bam_txn->rx_sgl_start; -- bam_txn->rx_sgl_start = bam_txn->rx_sgl_pos; -- dir_eng = DMA_DEV_TO_MEM; -- desc->dir = DMA_FROM_DEVICE; -- } -- -- sg_mark_end(sgl + sgl_cnt - 1); -- ret = dma_map_sg(nandc->dev, sgl, sgl_cnt, desc->dir); -- if (ret == 0) { -- dev_err(nandc->dev, "failure in mapping desc\n"); -- kfree(desc); -- return -ENOMEM; -- } -- -- desc->sgl_cnt = sgl_cnt; -- desc->bam_sgl = sgl; -- -- dma_desc = dmaengine_prep_slave_sg(chan, sgl, sgl_cnt, dir_eng, -- flags); -- -- if (!dma_desc) { -- dev_err(nandc->dev, "failure in prep desc\n"); -- dma_unmap_sg(nandc->dev, sgl, sgl_cnt, desc->dir); -- kfree(desc); -- return -EINVAL; -- } -- -- desc->dma_desc = dma_desc; -- -- /* update last data/command descriptor */ -- if (chan == nandc->cmd_chan) -- bam_txn->last_cmd_desc = dma_desc; -- else -- bam_txn->last_data_desc = dma_desc; -- -- list_add_tail(&desc->node, &nandc->desc_list); -- -- return 0; --} -- --/* -- * Prepares the command descriptor for BAM DMA which will be used for NAND -- * register reads and writes. The command descriptor requires the command -- * to be formed in command element type so this function uses the command -- * element from bam transaction ce array and fills the same with required -- * data. A single SGL can contain multiple command elements so -- * NAND_BAM_NEXT_SGL will be used for starting the separate SGL -- * after the current command element. -- */ --static int qcom_prep_bam_dma_desc_cmd(struct qcom_nand_controller *nandc, bool read, -- int reg_off, const void *vaddr, -- int size, unsigned int flags) --{ -- int bam_ce_size; -- int i, ret; -- struct bam_cmd_element *bam_ce_buffer; -- struct bam_transaction *bam_txn = nandc->bam_txn; -- -- bam_ce_buffer = &bam_txn->bam_ce[bam_txn->bam_ce_pos]; -- -- /* fill the command desc */ -- for (i = 0; i < size; i++) { -- if (read) -- bam_prep_ce(&bam_ce_buffer[i], -- nandc_reg_phys(nandc, reg_off + 4 * i), -- BAM_READ_COMMAND, -- reg_buf_dma_addr(nandc, -- (__le32 *)vaddr + i)); -- else -- bam_prep_ce_le32(&bam_ce_buffer[i], -- nandc_reg_phys(nandc, reg_off + 4 * i), -- BAM_WRITE_COMMAND, -- *((__le32 *)vaddr + i)); -- } -- -- bam_txn->bam_ce_pos += size; -- -- /* use the separate sgl after this command */ -- if (flags & NAND_BAM_NEXT_SGL) { -- bam_ce_buffer = &bam_txn->bam_ce[bam_txn->bam_ce_start]; -- bam_ce_size = (bam_txn->bam_ce_pos - -- bam_txn->bam_ce_start) * -- sizeof(struct bam_cmd_element); -- sg_set_buf(&bam_txn->cmd_sgl[bam_txn->cmd_sgl_pos], -- bam_ce_buffer, bam_ce_size); -- bam_txn->cmd_sgl_pos++; -- bam_txn->bam_ce_start = bam_txn->bam_ce_pos; -- -- if (flags & NAND_BAM_NWD) { -- ret = qcom_prepare_bam_async_desc(nandc, nandc->cmd_chan, -- DMA_PREP_FENCE | -- DMA_PREP_CMD); -- if (ret) -- return ret; -- } -- } -- -- return 0; --} -- --/* -- * Prepares the data descriptor for BAM DMA which will be used for NAND -- * data reads and writes. -- */ --static int qcom_prep_bam_dma_desc_data(struct qcom_nand_controller *nandc, bool read, -- const void *vaddr, int size, unsigned int flags) --{ -- int ret; -- struct bam_transaction *bam_txn = nandc->bam_txn; -- -- if (read) { -- sg_set_buf(&bam_txn->data_sgl[bam_txn->rx_sgl_pos], -- vaddr, size); -- bam_txn->rx_sgl_pos++; -- } else { -- sg_set_buf(&bam_txn->data_sgl[bam_txn->tx_sgl_pos], -- vaddr, size); -- bam_txn->tx_sgl_pos++; -- -- /* -- * BAM will only set EOT for DMA_PREP_INTERRUPT so if this flag -- * is not set, form the DMA descriptor -- */ -- if (!(flags & NAND_BAM_NO_EOT)) { -- ret = qcom_prepare_bam_async_desc(nandc, nandc->tx_chan, -- DMA_PREP_INTERRUPT); -- if (ret) -- return ret; -- } -- } -- -- return 0; --} -- --static int qcom_prep_adm_dma_desc(struct qcom_nand_controller *nandc, bool read, -- int reg_off, const void *vaddr, int size, -- bool flow_control) --{ -- struct desc_info *desc; -- struct dma_async_tx_descriptor *dma_desc; -- struct scatterlist *sgl; -- struct dma_slave_config slave_conf; -- struct qcom_adm_peripheral_config periph_conf = {}; -- enum dma_transfer_direction dir_eng; -- int ret; -- -- desc = kzalloc(sizeof(*desc), GFP_KERNEL); -- if (!desc) -- return -ENOMEM; -- -- sgl = &desc->adm_sgl; -- -- sg_init_one(sgl, vaddr, size); -- -- if (read) { -- dir_eng = DMA_DEV_TO_MEM; -- desc->dir = DMA_FROM_DEVICE; -- } else { -- dir_eng = DMA_MEM_TO_DEV; -- desc->dir = DMA_TO_DEVICE; -- } -- -- ret = dma_map_sg(nandc->dev, sgl, 1, desc->dir); -- if (ret == 0) { -- ret = -ENOMEM; -- goto err; -- } -- -- memset(&slave_conf, 0x00, sizeof(slave_conf)); -- -- slave_conf.device_fc = flow_control; -- if (read) { -- slave_conf.src_maxburst = 16; -- slave_conf.src_addr = nandc->base_dma + reg_off; -- if (nandc->data_crci) { -- periph_conf.crci = nandc->data_crci; -- slave_conf.peripheral_config = &periph_conf; -- slave_conf.peripheral_size = sizeof(periph_conf); -- } -- } else { -- slave_conf.dst_maxburst = 16; -- slave_conf.dst_addr = nandc->base_dma + reg_off; -- if (nandc->cmd_crci) { -- periph_conf.crci = nandc->cmd_crci; -- slave_conf.peripheral_config = &periph_conf; -- slave_conf.peripheral_size = sizeof(periph_conf); -- } -- } -- -- ret = dmaengine_slave_config(nandc->chan, &slave_conf); -- if (ret) { -- dev_err(nandc->dev, "failed to configure dma channel\n"); -- goto err; -- } -- -- dma_desc = dmaengine_prep_slave_sg(nandc->chan, sgl, 1, dir_eng, 0); -- if (!dma_desc) { -- dev_err(nandc->dev, "failed to prepare desc\n"); -- ret = -EINVAL; -- goto err; -- } -- -- desc->dma_desc = dma_desc; -- -- list_add_tail(&desc->node, &nandc->desc_list); -- -- return 0; --err: -- kfree(desc); -- -- return ret; --} -- --/* -- * qcom_read_reg_dma: prepares a descriptor to read a given number of -- * contiguous registers to the reg_read_buf pointer -- * -- * @first: offset of the first register in the contiguous block -- * @num_regs: number of registers to read -- * @flags: flags to control DMA descriptor preparation -- */ --static int qcom_read_reg_dma(struct qcom_nand_controller *nandc, int first, -- int num_regs, unsigned int flags) --{ -- bool flow_control = false; -- void *vaddr; -- -- vaddr = nandc->reg_read_buf + nandc->reg_read_pos; -- nandc->reg_read_pos += num_regs; -- -- if (first == NAND_DEV_CMD_VLD || first == NAND_DEV_CMD1) -- first = dev_cmd_reg_addr(nandc, first); -- -- if (nandc->props->supports_bam) -- return qcom_prep_bam_dma_desc_cmd(nandc, true, first, vaddr, -- num_regs, flags); -- -- if (first == NAND_READ_ID || first == NAND_FLASH_STATUS) -- flow_control = true; -- -- return qcom_prep_adm_dma_desc(nandc, true, first, vaddr, -- num_regs * sizeof(u32), flow_control); --} -- --/* -- * qcom_write_reg_dma: prepares a descriptor to write a given number of -- * contiguous registers -- * -- * @vaddr: contiguous memory from where register value will -- * be written -- * @first: offset of the first register in the contiguous block -- * @num_regs: number of registers to write -- * @flags: flags to control DMA descriptor preparation -- */ --static int qcom_write_reg_dma(struct qcom_nand_controller *nandc, __le32 *vaddr, -- int first, int num_regs, unsigned int flags) --{ -- bool flow_control = false; -- -- if (first == NAND_EXEC_CMD) -- flags |= NAND_BAM_NWD; -- -- if (first == NAND_DEV_CMD1_RESTORE || first == NAND_DEV_CMD1) -- first = dev_cmd_reg_addr(nandc, NAND_DEV_CMD1); -- -- if (first == NAND_DEV_CMD_VLD_RESTORE || first == NAND_DEV_CMD_VLD) -- first = dev_cmd_reg_addr(nandc, NAND_DEV_CMD_VLD); -- -- if (nandc->props->supports_bam) -- return qcom_prep_bam_dma_desc_cmd(nandc, false, first, vaddr, -- num_regs, flags); -- -- if (first == NAND_FLASH_CMD) -- flow_control = true; -- -- return qcom_prep_adm_dma_desc(nandc, false, first, vaddr, -- num_regs * sizeof(u32), flow_control); --} -- --/* -- * qcom_read_data_dma: prepares a DMA descriptor to transfer data from the -- * controller's internal buffer to the buffer 'vaddr' -- * -- * @reg_off: offset within the controller's data buffer -- * @vaddr: virtual address of the buffer we want to write to -- * @size: DMA transaction size in bytes -- * @flags: flags to control DMA descriptor preparation -- */ --static int qcom_read_data_dma(struct qcom_nand_controller *nandc, int reg_off, -- const u8 *vaddr, int size, unsigned int flags) --{ -- if (nandc->props->supports_bam) -- return qcom_prep_bam_dma_desc_data(nandc, true, vaddr, size, flags); -- -- return qcom_prep_adm_dma_desc(nandc, true, reg_off, vaddr, size, false); --} -- --/* -- * qcom_write_data_dma: prepares a DMA descriptor to transfer data from -- * 'vaddr' to the controller's internal buffer -- * -- * @reg_off: offset within the controller's data buffer -- * @vaddr: virtual address of the buffer we want to read from -- * @size: DMA transaction size in bytes -- * @flags: flags to control DMA descriptor preparation -- */ --static int qcom_write_data_dma(struct qcom_nand_controller *nandc, int reg_off, -- const u8 *vaddr, int size, unsigned int flags) --{ -- if (nandc->props->supports_bam) -- return qcom_prep_bam_dma_desc_data(nandc, false, vaddr, size, flags); -- -- return qcom_prep_adm_dma_desc(nandc, false, reg_off, vaddr, size, false); --} -- --/* - * Helper to prepare DMA descriptors for configuring registers - * before reading a NAND page. - */ -@@ -1262,83 +394,6 @@ static void config_nand_cw_write(struct - NAND_BAM_NEXT_SGL); - } - --/* helpers to submit/free our list of dma descriptors */ --static int qcom_submit_descs(struct qcom_nand_controller *nandc) --{ -- struct desc_info *desc, *n; -- dma_cookie_t cookie = 0; -- struct bam_transaction *bam_txn = nandc->bam_txn; -- int ret = 0; -- -- if (nandc->props->supports_bam) { -- if (bam_txn->rx_sgl_pos > bam_txn->rx_sgl_start) { -- ret = qcom_prepare_bam_async_desc(nandc, nandc->rx_chan, 0); -- if (ret) -- goto err_unmap_free_desc; -- } -- -- if (bam_txn->tx_sgl_pos > bam_txn->tx_sgl_start) { -- ret = qcom_prepare_bam_async_desc(nandc, nandc->tx_chan, -- DMA_PREP_INTERRUPT); -- if (ret) -- goto err_unmap_free_desc; -- } -- -- if (bam_txn->cmd_sgl_pos > bam_txn->cmd_sgl_start) { -- ret = qcom_prepare_bam_async_desc(nandc, nandc->cmd_chan, -- DMA_PREP_CMD); -- if (ret) -- goto err_unmap_free_desc; -- } -- } -- -- list_for_each_entry(desc, &nandc->desc_list, node) -- cookie = dmaengine_submit(desc->dma_desc); -- -- if (nandc->props->supports_bam) { -- bam_txn->last_cmd_desc->callback = qcom_qpic_bam_dma_done; -- bam_txn->last_cmd_desc->callback_param = bam_txn; -- -- dma_async_issue_pending(nandc->tx_chan); -- dma_async_issue_pending(nandc->rx_chan); -- dma_async_issue_pending(nandc->cmd_chan); -- -- if (!wait_for_completion_timeout(&bam_txn->txn_done, -- QPIC_NAND_COMPLETION_TIMEOUT)) -- ret = -ETIMEDOUT; -- } else { -- if (dma_sync_wait(nandc->chan, cookie) != DMA_COMPLETE) -- ret = -ETIMEDOUT; -- } -- --err_unmap_free_desc: -- /* -- * Unmap the dma sg_list and free the desc allocated by both -- * qcom_prepare_bam_async_desc() and qcom_prep_adm_dma_desc() functions. -- */ -- list_for_each_entry_safe(desc, n, &nandc->desc_list, node) { -- list_del(&desc->node); -- -- if (nandc->props->supports_bam) -- dma_unmap_sg(nandc->dev, desc->bam_sgl, -- desc->sgl_cnt, desc->dir); -- else -- dma_unmap_sg(nandc->dev, &desc->adm_sgl, 1, -- desc->dir); -- -- kfree(desc); -- } -- -- return ret; --} -- --/* reset the register read buffer for next NAND operation */ --static void qcom_clear_read_regs(struct qcom_nand_controller *nandc) --{ -- nandc->reg_read_pos = 0; -- qcom_nandc_dev_to_mem(nandc, false); --} -- - /* - * when using BCH ECC, the HW flags an error in NAND_FLASH_STATUS if it read - * an erased CW, and reports an erased CW in NAND_ERASED_CW_DETECT_STATUS. -@@ -2975,141 +2030,14 @@ static const struct nand_controller_ops - .exec_op = qcom_nand_exec_op, - }; - --static void qcom_nandc_unalloc(struct qcom_nand_controller *nandc) --{ -- if (nandc->props->supports_bam) { -- if (!dma_mapping_error(nandc->dev, nandc->reg_read_dma)) -- dma_unmap_single(nandc->dev, nandc->reg_read_dma, -- MAX_REG_RD * -- sizeof(*nandc->reg_read_buf), -- DMA_FROM_DEVICE); -- -- if (nandc->tx_chan) -- dma_release_channel(nandc->tx_chan); -- -- if (nandc->rx_chan) -- dma_release_channel(nandc->rx_chan); -- -- if (nandc->cmd_chan) -- dma_release_channel(nandc->cmd_chan); -- } else { -- if (nandc->chan) -- dma_release_channel(nandc->chan); -- } --} -- --static int qcom_nandc_alloc(struct qcom_nand_controller *nandc) --{ -- int ret; -- -- ret = dma_set_coherent_mask(nandc->dev, DMA_BIT_MASK(32)); -- if (ret) { -- dev_err(nandc->dev, "failed to set DMA mask\n"); -- return ret; -- } -- -- /* -- * we use the internal buffer for reading ONFI params, reading small -- * data like ID and status, and preforming read-copy-write operations -- * when writing to a codeword partially. 532 is the maximum possible -- * size of a codeword for our nand controller -- */ -- nandc->buf_size = 532; -- -- nandc->data_buffer = devm_kzalloc(nandc->dev, nandc->buf_size, GFP_KERNEL); -- if (!nandc->data_buffer) -- return -ENOMEM; -- -- nandc->regs = devm_kzalloc(nandc->dev, sizeof(*nandc->regs), GFP_KERNEL); -- if (!nandc->regs) -- return -ENOMEM; -- -- nandc->reg_read_buf = devm_kcalloc(nandc->dev, MAX_REG_RD, -- sizeof(*nandc->reg_read_buf), -- GFP_KERNEL); -- if (!nandc->reg_read_buf) -- return -ENOMEM; -- -- if (nandc->props->supports_bam) { -- nandc->reg_read_dma = -- dma_map_single(nandc->dev, nandc->reg_read_buf, -- MAX_REG_RD * -- sizeof(*nandc->reg_read_buf), -- DMA_FROM_DEVICE); -- if (dma_mapping_error(nandc->dev, nandc->reg_read_dma)) { -- dev_err(nandc->dev, "failed to DMA MAP reg buffer\n"); -- return -EIO; -- } -- -- nandc->tx_chan = dma_request_chan(nandc->dev, "tx"); -- if (IS_ERR(nandc->tx_chan)) { -- ret = PTR_ERR(nandc->tx_chan); -- nandc->tx_chan = NULL; -- dev_err_probe(nandc->dev, ret, -- "tx DMA channel request failed\n"); -- goto unalloc; -- } -- -- nandc->rx_chan = dma_request_chan(nandc->dev, "rx"); -- if (IS_ERR(nandc->rx_chan)) { -- ret = PTR_ERR(nandc->rx_chan); -- nandc->rx_chan = NULL; -- dev_err_probe(nandc->dev, ret, -- "rx DMA channel request failed\n"); -- goto unalloc; -- } -- -- nandc->cmd_chan = dma_request_chan(nandc->dev, "cmd"); -- if (IS_ERR(nandc->cmd_chan)) { -- ret = PTR_ERR(nandc->cmd_chan); -- nandc->cmd_chan = NULL; -- dev_err_probe(nandc->dev, ret, -- "cmd DMA channel request failed\n"); -- goto unalloc; -- } -- -- /* -- * Initially allocate BAM transaction to read ONFI param page. -- * After detecting all the devices, this BAM transaction will -- * be freed and the next BAM transaction will be allocated with -- * maximum codeword size -- */ -- nandc->max_cwperpage = 1; -- nandc->bam_txn = qcom_alloc_bam_transaction(nandc); -- if (!nandc->bam_txn) { -- dev_err(nandc->dev, -- "failed to allocate bam transaction\n"); -- ret = -ENOMEM; -- goto unalloc; -- } -- } else { -- nandc->chan = dma_request_chan(nandc->dev, "rxtx"); -- if (IS_ERR(nandc->chan)) { -- ret = PTR_ERR(nandc->chan); -- nandc->chan = NULL; -- dev_err_probe(nandc->dev, ret, -- "rxtx DMA channel request failed\n"); -- return ret; -- } -- } -- -- INIT_LIST_HEAD(&nandc->desc_list); -- INIT_LIST_HEAD(&nandc->host_list); -- -- nand_controller_init(&nandc->controller); -- nandc->controller.ops = &qcom_nandc_ops; -- -- return 0; --unalloc: -- qcom_nandc_unalloc(nandc); -- return ret; --} -- - /* one time setup of a few nand controller registers */ - static int qcom_nandc_setup(struct qcom_nand_controller *nandc) - { - u32 nand_ctrl; - -+ nand_controller_init(nandc->controller); -+ nandc->controller->ops = &qcom_nandc_ops; -+ - /* kill onenand */ - if (!nandc->props->nandc_part_of_qpic) - nandc_write(nandc, SFLASHC_BURST_CFG, 0); -@@ -3248,7 +2176,7 @@ static int qcom_nand_host_init_and_regis - chip->legacy.block_bad = qcom_nandc_block_bad; - chip->legacy.block_markbad = qcom_nandc_block_markbad; - -- chip->controller = &nandc->controller; -+ chip->controller = nandc->controller; - chip->options |= NAND_NO_SUBPAGE_WRITE | NAND_USES_DMA | - NAND_SKIP_BBTSCAN; - -@@ -3331,17 +2259,21 @@ static int qcom_nandc_parse_dt(struct pl - static int qcom_nandc_probe(struct platform_device *pdev) - { - struct qcom_nand_controller *nandc; -+ struct nand_controller *controller; - const void *dev_data; - struct device *dev = &pdev->dev; - struct resource *res; - int ret; - -- nandc = devm_kzalloc(&pdev->dev, sizeof(*nandc), GFP_KERNEL); -+ nandc = devm_kzalloc(&pdev->dev, sizeof(*nandc) + sizeof(*controller), -+ GFP_KERNEL); - if (!nandc) - return -ENOMEM; -+ controller = (struct nand_controller *)&nandc[1]; - - platform_set_drvdata(pdev, nandc); - nandc->dev = dev; -+ nandc->controller = controller; - - dev_data = of_device_get_match_data(dev); - if (!dev_data) { ---- /dev/null -+++ b/include/linux/mtd/nand-qpic-common.h -@@ -0,0 +1,468 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * QCOM QPIC common APIs header file -+ * -+ * Copyright (c) 2023 Qualcomm Inc. -+ * Authors: Md sadre Alam -+ * -+ */ -+#ifndef __MTD_NAND_QPIC_COMMON_H__ -+#define __MTD_NAND_QPIC_COMMON_H__ -+ -+/* NANDc reg offsets */ -+#define NAND_FLASH_CMD 0x00 -+#define NAND_ADDR0 0x04 -+#define NAND_ADDR1 0x08 -+#define NAND_FLASH_CHIP_SELECT 0x0c -+#define NAND_EXEC_CMD 0x10 -+#define NAND_FLASH_STATUS 0x14 -+#define NAND_BUFFER_STATUS 0x18 -+#define NAND_DEV0_CFG0 0x20 -+#define NAND_DEV0_CFG1 0x24 -+#define NAND_DEV0_ECC_CFG 0x28 -+#define NAND_AUTO_STATUS_EN 0x2c -+#define NAND_DEV1_CFG0 0x30 -+#define NAND_DEV1_CFG1 0x34 -+#define NAND_READ_ID 0x40 -+#define NAND_READ_STATUS 0x44 -+#define NAND_DEV_CMD0 0xa0 -+#define NAND_DEV_CMD1 0xa4 -+#define NAND_DEV_CMD2 0xa8 -+#define NAND_DEV_CMD_VLD 0xac -+#define SFLASHC_BURST_CFG 0xe0 -+#define NAND_ERASED_CW_DETECT_CFG 0xe8 -+#define NAND_ERASED_CW_DETECT_STATUS 0xec -+#define NAND_EBI2_ECC_BUF_CFG 0xf0 -+#define FLASH_BUF_ACC 0x100 -+ -+#define NAND_CTRL 0xf00 -+#define NAND_VERSION 0xf08 -+#define NAND_READ_LOCATION_0 0xf20 -+#define NAND_READ_LOCATION_1 0xf24 -+#define NAND_READ_LOCATION_2 0xf28 -+#define NAND_READ_LOCATION_3 0xf2c -+#define NAND_READ_LOCATION_LAST_CW_0 0xf40 -+#define NAND_READ_LOCATION_LAST_CW_1 0xf44 -+#define NAND_READ_LOCATION_LAST_CW_2 0xf48 -+#define NAND_READ_LOCATION_LAST_CW_3 0xf4c -+ -+/* dummy register offsets, used by qcom_write_reg_dma */ -+#define NAND_DEV_CMD1_RESTORE 0xdead -+#define NAND_DEV_CMD_VLD_RESTORE 0xbeef -+ -+/* NAND_FLASH_CMD bits */ -+#define PAGE_ACC BIT(4) -+#define LAST_PAGE BIT(5) -+ -+/* NAND_FLASH_CHIP_SELECT bits */ -+#define NAND_DEV_SEL 0 -+#define DM_EN BIT(2) -+ -+/* NAND_FLASH_STATUS bits */ -+#define FS_OP_ERR BIT(4) -+#define FS_READY_BSY_N BIT(5) -+#define FS_MPU_ERR BIT(8) -+#define FS_DEVICE_STS_ERR BIT(16) -+#define FS_DEVICE_WP BIT(23) -+ -+/* NAND_BUFFER_STATUS bits */ -+#define BS_UNCORRECTABLE_BIT BIT(8) -+#define BS_CORRECTABLE_ERR_MSK 0x1f -+ -+/* NAND_DEVn_CFG0 bits */ -+#define DISABLE_STATUS_AFTER_WRITE 4 -+#define CW_PER_PAGE 6 -+#define UD_SIZE_BYTES 9 -+#define UD_SIZE_BYTES_MASK GENMASK(18, 9) -+#define ECC_PARITY_SIZE_BYTES_RS 19 -+#define SPARE_SIZE_BYTES 23 -+#define SPARE_SIZE_BYTES_MASK GENMASK(26, 23) -+#define NUM_ADDR_CYCLES 27 -+#define STATUS_BFR_READ 30 -+#define SET_RD_MODE_AFTER_STATUS 31 -+ -+/* NAND_DEVn_CFG0 bits */ -+#define DEV0_CFG1_ECC_DISABLE 0 -+#define WIDE_FLASH 1 -+#define NAND_RECOVERY_CYCLES 2 -+#define CS_ACTIVE_BSY 5 -+#define BAD_BLOCK_BYTE_NUM 6 -+#define BAD_BLOCK_IN_SPARE_AREA 16 -+#define WR_RD_BSY_GAP 17 -+#define ENABLE_BCH_ECC 27 -+ -+/* NAND_DEV0_ECC_CFG bits */ -+#define ECC_CFG_ECC_DISABLE 0 -+#define ECC_SW_RESET 1 -+#define ECC_MODE 4 -+#define ECC_PARITY_SIZE_BYTES_BCH 8 -+#define ECC_NUM_DATA_BYTES 16 -+#define ECC_NUM_DATA_BYTES_MASK GENMASK(25, 16) -+#define ECC_FORCE_CLK_OPEN 30 -+ -+/* NAND_DEV_CMD1 bits */ -+#define READ_ADDR 0 -+ -+/* NAND_DEV_CMD_VLD bits */ -+#define READ_START_VLD BIT(0) -+#define READ_STOP_VLD BIT(1) -+#define WRITE_START_VLD BIT(2) -+#define ERASE_START_VLD BIT(3) -+#define SEQ_READ_START_VLD BIT(4) -+ -+/* NAND_EBI2_ECC_BUF_CFG bits */ -+#define NUM_STEPS 0 -+ -+/* NAND_ERASED_CW_DETECT_CFG bits */ -+#define ERASED_CW_ECC_MASK 1 -+#define AUTO_DETECT_RES 0 -+#define MASK_ECC BIT(ERASED_CW_ECC_MASK) -+#define RESET_ERASED_DET BIT(AUTO_DETECT_RES) -+#define ACTIVE_ERASED_DET (0 << AUTO_DETECT_RES) -+#define CLR_ERASED_PAGE_DET (RESET_ERASED_DET | MASK_ECC) -+#define SET_ERASED_PAGE_DET (ACTIVE_ERASED_DET | MASK_ECC) -+ -+/* NAND_ERASED_CW_DETECT_STATUS bits */ -+#define PAGE_ALL_ERASED BIT(7) -+#define CODEWORD_ALL_ERASED BIT(6) -+#define PAGE_ERASED BIT(5) -+#define CODEWORD_ERASED BIT(4) -+#define ERASED_PAGE (PAGE_ALL_ERASED | PAGE_ERASED) -+#define ERASED_CW (CODEWORD_ALL_ERASED | CODEWORD_ERASED) -+ -+/* NAND_READ_LOCATION_n bits */ -+#define READ_LOCATION_OFFSET 0 -+#define READ_LOCATION_SIZE 16 -+#define READ_LOCATION_LAST 31 -+ -+/* Version Mask */ -+#define NAND_VERSION_MAJOR_MASK 0xf0000000 -+#define NAND_VERSION_MAJOR_SHIFT 28 -+#define NAND_VERSION_MINOR_MASK 0x0fff0000 -+#define NAND_VERSION_MINOR_SHIFT 16 -+ -+/* NAND OP_CMDs */ -+#define OP_PAGE_READ 0x2 -+#define OP_PAGE_READ_WITH_ECC 0x3 -+#define OP_PAGE_READ_WITH_ECC_SPARE 0x4 -+#define OP_PAGE_READ_ONFI_READ 0x5 -+#define OP_PROGRAM_PAGE 0x6 -+#define OP_PAGE_PROGRAM_WITH_ECC 0x7 -+#define OP_PROGRAM_PAGE_SPARE 0x9 -+#define OP_BLOCK_ERASE 0xa -+#define OP_CHECK_STATUS 0xc -+#define OP_FETCH_ID 0xb -+#define OP_RESET_DEVICE 0xd -+ -+/* Default Value for NAND_DEV_CMD_VLD */ -+#define NAND_DEV_CMD_VLD_VAL (READ_START_VLD | WRITE_START_VLD | \ -+ ERASE_START_VLD | SEQ_READ_START_VLD) -+ -+/* NAND_CTRL bits */ -+#define BAM_MODE_EN BIT(0) -+ -+/* -+ * the NAND controller performs reads/writes with ECC in 516 byte chunks. -+ * the driver calls the chunks 'step' or 'codeword' interchangeably -+ */ -+#define NANDC_STEP_SIZE 512 -+ -+/* -+ * the largest page size we support is 8K, this will have 16 steps/codewords -+ * of 512 bytes each -+ */ -+#define MAX_NUM_STEPS (SZ_8K / NANDC_STEP_SIZE) -+ -+/* we read at most 3 registers per codeword scan */ -+#define MAX_REG_RD (3 * MAX_NUM_STEPS) -+ -+/* ECC modes supported by the controller */ -+#define ECC_NONE BIT(0) -+#define ECC_RS_4BIT BIT(1) -+#define ECC_BCH_4BIT BIT(2) -+#define ECC_BCH_8BIT BIT(3) -+ -+/* -+ * Returns the actual register address for all NAND_DEV_ registers -+ * (i.e. NAND_DEV_CMD0, NAND_DEV_CMD1, NAND_DEV_CMD2 and NAND_DEV_CMD_VLD) -+ */ -+#define dev_cmd_reg_addr(nandc, reg) ((nandc)->props->dev_cmd_reg_start + (reg)) -+ -+/* Returns the NAND register physical address */ -+#define nandc_reg_phys(chip, offset) ((chip)->base_phys + (offset)) -+ -+/* Returns the dma address for reg read buffer */ -+#define reg_buf_dma_addr(chip, vaddr) \ -+ ((chip)->reg_read_dma + \ -+ ((u8 *)(vaddr) - (u8 *)(chip)->reg_read_buf)) -+ -+#define QPIC_PER_CW_CMD_ELEMENTS 32 -+#define QPIC_PER_CW_CMD_SGL 32 -+#define QPIC_PER_CW_DATA_SGL 8 -+ -+#define QPIC_NAND_COMPLETION_TIMEOUT msecs_to_jiffies(2000) -+ -+/* -+ * Flags used in DMA descriptor preparation helper functions -+ * (i.e. qcom_read_reg_dma/qcom_write_reg_dma/qcom_read_data_dma/qcom_write_data_dma) -+ */ -+/* Don't set the EOT in current tx BAM sgl */ -+#define NAND_BAM_NO_EOT BIT(0) -+/* Set the NWD flag in current BAM sgl */ -+#define NAND_BAM_NWD BIT(1) -+/* Finish writing in the current BAM sgl and start writing in another BAM sgl */ -+#define NAND_BAM_NEXT_SGL BIT(2) -+/* -+ * Erased codeword status is being used two times in single transfer so this -+ * flag will determine the current value of erased codeword status register -+ */ -+#define NAND_ERASED_CW_SET BIT(4) -+ -+#define MAX_ADDRESS_CYCLE 5 -+ -+/* -+ * This data type corresponds to the BAM transaction which will be used for all -+ * NAND transfers. -+ * @bam_ce - the array of BAM command elements -+ * @cmd_sgl - sgl for NAND BAM command pipe -+ * @data_sgl - sgl for NAND BAM consumer/producer pipe -+ * @last_data_desc - last DMA desc in data channel (tx/rx). -+ * @last_cmd_desc - last DMA desc in command channel. -+ * @txn_done - completion for NAND transfer. -+ * @bam_ce_pos - the index in bam_ce which is available for next sgl -+ * @bam_ce_start - the index in bam_ce which marks the start position ce -+ * for current sgl. It will be used for size calculation -+ * for current sgl -+ * @cmd_sgl_pos - current index in command sgl. -+ * @cmd_sgl_start - start index in command sgl. -+ * @tx_sgl_pos - current index in data sgl for tx. -+ * @tx_sgl_start - start index in data sgl for tx. -+ * @rx_sgl_pos - current index in data sgl for rx. -+ * @rx_sgl_start - start index in data sgl for rx. -+ */ -+struct bam_transaction { -+ struct bam_cmd_element *bam_ce; -+ struct scatterlist *cmd_sgl; -+ struct scatterlist *data_sgl; -+ struct dma_async_tx_descriptor *last_data_desc; -+ struct dma_async_tx_descriptor *last_cmd_desc; -+ struct completion txn_done; -+ u32 bam_ce_pos; -+ u32 bam_ce_start; -+ u32 cmd_sgl_pos; -+ u32 cmd_sgl_start; -+ u32 tx_sgl_pos; -+ u32 tx_sgl_start; -+ u32 rx_sgl_pos; -+ u32 rx_sgl_start; -+}; -+ -+/* -+ * This data type corresponds to the nand dma descriptor -+ * @dma_desc - low level DMA engine descriptor -+ * @list - list for desc_info -+ * -+ * @adm_sgl - sgl which will be used for single sgl dma descriptor. Only used by -+ * ADM -+ * @bam_sgl - sgl which will be used for dma descriptor. Only used by BAM -+ * @sgl_cnt - number of SGL in bam_sgl. Only used by BAM -+ * @dir - DMA transfer direction -+ */ -+struct desc_info { -+ struct dma_async_tx_descriptor *dma_desc; -+ struct list_head node; -+ -+ union { -+ struct scatterlist adm_sgl; -+ struct { -+ struct scatterlist *bam_sgl; -+ int sgl_cnt; -+ }; -+ }; -+ enum dma_data_direction dir; -+}; -+ -+/* -+ * holds the current register values that we want to write. acts as a contiguous -+ * chunk of memory which we use to write the controller registers through DMA. -+ */ -+struct nandc_regs { -+ __le32 cmd; -+ __le32 addr0; -+ __le32 addr1; -+ __le32 chip_sel; -+ __le32 exec; -+ -+ __le32 cfg0; -+ __le32 cfg1; -+ __le32 ecc_bch_cfg; -+ -+ __le32 clrflashstatus; -+ __le32 clrreadstatus; -+ -+ __le32 cmd1; -+ __le32 vld; -+ -+ __le32 orig_cmd1; -+ __le32 orig_vld; -+ -+ __le32 ecc_buf_cfg; -+ __le32 read_location0; -+ __le32 read_location1; -+ __le32 read_location2; -+ __le32 read_location3; -+ __le32 read_location_last0; -+ __le32 read_location_last1; -+ __le32 read_location_last2; -+ __le32 read_location_last3; -+ -+ __le32 erased_cw_detect_cfg_clr; -+ __le32 erased_cw_detect_cfg_set; -+}; -+ -+/* -+ * NAND controller data struct -+ * -+ * @dev: parent device -+ * -+ * @base: MMIO base -+ * -+ * @core_clk: controller clock -+ * @aon_clk: another controller clock -+ * -+ * @regs: a contiguous chunk of memory for DMA register -+ * writes. contains the register values to be -+ * written to controller -+ * -+ * @props: properties of current NAND controller, -+ * initialized via DT match data -+ * -+ * @controller: base controller structure -+ * @host_list: list containing all the chips attached to the -+ * controller -+ * -+ * @chan: dma channel -+ * @cmd_crci: ADM DMA CRCI for command flow control -+ * @data_crci: ADM DMA CRCI for data flow control -+ * -+ * @desc_list: DMA descriptor list (list of desc_infos) -+ * -+ * @data_buffer: our local DMA buffer for page read/writes, -+ * used when we can't use the buffer provided -+ * by upper layers directly -+ * @reg_read_buf: local buffer for reading back registers via DMA -+ * -+ * @base_phys: physical base address of controller registers -+ * @base_dma: dma base address of controller registers -+ * @reg_read_dma: contains dma address for register read buffer -+ * -+ * @buf_size/count/start: markers for chip->legacy.read_buf/write_buf -+ * functions -+ * @max_cwperpage: maximum QPIC codewords required. calculated -+ * from all connected NAND devices pagesize -+ * -+ * @reg_read_pos: marker for data read in reg_read_buf -+ * -+ * @cmd1/vld: some fixed controller register values -+ * -+ * @exec_opwrite: flag to select correct number of code word -+ * while reading status -+ */ -+struct qcom_nand_controller { -+ struct device *dev; -+ -+ void __iomem *base; -+ -+ struct clk *core_clk; -+ struct clk *aon_clk; -+ -+ struct nandc_regs *regs; -+ struct bam_transaction *bam_txn; -+ -+ const struct qcom_nandc_props *props; -+ -+ struct nand_controller *controller; -+ struct list_head host_list; -+ -+ union { -+ /* will be used only by QPIC for BAM DMA */ -+ struct { -+ struct dma_chan *tx_chan; -+ struct dma_chan *rx_chan; -+ struct dma_chan *cmd_chan; -+ }; -+ -+ /* will be used only by EBI2 for ADM DMA */ -+ struct { -+ struct dma_chan *chan; -+ unsigned int cmd_crci; -+ unsigned int data_crci; -+ }; -+ }; -+ -+ struct list_head desc_list; -+ -+ u8 *data_buffer; -+ __le32 *reg_read_buf; -+ -+ phys_addr_t base_phys; -+ dma_addr_t base_dma; -+ dma_addr_t reg_read_dma; -+ -+ int buf_size; -+ int buf_count; -+ int buf_start; -+ unsigned int max_cwperpage; -+ -+ int reg_read_pos; -+ -+ u32 cmd1, vld; -+ bool exec_opwrite; -+}; -+ -+/* -+ * This data type corresponds to the NAND controller properties which varies -+ * among different NAND controllers. -+ * @ecc_modes - ecc mode for NAND -+ * @dev_cmd_reg_start - NAND_DEV_CMD_* registers starting offset -+ * @supports_bam - whether NAND controller is using BAM -+ * @nandc_part_of_qpic - whether NAND controller is part of qpic IP -+ * @qpic_version2 - flag to indicate QPIC IP version 2 -+ * @use_codeword_fixup - whether NAND has different layout for boot partitions -+ */ -+struct qcom_nandc_props { -+ u32 ecc_modes; -+ u32 dev_cmd_reg_start; -+ bool supports_bam; -+ bool nandc_part_of_qpic; -+ bool qpic_version2; -+ bool use_codeword_fixup; -+}; -+ -+void qcom_free_bam_transaction(struct qcom_nand_controller *nandc); -+struct bam_transaction *qcom_alloc_bam_transaction(struct qcom_nand_controller *nandc); -+void qcom_clear_bam_transaction(struct qcom_nand_controller *nandc); -+void qcom_qpic_bam_dma_done(void *data); -+void qcom_nandc_dev_to_mem(struct qcom_nand_controller *nandc, bool is_cpu); -+int qcom_prepare_bam_async_desc(struct qcom_nand_controller *nandc, -+ struct dma_chan *chan, unsigned long flags); -+int qcom_prep_bam_dma_desc_cmd(struct qcom_nand_controller *nandc, bool read, -+ int reg_off, const void *vaddr, int size, unsigned int flags); -+int qcom_prep_bam_dma_desc_data(struct qcom_nand_controller *nandc, bool read, -+ const void *vaddr, int size, unsigned int flags); -+int qcom_prep_adm_dma_desc(struct qcom_nand_controller *nandc, bool read, int reg_off, -+ const void *vaddr, int size, bool flow_control); -+int qcom_read_reg_dma(struct qcom_nand_controller *nandc, int first, int num_regs, -+ unsigned int flags); -+int qcom_write_reg_dma(struct qcom_nand_controller *nandc, __le32 *vaddr, int first, -+ int num_regs, unsigned int flags); -+int qcom_read_data_dma(struct qcom_nand_controller *nandc, int reg_off, const u8 *vaddr, -+ int size, unsigned int flags); -+int qcom_write_data_dma(struct qcom_nand_controller *nandc, int reg_off, const u8 *vaddr, -+ int size, unsigned int flags); -+int qcom_submit_descs(struct qcom_nand_controller *nandc); -+void qcom_clear_read_regs(struct qcom_nand_controller *nandc); -+void qcom_nandc_unalloc(struct qcom_nand_controller *nandc); -+int qcom_nandc_alloc(struct qcom_nand_controller *nandc); -+#endif -+ diff --git a/target/linux/generic/backport-6.18/410-04-v6.14-mtd-rawnand-qcom-use-FIELD_PREP-and-GENMASK.patch b/target/linux/generic/backport-6.18/410-04-v6.14-mtd-rawnand-qcom-use-FIELD_PREP-and-GENMASK.patch deleted file mode 100644 index c19f681e9d..0000000000 --- a/target/linux/generic/backport-6.18/410-04-v6.14-mtd-rawnand-qcom-use-FIELD_PREP-and-GENMASK.patch +++ /dev/null @@ -1,198 +0,0 @@ -From 0c08080fd71cd5dd59643104b39d3c89d793ab3c Mon Sep 17 00:00:00 2001 -From: Md Sadre Alam -Date: Wed, 20 Nov 2024 14:45:03 +0530 -Subject: [PATCH 4/4] mtd: rawnand: qcom: use FIELD_PREP and GENMASK - -Use the bitfield macro FIELD_PREP, and GENMASK to -do the shift and mask in one go. This makes the code -more readable. - -Reviewed-by: Konrad Dybcio -Signed-off-by: Md Sadre Alam -Signed-off-by: Miquel Raynal ---- - drivers/mtd/nand/raw/qcom_nandc.c | 97 ++++++++++++++-------------- - include/linux/mtd/nand-qpic-common.h | 31 +++++---- - 2 files changed, 67 insertions(+), 61 deletions(-) - ---- a/drivers/mtd/nand/raw/qcom_nandc.c -+++ b/drivers/mtd/nand/raw/qcom_nandc.c -@@ -281,7 +281,7 @@ static void update_rw_regs(struct qcom_n - (num_cw - 1) << CW_PER_PAGE); - - cfg1 = cpu_to_le32(host->cfg1_raw); -- ecc_bch_cfg = cpu_to_le32(1 << ECC_CFG_ECC_DISABLE); -+ ecc_bch_cfg = cpu_to_le32(ECC_CFG_ECC_DISABLE); - } - - nandc->regs->cmd = cmd; -@@ -1494,42 +1494,41 @@ static int qcom_nand_attach_chip(struct - host->cw_size = host->cw_data + ecc->bytes; - bad_block_byte = mtd->writesize - host->cw_size * (cwperpage - 1) + 1; - -- host->cfg0 = (cwperpage - 1) << CW_PER_PAGE -- | host->cw_data << UD_SIZE_BYTES -- | 0 << DISABLE_STATUS_AFTER_WRITE -- | 5 << NUM_ADDR_CYCLES -- | host->ecc_bytes_hw << ECC_PARITY_SIZE_BYTES_RS -- | 0 << STATUS_BFR_READ -- | 1 << SET_RD_MODE_AFTER_STATUS -- | host->spare_bytes << SPARE_SIZE_BYTES; -- -- host->cfg1 = 7 << NAND_RECOVERY_CYCLES -- | 0 << CS_ACTIVE_BSY -- | bad_block_byte << BAD_BLOCK_BYTE_NUM -- | 0 << BAD_BLOCK_IN_SPARE_AREA -- | 2 << WR_RD_BSY_GAP -- | wide_bus << WIDE_FLASH -- | host->bch_enabled << ENABLE_BCH_ECC; -- -- host->cfg0_raw = (cwperpage - 1) << CW_PER_PAGE -- | host->cw_size << UD_SIZE_BYTES -- | 5 << NUM_ADDR_CYCLES -- | 0 << SPARE_SIZE_BYTES; -- -- host->cfg1_raw = 7 << NAND_RECOVERY_CYCLES -- | 0 << CS_ACTIVE_BSY -- | 17 << BAD_BLOCK_BYTE_NUM -- | 1 << BAD_BLOCK_IN_SPARE_AREA -- | 2 << WR_RD_BSY_GAP -- | wide_bus << WIDE_FLASH -- | 1 << DEV0_CFG1_ECC_DISABLE; -- -- host->ecc_bch_cfg = !host->bch_enabled << ECC_CFG_ECC_DISABLE -- | 0 << ECC_SW_RESET -- | host->cw_data << ECC_NUM_DATA_BYTES -- | 1 << ECC_FORCE_CLK_OPEN -- | ecc_mode << ECC_MODE -- | host->ecc_bytes_hw << ECC_PARITY_SIZE_BYTES_BCH; -+ host->cfg0 = FIELD_PREP(CW_PER_PAGE_MASK, (cwperpage - 1)) | -+ FIELD_PREP(UD_SIZE_BYTES_MASK, host->cw_data) | -+ FIELD_PREP(DISABLE_STATUS_AFTER_WRITE, 0) | -+ FIELD_PREP(NUM_ADDR_CYCLES_MASK, 5) | -+ FIELD_PREP(ECC_PARITY_SIZE_BYTES_RS, host->ecc_bytes_hw) | -+ FIELD_PREP(STATUS_BFR_READ, 0) | -+ FIELD_PREP(SET_RD_MODE_AFTER_STATUS, 1) | -+ FIELD_PREP(SPARE_SIZE_BYTES_MASK, host->spare_bytes); -+ -+ host->cfg1 = FIELD_PREP(NAND_RECOVERY_CYCLES_MASK, 7) | -+ FIELD_PREP(BAD_BLOCK_BYTE_NUM_MASK, bad_block_byte) | -+ FIELD_PREP(BAD_BLOCK_IN_SPARE_AREA, 0) | -+ FIELD_PREP(WR_RD_BSY_GAP_MASK, 2) | -+ FIELD_PREP(WIDE_FLASH, wide_bus) | -+ FIELD_PREP(ENABLE_BCH_ECC, host->bch_enabled); -+ -+ host->cfg0_raw = FIELD_PREP(CW_PER_PAGE_MASK, (cwperpage - 1)) | -+ FIELD_PREP(UD_SIZE_BYTES_MASK, host->cw_size) | -+ FIELD_PREP(NUM_ADDR_CYCLES_MASK, 5) | -+ FIELD_PREP(SPARE_SIZE_BYTES_MASK, 0); -+ -+ host->cfg1_raw = FIELD_PREP(NAND_RECOVERY_CYCLES_MASK, 7) | -+ FIELD_PREP(CS_ACTIVE_BSY, 0) | -+ FIELD_PREP(BAD_BLOCK_BYTE_NUM_MASK, 17) | -+ FIELD_PREP(BAD_BLOCK_IN_SPARE_AREA, 1) | -+ FIELD_PREP(WR_RD_BSY_GAP_MASK, 2) | -+ FIELD_PREP(WIDE_FLASH, wide_bus) | -+ FIELD_PREP(DEV0_CFG1_ECC_DISABLE, 1); -+ -+ host->ecc_bch_cfg = FIELD_PREP(ECC_CFG_ECC_DISABLE, !host->bch_enabled) | -+ FIELD_PREP(ECC_SW_RESET, 0) | -+ FIELD_PREP(ECC_NUM_DATA_BYTES_MASK, host->cw_data) | -+ FIELD_PREP(ECC_FORCE_CLK_OPEN, 1) | -+ FIELD_PREP(ECC_MODE_MASK, ecc_mode) | -+ FIELD_PREP(ECC_PARITY_SIZE_BYTES_BCH_MASK, host->ecc_bytes_hw); - - if (!nandc->props->qpic_version2) - host->ecc_buf_cfg = 0x203 << NUM_STEPS; -@@ -1887,21 +1886,21 @@ static int qcom_param_page_type_exec(str - nandc->regs->addr0 = 0; - nandc->regs->addr1 = 0; - -- nandc->regs->cfg0 = cpu_to_le32(0 << CW_PER_PAGE | -- 512 << UD_SIZE_BYTES | -- 5 << NUM_ADDR_CYCLES | -- 0 << SPARE_SIZE_BYTES); -- -- nandc->regs->cfg1 = cpu_to_le32(7 << NAND_RECOVERY_CYCLES | -- 0 << CS_ACTIVE_BSY | -- 17 << BAD_BLOCK_BYTE_NUM | -- 1 << BAD_BLOCK_IN_SPARE_AREA | -- 2 << WR_RD_BSY_GAP | -- 0 << WIDE_FLASH | -- 1 << DEV0_CFG1_ECC_DISABLE); -+ host->cfg0 = FIELD_PREP(CW_PER_PAGE_MASK, 0) | -+ FIELD_PREP(UD_SIZE_BYTES_MASK, 512) | -+ FIELD_PREP(NUM_ADDR_CYCLES_MASK, 5) | -+ FIELD_PREP(SPARE_SIZE_BYTES_MASK, 0); -+ -+ host->cfg1 = FIELD_PREP(NAND_RECOVERY_CYCLES_MASK, 7) | -+ FIELD_PREP(BAD_BLOCK_BYTE_NUM_MASK, 17) | -+ FIELD_PREP(CS_ACTIVE_BSY, 0) | -+ FIELD_PREP(BAD_BLOCK_IN_SPARE_AREA, 1) | -+ FIELD_PREP(WR_RD_BSY_GAP_MASK, 2) | -+ FIELD_PREP(WIDE_FLASH, 0) | -+ FIELD_PREP(DEV0_CFG1_ECC_DISABLE, 1); - - if (!nandc->props->qpic_version2) -- nandc->regs->ecc_buf_cfg = cpu_to_le32(1 << ECC_CFG_ECC_DISABLE); -+ nandc->regs->ecc_buf_cfg = cpu_to_le32(ECC_CFG_ECC_DISABLE); - - /* configure CMD1 and VLD for ONFI param probing in QPIC v1 */ - if (!nandc->props->qpic_version2) { ---- a/include/linux/mtd/nand-qpic-common.h -+++ b/include/linux/mtd/nand-qpic-common.h -@@ -70,35 +70,42 @@ - #define BS_CORRECTABLE_ERR_MSK 0x1f - - /* NAND_DEVn_CFG0 bits */ --#define DISABLE_STATUS_AFTER_WRITE 4 -+#define DISABLE_STATUS_AFTER_WRITE BIT(4) - #define CW_PER_PAGE 6 -+#define CW_PER_PAGE_MASK GENMASK(8, 6) - #define UD_SIZE_BYTES 9 - #define UD_SIZE_BYTES_MASK GENMASK(18, 9) --#define ECC_PARITY_SIZE_BYTES_RS 19 -+#define ECC_PARITY_SIZE_BYTES_RS GENMASK(22, 19) - #define SPARE_SIZE_BYTES 23 - #define SPARE_SIZE_BYTES_MASK GENMASK(26, 23) - #define NUM_ADDR_CYCLES 27 --#define STATUS_BFR_READ 30 --#define SET_RD_MODE_AFTER_STATUS 31 -+#define NUM_ADDR_CYCLES_MASK GENMASK(29, 27) -+#define STATUS_BFR_READ BIT(30) -+#define SET_RD_MODE_AFTER_STATUS BIT(31) - - /* NAND_DEVn_CFG0 bits */ --#define DEV0_CFG1_ECC_DISABLE 0 --#define WIDE_FLASH 1 -+#define DEV0_CFG1_ECC_DISABLE BIT(0) -+#define WIDE_FLASH BIT(1) - #define NAND_RECOVERY_CYCLES 2 --#define CS_ACTIVE_BSY 5 -+#define NAND_RECOVERY_CYCLES_MASK GENMASK(4, 2) -+#define CS_ACTIVE_BSY BIT(5) - #define BAD_BLOCK_BYTE_NUM 6 --#define BAD_BLOCK_IN_SPARE_AREA 16 -+#define BAD_BLOCK_BYTE_NUM_MASK GENMASK(15, 6) -+#define BAD_BLOCK_IN_SPARE_AREA BIT(16) - #define WR_RD_BSY_GAP 17 --#define ENABLE_BCH_ECC 27 -+#define WR_RD_BSY_GAP_MASK GENMASK(22, 17) -+#define ENABLE_BCH_ECC BIT(27) - - /* NAND_DEV0_ECC_CFG bits */ --#define ECC_CFG_ECC_DISABLE 0 --#define ECC_SW_RESET 1 -+#define ECC_CFG_ECC_DISABLE BIT(0) -+#define ECC_SW_RESET BIT(1) - #define ECC_MODE 4 -+#define ECC_MODE_MASK GENMASK(5, 4) - #define ECC_PARITY_SIZE_BYTES_BCH 8 -+#define ECC_PARITY_SIZE_BYTES_BCH_MASK GENMASK(12, 8) - #define ECC_NUM_DATA_BYTES 16 - #define ECC_NUM_DATA_BYTES_MASK GENMASK(25, 16) --#define ECC_FORCE_CLK_OPEN 30 -+#define ECC_FORCE_CLK_OPEN BIT(30) - - /* NAND_DEV_CMD1 bits */ - #define READ_ADDR 0 diff --git a/target/linux/generic/backport-6.18/410-05-v6.14-mtd-rawnand-qcom-fix-broken-config-in-qcom_param_pag.patch b/target/linux/generic/backport-6.18/410-05-v6.14-mtd-rawnand-qcom-fix-broken-config-in-qcom_param_pag.patch deleted file mode 100644 index 238a1f9d93..0000000000 --- a/target/linux/generic/backport-6.18/410-05-v6.14-mtd-rawnand-qcom-fix-broken-config-in-qcom_param_pag.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 9d4ffbcfde283f2a87ea45128ddf7e6651facdd9 Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Fri, 7 Feb 2025 20:42:38 +0100 -Subject: [PATCH] mtd: rawnand: qcom: fix broken config in - qcom_param_page_type_exec - -Fix broken config in qcom_param_page_type_exec caused by copy-paste error -from commit 0c08080fd71c ("mtd: rawnand: qcom: use FIELD_PREP and GENMASK") - -In qcom_param_page_type_exec the value needs to be set to -nandc->regs->cfg0 instead of host->cfg0. This wrong configuration caused -the Qcom NANDC driver to malfunction on any device that makes use of it -(IPQ806x, IPQ40xx, IPQ807x, IPQ60xx) with the following error: - -[ 0.885369] nand: device found, Manufacturer ID: 0x2c, Chip ID: 0xaa -[ 0.885909] nand: Micron NAND 256MiB 1,8V 8-bit -[ 0.892499] nand: 256 MiB, SLC, erase size: 128 KiB, page size: 2048, OOB size: 64 -[ 0.896823] nand: ECC (step, strength) = (512, 8) does not fit in OOB -[ 0.896836] qcom-nandc 79b0000.nand-controller: No valid ECC settings possible -[ 0.910996] bam-dma-engine 7984000.dma-controller: Cannot free busy channel -[ 0.918070] qcom-nandc: probe of 79b0000.nand-controller failed with error -28 - -Restore original configuration fix the problem and makes the driver work -again. - -Cc: stable@vger.kernel.org -Fixes: 0c08080fd71c ("mtd: rawnand: qcom: use FIELD_PREP and GENMASK") -Signed-off-by: Christian Marangi ---- - drivers/mtd/nand/raw/qcom_nandc.c | 24 ++++++++++++------------ - 1 file changed, 12 insertions(+), 12 deletions(-) - ---- a/drivers/mtd/nand/raw/qcom_nandc.c -+++ b/drivers/mtd/nand/raw/qcom_nandc.c -@@ -1886,18 +1886,18 @@ static int qcom_param_page_type_exec(str - nandc->regs->addr0 = 0; - nandc->regs->addr1 = 0; - -- host->cfg0 = FIELD_PREP(CW_PER_PAGE_MASK, 0) | -- FIELD_PREP(UD_SIZE_BYTES_MASK, 512) | -- FIELD_PREP(NUM_ADDR_CYCLES_MASK, 5) | -- FIELD_PREP(SPARE_SIZE_BYTES_MASK, 0); -+ nandc->regs->cfg0 = FIELD_PREP(CW_PER_PAGE_MASK, 0) | -+ FIELD_PREP(UD_SIZE_BYTES_MASK, 512) | -+ FIELD_PREP(NUM_ADDR_CYCLES_MASK, 5) | -+ FIELD_PREP(SPARE_SIZE_BYTES_MASK, 0); - -- host->cfg1 = FIELD_PREP(NAND_RECOVERY_CYCLES_MASK, 7) | -- FIELD_PREP(BAD_BLOCK_BYTE_NUM_MASK, 17) | -- FIELD_PREP(CS_ACTIVE_BSY, 0) | -- FIELD_PREP(BAD_BLOCK_IN_SPARE_AREA, 1) | -- FIELD_PREP(WR_RD_BSY_GAP_MASK, 2) | -- FIELD_PREP(WIDE_FLASH, 0) | -- FIELD_PREP(DEV0_CFG1_ECC_DISABLE, 1); -+ nandc->regs->cfg1 = FIELD_PREP(NAND_RECOVERY_CYCLES_MASK, 7) | -+ FIELD_PREP(BAD_BLOCK_BYTE_NUM_MASK, 17) | -+ FIELD_PREP(CS_ACTIVE_BSY, 0) | -+ FIELD_PREP(BAD_BLOCK_IN_SPARE_AREA, 1) | -+ FIELD_PREP(WR_RD_BSY_GAP_MASK, 2) | -+ FIELD_PREP(WIDE_FLASH, 0) | -+ FIELD_PREP(DEV0_CFG1_ECC_DISABLE, 1); - - if (!nandc->props->qpic_version2) - nandc->regs->ecc_buf_cfg = cpu_to_le32(ECC_CFG_ECC_DISABLE); diff --git a/target/linux/generic/backport-6.18/410-06-v6.14-mtd-rawnand-qcom-Fix-build-issue-on-x86-architecture.patch b/target/linux/generic/backport-6.18/410-06-v6.14-mtd-rawnand-qcom-Fix-build-issue-on-x86-architecture.patch deleted file mode 100644 index 67beed38d5..0000000000 --- a/target/linux/generic/backport-6.18/410-06-v6.14-mtd-rawnand-qcom-Fix-build-issue-on-x86-architecture.patch +++ /dev/null @@ -1,77 +0,0 @@ -From b9371866799d67a80be0ea9e01bd41987db22f26 Mon Sep 17 00:00:00 2001 -From: Md Sadre Alam -Date: Mon, 6 Jan 2025 18:45:58 +0530 -Subject: [PATCH] mtd: rawnand: qcom: Fix build issue on x86 architecture -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Fix a buffer overflow issue in qcom_clear_bam_transaction by using -struct_group to group related fields and avoid FORTIFY_SOURCE warnings. - -On x86 architecture, the following error occurs due to warnings being -treated as errors: - -In function ‘fortify_memset_chk’, - inlined from ‘qcom_clear_bam_transaction’ at -drivers/mtd/nand/qpic_common.c:88:2: -./include/linux/fortify-string.h:480:25: error: call to ‘__write_overflow_field’ -declared with attribute warning: detected write beyond size of field -(1st parameter); maybe use struct_group()? [-Werror=attribute-warning] - 480 | __write_overflow_field(p_size_field, size); - | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - LD [M] drivers/mtd/nand/nandcore.o - CC [M] drivers/w1/masters/mxc_w1.o -cc1: all warnings being treated as errors - -This patch addresses the issue by grouping the related fields in -struct bam_transaction using struct_group and updating the memset call -accordingly. - -Fixes: 8c52932da5e6 ("mtd: rawnand: qcom: cleanup qcom_nandc driver") -Signed-off-by: Md Sadre Alam -Signed-off-by: Miquel Raynal ---- - drivers/mtd/nand/qpic_common.c | 2 +- - include/linux/mtd/nand-qpic-common.h | 19 +++++++++++-------- - 2 files changed, 12 insertions(+), 9 deletions(-) - ---- a/drivers/mtd/nand/qpic_common.c -+++ b/drivers/mtd/nand/qpic_common.c -@@ -85,7 +85,7 @@ void qcom_clear_bam_transaction(struct q - if (!nandc->props->supports_bam) - return; - -- memset(&bam_txn->bam_ce_pos, 0, sizeof(u32) * 8); -+ memset(&bam_txn->bam_positions, 0, sizeof(bam_txn->bam_positions)); - bam_txn->last_data_desc = NULL; - - sg_init_table(bam_txn->cmd_sgl, nandc->max_cwperpage * ---- a/include/linux/mtd/nand-qpic-common.h -+++ b/include/linux/mtd/nand-qpic-common.h -@@ -254,14 +254,17 @@ struct bam_transaction { - struct dma_async_tx_descriptor *last_data_desc; - struct dma_async_tx_descriptor *last_cmd_desc; - struct completion txn_done; -- u32 bam_ce_pos; -- u32 bam_ce_start; -- u32 cmd_sgl_pos; -- u32 cmd_sgl_start; -- u32 tx_sgl_pos; -- u32 tx_sgl_start; -- u32 rx_sgl_pos; -- u32 rx_sgl_start; -+ struct_group(bam_positions, -+ u32 bam_ce_pos; -+ u32 bam_ce_start; -+ u32 cmd_sgl_pos; -+ u32 cmd_sgl_start; -+ u32 tx_sgl_pos; -+ u32 tx_sgl_start; -+ u32 rx_sgl_pos; -+ u32 rx_sgl_start; -+ -+ ); - }; - - /* diff --git a/target/linux/generic/backport-6.18/410-07-v6.15-spi-spi-qpic-add-driver-for-QCOM-SPI-NAND-flash-Inte.patch b/target/linux/generic/backport-6.18/410-07-v6.15-spi-spi-qpic-add-driver-for-QCOM-SPI-NAND-flash-Inte.patch deleted file mode 100644 index 310d90233f..0000000000 --- a/target/linux/generic/backport-6.18/410-07-v6.15-spi-spi-qpic-add-driver-for-QCOM-SPI-NAND-flash-Inte.patch +++ /dev/null @@ -1,1737 +0,0 @@ -From 7304d1909080ef0c9da703500a97f46c98393fcd Mon Sep 17 00:00:00 2001 -From: Md Sadre Alam -Date: Mon, 24 Feb 2025 16:44:14 +0530 -Subject: [PATCH] spi: spi-qpic: add driver for QCOM SPI NAND flash Interface - -This driver implements support for the SPI-NAND mode of QCOM NAND Flash -Interface as a SPI-MEM controller with pipelined ECC capability. - -Co-developed-by: Sricharan Ramabadhran -Signed-off-by: Sricharan Ramabadhran -Co-developed-by: Varadarajan Narayanan -Signed-off-by: Varadarajan Narayanan -Signed-off-by: Md Sadre Alam -Link: https://patch.msgid.link/20250224111414.2809669-3-quic_mdalam@quicinc.com -Signed-off-by: Mark Brown ---- - drivers/mtd/nand/Makefile | 4 + - drivers/spi/Kconfig | 9 + - drivers/spi/Makefile | 1 + - drivers/spi/spi-qpic-snand.c | 1631 ++++++++++++++++++++++++++ - include/linux/mtd/nand-qpic-common.h | 7 + - 5 files changed, 1652 insertions(+) - create mode 100644 drivers/spi/spi-qpic-snand.c - ---- a/drivers/mtd/nand/Makefile -+++ b/drivers/mtd/nand/Makefile -@@ -3,7 +3,11 @@ - nandcore-objs := core.o bbt.o - obj-$(CONFIG_MTD_NAND_CORE) += nandcore.o - obj-$(CONFIG_MTD_NAND_ECC_MEDIATEK) += ecc-mtk.o -+ifeq ($(CONFIG_SPI_QPIC_SNAND),y) -+obj-$(CONFIG_SPI_QPIC_SNAND) += qpic_common.o -+else - obj-$(CONFIG_MTD_NAND_QCOM) += qpic_common.o -+endif - obj-y += onenand/ - obj-y += raw/ - obj-y += spi/ ---- a/drivers/spi/Kconfig -+++ b/drivers/spi/Kconfig -@@ -898,6 +898,15 @@ config SPI_QCOM_QSPI - help - QSPI(Quad SPI) driver for Qualcomm QSPI controller. - -+config SPI_QPIC_SNAND -+ bool "QPIC SNAND controller" -+ depends on ARCH_QCOM || COMPILE_TEST -+ select MTD -+ help -+ QPIC_SNAND (QPIC SPI NAND) driver for Qualcomm QPIC controller. -+ QPIC controller supports both parallel nand and serial nand. -+ This config will enable serial nand driver for QPIC controller. -+ - config SPI_QUP - tristate "Qualcomm SPI controller with QUP interface" - depends on ARCH_QCOM || COMPILE_TEST ---- a/drivers/spi/Makefile -+++ b/drivers/spi/Makefile -@@ -114,6 +114,7 @@ obj-$(CONFIG_SPI_PXA2XX) += spi-pxa2xx- - obj-$(CONFIG_SPI_PXA2XX_PCI) += spi-pxa2xx-pci.o - obj-$(CONFIG_SPI_QCOM_GENI) += spi-geni-qcom.o - obj-$(CONFIG_SPI_QCOM_QSPI) += spi-qcom-qspi.o -+obj-$(CONFIG_SPI_QPIC_SNAND) += spi-qpic-snand.o - obj-$(CONFIG_SPI_QUP) += spi-qup.o - obj-$(CONFIG_SPI_ROCKCHIP) += spi-rockchip.o - obj-$(CONFIG_SPI_ROCKCHIP_SFC) += spi-rockchip-sfc.o ---- /dev/null -+++ b/drivers/spi/spi-qpic-snand.c -@@ -0,0 +1,1631 @@ -+/* -+ * SPDX-License-Identifier: GPL-2.0 -+ * -+ * Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved. -+ * -+ * Authors: -+ * Md Sadre Alam -+ * Sricharan R -+ * Varadarajan Narayanan -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define NAND_FLASH_SPI_CFG 0xc0 -+#define NAND_NUM_ADDR_CYCLES 0xc4 -+#define NAND_BUSY_CHECK_WAIT_CNT 0xc8 -+#define NAND_FLASH_FEATURES 0xf64 -+ -+/* QSPI NAND config reg bits */ -+#define LOAD_CLK_CNTR_INIT_EN BIT(28) -+#define CLK_CNTR_INIT_VAL_VEC 0x924 -+#define CLK_CNTR_INIT_VAL_VEC_MASK GENMASK(27, 16) -+#define FEA_STATUS_DEV_ADDR 0xc0 -+#define FEA_STATUS_DEV_ADDR_MASK GENMASK(15, 8) -+#define SPI_CFG BIT(0) -+#define SPI_NUM_ADDR 0xDA4DB -+#define SPI_WAIT_CNT 0x10 -+#define QPIC_QSPI_NUM_CS 1 -+#define SPI_TRANSFER_MODE_x1 BIT(29) -+#define SPI_TRANSFER_MODE_x4 (3 << 29) -+#define SPI_WP BIT(28) -+#define SPI_HOLD BIT(27) -+#define QPIC_SET_FEATURE BIT(31) -+ -+#define SPINAND_RESET 0xff -+#define SPINAND_READID 0x9f -+#define SPINAND_GET_FEATURE 0x0f -+#define SPINAND_SET_FEATURE 0x1f -+#define SPINAND_READ 0x13 -+#define SPINAND_ERASE 0xd8 -+#define SPINAND_WRITE_EN 0x06 -+#define SPINAND_PROGRAM_EXECUTE 0x10 -+#define SPINAND_PROGRAM_LOAD 0x84 -+ -+#define ACC_FEATURE 0xe -+#define BAD_BLOCK_MARKER_SIZE 0x2 -+#define OOB_BUF_SIZE 128 -+#define ecceng_to_qspi(eng) container_of(eng, struct qpic_spi_nand, ecc_eng) -+ -+struct qpic_snand_op { -+ u32 cmd_reg; -+ u32 addr1_reg; -+ u32 addr2_reg; -+}; -+ -+struct snandc_read_status { -+ __le32 snandc_flash; -+ __le32 snandc_buffer; -+ __le32 snandc_erased_cw; -+}; -+ -+/* -+ * ECC state struct -+ * @corrected: ECC corrected -+ * @bitflips: Max bit flip -+ * @failed: ECC failed -+ */ -+struct qcom_ecc_stats { -+ u32 corrected; -+ u32 bitflips; -+ u32 failed; -+}; -+ -+struct qpic_ecc { -+ struct device *dev; -+ int ecc_bytes_hw; -+ int spare_bytes; -+ int bbm_size; -+ int ecc_mode; -+ int bytes; -+ int steps; -+ int step_size; -+ int strength; -+ int cw_size; -+ int cw_data; -+ u32 cfg0; -+ u32 cfg1; -+ u32 cfg0_raw; -+ u32 cfg1_raw; -+ u32 ecc_buf_cfg; -+ u32 ecc_bch_cfg; -+ u32 clrflashstatus; -+ u32 clrreadstatus; -+ bool bch_enabled; -+}; -+ -+struct qpic_spi_nand { -+ struct qcom_nand_controller *snandc; -+ struct spi_controller *ctlr; -+ struct mtd_info *mtd; -+ struct clk *iomacro_clk; -+ struct qpic_ecc *ecc; -+ struct qcom_ecc_stats ecc_stats; -+ struct nand_ecc_engine ecc_eng; -+ u8 *data_buf; -+ u8 *oob_buf; -+ u32 wlen; -+ __le32 addr1; -+ __le32 addr2; -+ __le32 cmd; -+ u32 num_cw; -+ bool oob_rw; -+ bool page_rw; -+ bool raw_rw; -+}; -+ -+static void qcom_spi_set_read_loc_first(struct qcom_nand_controller *snandc, -+ int reg, int cw_offset, int read_size, -+ int is_last_read_loc) -+{ -+ __le32 locreg_val; -+ u32 val = (((cw_offset) << READ_LOCATION_OFFSET) | -+ ((read_size) << READ_LOCATION_SIZE) | ((is_last_read_loc) -+ << READ_LOCATION_LAST)); -+ -+ locreg_val = cpu_to_le32(val); -+ -+ if (reg == NAND_READ_LOCATION_0) -+ snandc->regs->read_location0 = locreg_val; -+ else if (reg == NAND_READ_LOCATION_1) -+ snandc->regs->read_location1 = locreg_val; -+ else if (reg == NAND_READ_LOCATION_2) -+ snandc->regs->read_location1 = locreg_val; -+ else if (reg == NAND_READ_LOCATION_3) -+ snandc->regs->read_location3 = locreg_val; -+} -+ -+static void qcom_spi_set_read_loc_last(struct qcom_nand_controller *snandc, -+ int reg, int cw_offset, int read_size, -+ int is_last_read_loc) -+{ -+ __le32 locreg_val; -+ u32 val = (((cw_offset) << READ_LOCATION_OFFSET) | -+ ((read_size) << READ_LOCATION_SIZE) | ((is_last_read_loc) -+ << READ_LOCATION_LAST)); -+ -+ locreg_val = cpu_to_le32(val); -+ -+ if (reg == NAND_READ_LOCATION_LAST_CW_0) -+ snandc->regs->read_location_last0 = locreg_val; -+ else if (reg == NAND_READ_LOCATION_LAST_CW_1) -+ snandc->regs->read_location_last1 = locreg_val; -+ else if (reg == NAND_READ_LOCATION_LAST_CW_2) -+ snandc->regs->read_location_last2 = locreg_val; -+ else if (reg == NAND_READ_LOCATION_LAST_CW_3) -+ snandc->regs->read_location_last3 = locreg_val; -+} -+ -+static struct qcom_nand_controller *nand_to_qcom_snand(struct nand_device *nand) -+{ -+ struct nand_ecc_engine *eng = nand->ecc.engine; -+ struct qpic_spi_nand *qspi = ecceng_to_qspi(eng); -+ -+ return qspi->snandc; -+} -+ -+static int qcom_spi_init(struct qcom_nand_controller *snandc) -+{ -+ u32 snand_cfg_val = 0x0; -+ int ret; -+ -+ snand_cfg_val = FIELD_PREP(CLK_CNTR_INIT_VAL_VEC_MASK, CLK_CNTR_INIT_VAL_VEC) | -+ FIELD_PREP(LOAD_CLK_CNTR_INIT_EN, 0) | -+ FIELD_PREP(FEA_STATUS_DEV_ADDR_MASK, FEA_STATUS_DEV_ADDR) | -+ FIELD_PREP(SPI_CFG, 0); -+ -+ snandc->regs->spi_cfg = cpu_to_le32(snand_cfg_val); -+ snandc->regs->num_addr_cycle = cpu_to_le32(SPI_NUM_ADDR); -+ snandc->regs->busy_wait_cnt = cpu_to_le32(SPI_WAIT_CNT); -+ -+ qcom_write_reg_dma(snandc, &snandc->regs->spi_cfg, NAND_FLASH_SPI_CFG, 1, 0); -+ -+ snand_cfg_val &= ~LOAD_CLK_CNTR_INIT_EN; -+ snandc->regs->spi_cfg = cpu_to_le32(snand_cfg_val); -+ -+ qcom_write_reg_dma(snandc, &snandc->regs->spi_cfg, NAND_FLASH_SPI_CFG, 1, 0); -+ -+ qcom_write_reg_dma(snandc, &snandc->regs->num_addr_cycle, NAND_NUM_ADDR_CYCLES, 1, 0); -+ qcom_write_reg_dma(snandc, &snandc->regs->busy_wait_cnt, NAND_BUSY_CHECK_WAIT_CNT, 1, -+ NAND_BAM_NEXT_SGL); -+ -+ ret = qcom_submit_descs(snandc); -+ if (ret) { -+ dev_err(snandc->dev, "failure in submitting spi init descriptor\n"); -+ return ret; -+ } -+ -+ return ret; -+} -+ -+static int qcom_spi_ooblayout_ecc(struct mtd_info *mtd, int section, -+ struct mtd_oob_region *oobregion) -+{ -+ struct nand_device *nand = mtd_to_nanddev(mtd); -+ struct qcom_nand_controller *snandc = nand_to_qcom_snand(nand); -+ struct qpic_ecc *qecc = snandc->qspi->ecc; -+ -+ if (section > 1) -+ return -ERANGE; -+ -+ oobregion->length = qecc->ecc_bytes_hw + qecc->spare_bytes; -+ oobregion->offset = mtd->oobsize - oobregion->length; -+ -+ return 0; -+} -+ -+static int qcom_spi_ooblayout_free(struct mtd_info *mtd, int section, -+ struct mtd_oob_region *oobregion) -+{ -+ struct nand_device *nand = mtd_to_nanddev(mtd); -+ struct qcom_nand_controller *snandc = nand_to_qcom_snand(nand); -+ struct qpic_ecc *qecc = snandc->qspi->ecc; -+ -+ if (section) -+ return -ERANGE; -+ -+ oobregion->length = qecc->steps * 4; -+ oobregion->offset = ((qecc->steps - 1) * qecc->bytes) + qecc->bbm_size; -+ -+ return 0; -+} -+ -+static const struct mtd_ooblayout_ops qcom_spi_ooblayout = { -+ .ecc = qcom_spi_ooblayout_ecc, -+ .free = qcom_spi_ooblayout_free, -+}; -+ -+static int qcom_spi_ecc_init_ctx_pipelined(struct nand_device *nand) -+{ -+ struct qcom_nand_controller *snandc = nand_to_qcom_snand(nand); -+ struct nand_ecc_props *conf = &nand->ecc.ctx.conf; -+ struct mtd_info *mtd = nanddev_to_mtd(nand); -+ int cwperpage, bad_block_byte; -+ struct qpic_ecc *ecc_cfg; -+ -+ cwperpage = mtd->writesize / NANDC_STEP_SIZE; -+ snandc->qspi->num_cw = cwperpage; -+ -+ ecc_cfg = kzalloc(sizeof(*ecc_cfg), GFP_KERNEL); -+ if (!ecc_cfg) -+ return -ENOMEM; -+ snandc->qspi->oob_buf = kzalloc(mtd->writesize + mtd->oobsize, -+ GFP_KERNEL); -+ if (!snandc->qspi->oob_buf) -+ return -ENOMEM; -+ -+ memset(snandc->qspi->oob_buf, 0xff, mtd->writesize + mtd->oobsize); -+ -+ nand->ecc.ctx.priv = ecc_cfg; -+ snandc->qspi->mtd = mtd; -+ -+ ecc_cfg->ecc_bytes_hw = 7; -+ ecc_cfg->spare_bytes = 4; -+ ecc_cfg->bbm_size = 1; -+ ecc_cfg->bch_enabled = true; -+ ecc_cfg->bytes = ecc_cfg->ecc_bytes_hw + ecc_cfg->spare_bytes + ecc_cfg->bbm_size; -+ -+ ecc_cfg->steps = 4; -+ ecc_cfg->strength = 4; -+ ecc_cfg->step_size = 512; -+ ecc_cfg->cw_data = 516; -+ ecc_cfg->cw_size = ecc_cfg->cw_data + ecc_cfg->bytes; -+ bad_block_byte = mtd->writesize - ecc_cfg->cw_size * (cwperpage - 1) + 1; -+ -+ mtd_set_ooblayout(mtd, &qcom_spi_ooblayout); -+ -+ ecc_cfg->cfg0 = FIELD_PREP(CW_PER_PAGE_MASK, (cwperpage - 1)) | -+ FIELD_PREP(UD_SIZE_BYTES_MASK, ecc_cfg->cw_data) | -+ FIELD_PREP(DISABLE_STATUS_AFTER_WRITE, 1) | -+ FIELD_PREP(NUM_ADDR_CYCLES_MASK, 3) | -+ FIELD_PREP(ECC_PARITY_SIZE_BYTES_RS, ecc_cfg->ecc_bytes_hw) | -+ FIELD_PREP(STATUS_BFR_READ, 0) | -+ FIELD_PREP(SET_RD_MODE_AFTER_STATUS, 1) | -+ FIELD_PREP(SPARE_SIZE_BYTES_MASK, ecc_cfg->spare_bytes); -+ -+ ecc_cfg->cfg1 = FIELD_PREP(NAND_RECOVERY_CYCLES_MASK, 0) | -+ FIELD_PREP(CS_ACTIVE_BSY, 0) | -+ FIELD_PREP(BAD_BLOCK_BYTE_NUM_MASK, bad_block_byte) | -+ FIELD_PREP(BAD_BLOCK_IN_SPARE_AREA, 0) | -+ FIELD_PREP(WR_RD_BSY_GAP_MASK, 20) | -+ FIELD_PREP(WIDE_FLASH, 0) | -+ FIELD_PREP(ENABLE_BCH_ECC, ecc_cfg->bch_enabled); -+ -+ ecc_cfg->cfg0_raw = FIELD_PREP(CW_PER_PAGE_MASK, (cwperpage - 1)) | -+ FIELD_PREP(NUM_ADDR_CYCLES_MASK, 3) | -+ FIELD_PREP(UD_SIZE_BYTES_MASK, ecc_cfg->cw_size) | -+ FIELD_PREP(SPARE_SIZE_BYTES_MASK, 0); -+ -+ ecc_cfg->cfg1_raw = FIELD_PREP(NAND_RECOVERY_CYCLES_MASK, 0) | -+ FIELD_PREP(CS_ACTIVE_BSY, 0) | -+ FIELD_PREP(BAD_BLOCK_BYTE_NUM_MASK, 17) | -+ FIELD_PREP(BAD_BLOCK_IN_SPARE_AREA, 1) | -+ FIELD_PREP(WR_RD_BSY_GAP_MASK, 20) | -+ FIELD_PREP(WIDE_FLASH, 0) | -+ FIELD_PREP(DEV0_CFG1_ECC_DISABLE, 1); -+ -+ ecc_cfg->ecc_bch_cfg = FIELD_PREP(ECC_CFG_ECC_DISABLE, !ecc_cfg->bch_enabled) | -+ FIELD_PREP(ECC_SW_RESET, 0) | -+ FIELD_PREP(ECC_NUM_DATA_BYTES_MASK, ecc_cfg->cw_data) | -+ FIELD_PREP(ECC_FORCE_CLK_OPEN, 1) | -+ FIELD_PREP(ECC_MODE_MASK, 0) | -+ FIELD_PREP(ECC_PARITY_SIZE_BYTES_BCH_MASK, ecc_cfg->ecc_bytes_hw); -+ -+ ecc_cfg->ecc_buf_cfg = 0x203 << NUM_STEPS; -+ ecc_cfg->clrflashstatus = FS_READY_BSY_N; -+ ecc_cfg->clrreadstatus = 0xc0; -+ -+ conf->step_size = ecc_cfg->step_size; -+ conf->strength = ecc_cfg->strength; -+ -+ snandc->regs->erased_cw_detect_cfg_clr = cpu_to_le32(CLR_ERASED_PAGE_DET); -+ snandc->regs->erased_cw_detect_cfg_set = cpu_to_le32(SET_ERASED_PAGE_DET); -+ -+ dev_dbg(snandc->dev, "ECC strength: %u bits per %u bytes\n", -+ ecc_cfg->strength, ecc_cfg->step_size); -+ -+ return 0; -+} -+ -+static void qcom_spi_ecc_cleanup_ctx_pipelined(struct nand_device *nand) -+{ -+ struct qpic_ecc *ecc_cfg = nand_to_ecc_ctx(nand); -+ -+ kfree(ecc_cfg); -+} -+ -+static int qcom_spi_ecc_prepare_io_req_pipelined(struct nand_device *nand, -+ struct nand_page_io_req *req) -+{ -+ struct qcom_nand_controller *snandc = nand_to_qcom_snand(nand); -+ struct qpic_ecc *ecc_cfg = nand_to_ecc_ctx(nand); -+ -+ snandc->qspi->ecc = ecc_cfg; -+ snandc->qspi->raw_rw = false; -+ snandc->qspi->oob_rw = false; -+ snandc->qspi->page_rw = false; -+ -+ if (req->datalen) -+ snandc->qspi->page_rw = true; -+ -+ if (req->ooblen) -+ snandc->qspi->oob_rw = true; -+ -+ if (req->mode == MTD_OPS_RAW) -+ snandc->qspi->raw_rw = true; -+ -+ return 0; -+} -+ -+static int qcom_spi_ecc_finish_io_req_pipelined(struct nand_device *nand, -+ struct nand_page_io_req *req) -+{ -+ struct qcom_nand_controller *snandc = nand_to_qcom_snand(nand); -+ struct mtd_info *mtd = nanddev_to_mtd(nand); -+ -+ if (req->mode == MTD_OPS_RAW || req->type != NAND_PAGE_READ) -+ return 0; -+ -+ if (snandc->qspi->ecc_stats.failed) -+ mtd->ecc_stats.failed += snandc->qspi->ecc_stats.failed; -+ else -+ mtd->ecc_stats.corrected += snandc->qspi->ecc_stats.corrected; -+ -+ if (snandc->qspi->ecc_stats.failed) -+ return -EBADMSG; -+ else -+ return snandc->qspi->ecc_stats.bitflips; -+} -+ -+static struct nand_ecc_engine_ops qcom_spi_ecc_engine_ops_pipelined = { -+ .init_ctx = qcom_spi_ecc_init_ctx_pipelined, -+ .cleanup_ctx = qcom_spi_ecc_cleanup_ctx_pipelined, -+ .prepare_io_req = qcom_spi_ecc_prepare_io_req_pipelined, -+ .finish_io_req = qcom_spi_ecc_finish_io_req_pipelined, -+}; -+ -+/* helper to configure location register values */ -+static void qcom_spi_set_read_loc(struct qcom_nand_controller *snandc, int cw, int reg, -+ int cw_offset, int read_size, int is_last_read_loc) -+{ -+ int reg_base = NAND_READ_LOCATION_0; -+ int num_cw = snandc->qspi->num_cw; -+ -+ if (cw == (num_cw - 1)) -+ reg_base = NAND_READ_LOCATION_LAST_CW_0; -+ -+ reg_base += reg * 4; -+ -+ if (cw == (num_cw - 1)) -+ return qcom_spi_set_read_loc_last(snandc, reg_base, cw_offset, -+ read_size, is_last_read_loc); -+ else -+ return qcom_spi_set_read_loc_first(snandc, reg_base, cw_offset, -+ read_size, is_last_read_loc); -+} -+ -+static void -+qcom_spi_config_cw_read(struct qcom_nand_controller *snandc, bool use_ecc, int cw) -+{ -+ __le32 *reg = &snandc->regs->read_location0; -+ int num_cw = snandc->qspi->num_cw; -+ -+ qcom_write_reg_dma(snandc, reg, NAND_READ_LOCATION_0, 4, NAND_BAM_NEXT_SGL); -+ if (cw == (num_cw - 1)) { -+ reg = &snandc->regs->read_location_last0; -+ qcom_write_reg_dma(snandc, reg, NAND_READ_LOCATION_LAST_CW_0, 4, -+ NAND_BAM_NEXT_SGL); -+ } -+ -+ qcom_write_reg_dma(snandc, &snandc->regs->cmd, NAND_FLASH_CMD, 1, NAND_BAM_NEXT_SGL); -+ qcom_write_reg_dma(snandc, &snandc->regs->exec, NAND_EXEC_CMD, 1, NAND_BAM_NEXT_SGL); -+ -+ qcom_read_reg_dma(snandc, NAND_FLASH_STATUS, 2, 0); -+ qcom_read_reg_dma(snandc, NAND_ERASED_CW_DETECT_STATUS, 1, -+ NAND_BAM_NEXT_SGL); -+} -+ -+static int qcom_spi_block_erase(struct qcom_nand_controller *snandc) -+{ -+ struct qpic_ecc *ecc_cfg = snandc->qspi->ecc; -+ int ret; -+ -+ snandc->buf_count = 0; -+ snandc->buf_start = 0; -+ qcom_clear_read_regs(snandc); -+ qcom_clear_bam_transaction(snandc); -+ -+ snandc->regs->cmd = snandc->qspi->cmd; -+ snandc->regs->addr0 = snandc->qspi->addr1; -+ snandc->regs->addr1 = snandc->qspi->addr2; -+ snandc->regs->cfg0 = cpu_to_le32(ecc_cfg->cfg0_raw & ~(7 << CW_PER_PAGE)); -+ snandc->regs->cfg1 = cpu_to_le32(ecc_cfg->cfg1_raw); -+ snandc->regs->exec = cpu_to_le32(1); -+ -+ qcom_write_reg_dma(snandc, &snandc->regs->cmd, NAND_FLASH_CMD, 3, NAND_BAM_NEXT_SGL); -+ qcom_write_reg_dma(snandc, &snandc->regs->cfg0, NAND_DEV0_CFG0, 2, NAND_BAM_NEXT_SGL); -+ qcom_write_reg_dma(snandc, &snandc->regs->exec, NAND_EXEC_CMD, 1, NAND_BAM_NEXT_SGL); -+ -+ ret = qcom_submit_descs(snandc); -+ if (ret) { -+ dev_err(snandc->dev, "failure to erase block\n"); -+ return ret; -+ } -+ -+ return 0; -+} -+ -+static void qcom_spi_config_single_cw_page_read(struct qcom_nand_controller *snandc, -+ bool use_ecc, int cw) -+{ -+ __le32 *reg = &snandc->regs->read_location0; -+ int num_cw = snandc->qspi->num_cw; -+ -+ qcom_write_reg_dma(snandc, &snandc->regs->addr0, NAND_ADDR0, 2, 0); -+ qcom_write_reg_dma(snandc, &snandc->regs->cfg0, NAND_DEV0_CFG0, 3, 0); -+ qcom_write_reg_dma(snandc, &snandc->regs->erased_cw_detect_cfg_clr, -+ NAND_ERASED_CW_DETECT_CFG, 1, 0); -+ qcom_write_reg_dma(snandc, &snandc->regs->erased_cw_detect_cfg_set, -+ NAND_ERASED_CW_DETECT_CFG, 1, -+ NAND_ERASED_CW_SET | NAND_BAM_NEXT_SGL); -+ -+ if (cw == (num_cw - 1)) { -+ reg = &snandc->regs->read_location_last0; -+ qcom_write_reg_dma(snandc, reg, NAND_READ_LOCATION_LAST_CW_0, 4, NAND_BAM_NEXT_SGL); -+ } -+ qcom_write_reg_dma(snandc, &snandc->regs->cmd, NAND_FLASH_CMD, 1, NAND_BAM_NEXT_SGL); -+ qcom_write_reg_dma(snandc, &snandc->regs->exec, NAND_EXEC_CMD, 1, NAND_BAM_NEXT_SGL); -+ -+ qcom_read_reg_dma(snandc, NAND_FLASH_STATUS, 1, 0); -+} -+ -+static int qcom_spi_read_last_cw(struct qcom_nand_controller *snandc, -+ const struct spi_mem_op *op) -+{ -+ struct qpic_ecc *ecc_cfg = snandc->qspi->ecc; -+ struct mtd_info *mtd = snandc->qspi->mtd; -+ int size, ret = 0; -+ int col, bbpos; -+ u32 cfg0, cfg1, ecc_bch_cfg; -+ u32 num_cw = snandc->qspi->num_cw; -+ -+ qcom_clear_bam_transaction(snandc); -+ qcom_clear_read_regs(snandc); -+ -+ size = ecc_cfg->cw_size; -+ col = ecc_cfg->cw_size * (num_cw - 1); -+ -+ memset(snandc->data_buffer, 0xff, size); -+ snandc->regs->addr0 = (snandc->qspi->addr1 | cpu_to_le32(col)); -+ snandc->regs->addr1 = snandc->qspi->addr2; -+ -+ cfg0 = (ecc_cfg->cfg0_raw & ~(7U << CW_PER_PAGE)) | -+ 0 << CW_PER_PAGE; -+ cfg1 = ecc_cfg->cfg1_raw; -+ ecc_bch_cfg = 1 << ECC_CFG_ECC_DISABLE; -+ -+ snandc->regs->cmd = snandc->qspi->cmd; -+ snandc->regs->cfg0 = cpu_to_le32(cfg0); -+ snandc->regs->cfg1 = cpu_to_le32(cfg1); -+ snandc->regs->ecc_bch_cfg = cpu_to_le32(ecc_bch_cfg); -+ snandc->regs->clrflashstatus = cpu_to_le32(ecc_cfg->clrflashstatus); -+ snandc->regs->clrreadstatus = cpu_to_le32(ecc_cfg->clrreadstatus); -+ snandc->regs->exec = cpu_to_le32(1); -+ -+ qcom_spi_set_read_loc(snandc, num_cw - 1, 0, 0, ecc_cfg->cw_size, 1); -+ -+ qcom_spi_config_single_cw_page_read(snandc, false, num_cw - 1); -+ -+ qcom_read_data_dma(snandc, FLASH_BUF_ACC, snandc->data_buffer, size, 0); -+ -+ ret = qcom_submit_descs(snandc); -+ if (ret) { -+ dev_err(snandc->dev, "failed to read last cw\n"); -+ return ret; -+ } -+ -+ qcom_nandc_dev_to_mem(snandc, true); -+ u32 flash = le32_to_cpu(snandc->reg_read_buf[0]); -+ -+ if (flash & (FS_OP_ERR | FS_MPU_ERR)) -+ return -EIO; -+ -+ bbpos = mtd->writesize - ecc_cfg->cw_size * (num_cw - 1); -+ -+ if (snandc->data_buffer[bbpos] == 0xff) -+ snandc->data_buffer[bbpos + 1] = 0xff; -+ if (snandc->data_buffer[bbpos] != 0xff) -+ snandc->data_buffer[bbpos + 1] = snandc->data_buffer[bbpos]; -+ -+ memcpy(op->data.buf.in, snandc->data_buffer + bbpos, op->data.nbytes); -+ -+ return ret; -+} -+ -+static int qcom_spi_check_error(struct qcom_nand_controller *snandc, u8 *data_buf, u8 *oob_buf) -+{ -+ struct snandc_read_status *buf; -+ struct qpic_ecc *ecc_cfg = snandc->qspi->ecc; -+ int i, num_cw = snandc->qspi->num_cw; -+ bool flash_op_err = false, erased; -+ unsigned int max_bitflips = 0; -+ unsigned int uncorrectable_cws = 0; -+ -+ snandc->qspi->ecc_stats.failed = 0; -+ snandc->qspi->ecc_stats.corrected = 0; -+ -+ qcom_nandc_dev_to_mem(snandc, true); -+ buf = (struct snandc_read_status *)snandc->reg_read_buf; -+ -+ for (i = 0; i < num_cw; i++, buf++) { -+ u32 flash, buffer, erased_cw; -+ int data_len, oob_len; -+ -+ if (i == (num_cw - 1)) { -+ data_len = NANDC_STEP_SIZE - ((num_cw - 1) << 2); -+ oob_len = num_cw << 2; -+ } else { -+ data_len = ecc_cfg->cw_data; -+ oob_len = 0; -+ } -+ -+ flash = le32_to_cpu(buf->snandc_flash); -+ buffer = le32_to_cpu(buf->snandc_buffer); -+ erased_cw = le32_to_cpu(buf->snandc_erased_cw); -+ -+ if ((flash & FS_OP_ERR) && (buffer & BS_UNCORRECTABLE_BIT)) { -+ if (ecc_cfg->bch_enabled) -+ erased = (erased_cw & ERASED_CW) == ERASED_CW; -+ else -+ erased = false; -+ -+ if (!erased) -+ uncorrectable_cws |= BIT(i); -+ -+ } else if (flash & (FS_OP_ERR | FS_MPU_ERR)) { -+ flash_op_err = true; -+ } else { -+ unsigned int stat; -+ -+ stat = buffer & BS_CORRECTABLE_ERR_MSK; -+ snandc->qspi->ecc_stats.corrected += stat; -+ max_bitflips = max(max_bitflips, stat); -+ } -+ -+ if (data_buf) -+ data_buf += data_len; -+ if (oob_buf) -+ oob_buf += oob_len + ecc_cfg->bytes; -+ } -+ -+ if (flash_op_err) -+ return -EIO; -+ -+ if (!uncorrectable_cws) -+ snandc->qspi->ecc_stats.bitflips = max_bitflips; -+ else -+ snandc->qspi->ecc_stats.failed++; -+ -+ return 0; -+} -+ -+static int qcom_spi_check_raw_flash_errors(struct qcom_nand_controller *snandc, int cw_cnt) -+{ -+ int i; -+ -+ qcom_nandc_dev_to_mem(snandc, true); -+ -+ for (i = 0; i < cw_cnt; i++) { -+ u32 flash = le32_to_cpu(snandc->reg_read_buf[i]); -+ -+ if (flash & (FS_OP_ERR | FS_MPU_ERR)) -+ return -EIO; -+ } -+ -+ return 0; -+} -+ -+static int qcom_spi_read_cw_raw(struct qcom_nand_controller *snandc, u8 *data_buf, -+ u8 *oob_buf, int cw) -+{ -+ struct qpic_ecc *ecc_cfg = snandc->qspi->ecc; -+ struct mtd_info *mtd = snandc->qspi->mtd; -+ int data_size1, data_size2, oob_size1, oob_size2; -+ int ret, reg_off = FLASH_BUF_ACC, read_loc = 0; -+ int raw_cw = cw; -+ u32 cfg0, cfg1, ecc_bch_cfg, num_cw = snandc->qspi->num_cw; -+ int col; -+ -+ snandc->buf_count = 0; -+ snandc->buf_start = 0; -+ qcom_clear_read_regs(snandc); -+ qcom_clear_bam_transaction(snandc); -+ raw_cw = num_cw - 1; -+ -+ cfg0 = (ecc_cfg->cfg0_raw & ~(7U << CW_PER_PAGE)) | -+ 0 << CW_PER_PAGE; -+ cfg1 = ecc_cfg->cfg1_raw; -+ ecc_bch_cfg = ECC_CFG_ECC_DISABLE; -+ -+ col = ecc_cfg->cw_size * cw; -+ -+ snandc->regs->addr0 = (snandc->qspi->addr1 | cpu_to_le32(col)); -+ snandc->regs->addr1 = snandc->qspi->addr2; -+ snandc->regs->cmd = snandc->qspi->cmd; -+ snandc->regs->cfg0 = cpu_to_le32(cfg0); -+ snandc->regs->cfg1 = cpu_to_le32(cfg1); -+ snandc->regs->ecc_bch_cfg = cpu_to_le32(ecc_bch_cfg); -+ snandc->regs->clrflashstatus = cpu_to_le32(ecc_cfg->clrflashstatus); -+ snandc->regs->clrreadstatus = cpu_to_le32(ecc_cfg->clrreadstatus); -+ snandc->regs->exec = cpu_to_le32(1); -+ -+ qcom_spi_set_read_loc(snandc, raw_cw, 0, 0, ecc_cfg->cw_size, 1); -+ -+ qcom_write_reg_dma(snandc, &snandc->regs->addr0, NAND_ADDR0, 2, 0); -+ qcom_write_reg_dma(snandc, &snandc->regs->cfg0, NAND_DEV0_CFG0, 3, 0); -+ qcom_write_reg_dma(snandc, &snandc->regs->ecc_buf_cfg, NAND_EBI2_ECC_BUF_CFG, 1, 0); -+ -+ qcom_write_reg_dma(snandc, &snandc->regs->erased_cw_detect_cfg_clr, -+ NAND_ERASED_CW_DETECT_CFG, 1, 0); -+ qcom_write_reg_dma(snandc, &snandc->regs->erased_cw_detect_cfg_set, -+ NAND_ERASED_CW_DETECT_CFG, 1, -+ NAND_ERASED_CW_SET | NAND_BAM_NEXT_SGL); -+ -+ data_size1 = mtd->writesize - ecc_cfg->cw_size * (num_cw - 1); -+ oob_size1 = ecc_cfg->bbm_size; -+ -+ if (cw == (num_cw - 1)) { -+ data_size2 = NANDC_STEP_SIZE - data_size1 - -+ ((num_cw - 1) * 4); -+ oob_size2 = (num_cw * 4) + ecc_cfg->ecc_bytes_hw + -+ ecc_cfg->spare_bytes; -+ } else { -+ data_size2 = ecc_cfg->cw_data - data_size1; -+ oob_size2 = ecc_cfg->ecc_bytes_hw + ecc_cfg->spare_bytes; -+ } -+ -+ qcom_spi_set_read_loc(snandc, cw, 0, read_loc, data_size1, 0); -+ read_loc += data_size1; -+ -+ qcom_spi_set_read_loc(snandc, cw, 1, read_loc, oob_size1, 0); -+ read_loc += oob_size1; -+ -+ qcom_spi_set_read_loc(snandc, cw, 2, read_loc, data_size2, 0); -+ read_loc += data_size2; -+ -+ qcom_spi_set_read_loc(snandc, cw, 3, read_loc, oob_size2, 1); -+ -+ qcom_spi_config_cw_read(snandc, false, raw_cw); -+ -+ qcom_read_data_dma(snandc, reg_off, data_buf, data_size1, 0); -+ reg_off += data_size1; -+ -+ qcom_read_data_dma(snandc, reg_off, oob_buf, oob_size1, 0); -+ reg_off += oob_size1; -+ -+ qcom_read_data_dma(snandc, reg_off, data_buf + data_size1, data_size2, 0); -+ reg_off += data_size2; -+ -+ qcom_read_data_dma(snandc, reg_off, oob_buf + oob_size1, oob_size2, 0); -+ -+ ret = qcom_submit_descs(snandc); -+ if (ret) { -+ dev_err(snandc->dev, "failure to read raw cw %d\n", cw); -+ return ret; -+ } -+ -+ return qcom_spi_check_raw_flash_errors(snandc, 1); -+} -+ -+static int qcom_spi_read_page_raw(struct qcom_nand_controller *snandc, -+ const struct spi_mem_op *op) -+{ -+ struct qpic_ecc *ecc_cfg = snandc->qspi->ecc; -+ u8 *data_buf = NULL, *oob_buf = NULL; -+ int ret, cw; -+ u32 num_cw = snandc->qspi->num_cw; -+ -+ if (snandc->qspi->page_rw) -+ data_buf = op->data.buf.in; -+ -+ oob_buf = snandc->qspi->oob_buf; -+ memset(oob_buf, 0xff, OOB_BUF_SIZE); -+ -+ for (cw = 0; cw < num_cw; cw++) { -+ ret = qcom_spi_read_cw_raw(snandc, data_buf, oob_buf, cw); -+ if (ret) -+ return ret; -+ -+ if (data_buf) -+ data_buf += ecc_cfg->cw_data; -+ if (oob_buf) -+ oob_buf += ecc_cfg->bytes; -+ } -+ -+ return 0; -+} -+ -+static int qcom_spi_read_page_ecc(struct qcom_nand_controller *snandc, -+ const struct spi_mem_op *op) -+{ -+ struct qpic_ecc *ecc_cfg = snandc->qspi->ecc; -+ u8 *data_buf = NULL, *data_buf_start, *oob_buf = NULL, *oob_buf_start; -+ int ret, i; -+ u32 cfg0, cfg1, ecc_bch_cfg, num_cw = snandc->qspi->num_cw; -+ -+ data_buf = op->data.buf.in; -+ data_buf_start = data_buf; -+ -+ oob_buf = snandc->qspi->oob_buf; -+ oob_buf_start = oob_buf; -+ -+ snandc->buf_count = 0; -+ snandc->buf_start = 0; -+ qcom_clear_read_regs(snandc); -+ -+ cfg0 = (ecc_cfg->cfg0 & ~(7U << CW_PER_PAGE)) | -+ (num_cw - 1) << CW_PER_PAGE; -+ cfg1 = ecc_cfg->cfg1; -+ ecc_bch_cfg = ecc_cfg->ecc_bch_cfg; -+ -+ snandc->regs->addr0 = snandc->qspi->addr1; -+ snandc->regs->addr1 = snandc->qspi->addr2; -+ snandc->regs->cmd = snandc->qspi->cmd; -+ snandc->regs->cfg0 = cpu_to_le32(cfg0); -+ snandc->regs->cfg1 = cpu_to_le32(cfg1); -+ snandc->regs->ecc_bch_cfg = cpu_to_le32(ecc_bch_cfg); -+ snandc->regs->clrflashstatus = cpu_to_le32(ecc_cfg->clrflashstatus); -+ snandc->regs->clrreadstatus = cpu_to_le32(ecc_cfg->clrreadstatus); -+ snandc->regs->exec = cpu_to_le32(1); -+ -+ qcom_spi_set_read_loc(snandc, 0, 0, 0, ecc_cfg->cw_data, 1); -+ -+ qcom_clear_bam_transaction(snandc); -+ -+ qcom_write_reg_dma(snandc, &snandc->regs->addr0, NAND_ADDR0, 2, 0); -+ qcom_write_reg_dma(snandc, &snandc->regs->cfg0, NAND_DEV0_CFG0, 3, 0); -+ qcom_write_reg_dma(snandc, &snandc->regs->erased_cw_detect_cfg_clr, -+ NAND_ERASED_CW_DETECT_CFG, 1, 0); -+ qcom_write_reg_dma(snandc, &snandc->regs->erased_cw_detect_cfg_set, -+ NAND_ERASED_CW_DETECT_CFG, 1, -+ NAND_ERASED_CW_SET | NAND_BAM_NEXT_SGL); -+ -+ for (i = 0; i < num_cw; i++) { -+ int data_size, oob_size; -+ -+ if (i == (num_cw - 1)) { -+ data_size = 512 - ((num_cw - 1) << 2); -+ oob_size = (num_cw << 2) + ecc_cfg->ecc_bytes_hw + -+ ecc_cfg->spare_bytes; -+ } else { -+ data_size = ecc_cfg->cw_data; -+ oob_size = ecc_cfg->ecc_bytes_hw + ecc_cfg->spare_bytes; -+ } -+ -+ if (data_buf && oob_buf) { -+ qcom_spi_set_read_loc(snandc, i, 0, 0, data_size, 0); -+ qcom_spi_set_read_loc(snandc, i, 1, data_size, oob_size, 1); -+ } else if (data_buf) { -+ qcom_spi_set_read_loc(snandc, i, 0, 0, data_size, 1); -+ } else { -+ qcom_spi_set_read_loc(snandc, i, 0, data_size, oob_size, 1); -+ } -+ -+ qcom_spi_config_cw_read(snandc, true, i); -+ -+ if (data_buf) -+ qcom_read_data_dma(snandc, FLASH_BUF_ACC, data_buf, -+ data_size, 0); -+ if (oob_buf) { -+ int j; -+ -+ for (j = 0; j < ecc_cfg->bbm_size; j++) -+ *oob_buf++ = 0xff; -+ -+ qcom_read_data_dma(snandc, FLASH_BUF_ACC + data_size, -+ oob_buf, oob_size, 0); -+ } -+ -+ if (data_buf) -+ data_buf += data_size; -+ if (oob_buf) -+ oob_buf += oob_size; -+ } -+ -+ ret = qcom_submit_descs(snandc); -+ if (ret) { -+ dev_err(snandc->dev, "failure to read page\n"); -+ return ret; -+ } -+ -+ return qcom_spi_check_error(snandc, data_buf_start, oob_buf_start); -+} -+ -+static int qcom_spi_read_page_oob(struct qcom_nand_controller *snandc, -+ const struct spi_mem_op *op) -+{ -+ struct qpic_ecc *ecc_cfg = snandc->qspi->ecc; -+ u8 *data_buf = NULL, *data_buf_start, *oob_buf = NULL, *oob_buf_start; -+ int ret, i; -+ u32 cfg0, cfg1, ecc_bch_cfg, num_cw = snandc->qspi->num_cw; -+ -+ oob_buf = op->data.buf.in; -+ oob_buf_start = oob_buf; -+ -+ data_buf_start = data_buf; -+ -+ snandc->buf_count = 0; -+ snandc->buf_start = 0; -+ qcom_clear_read_regs(snandc); -+ qcom_clear_bam_transaction(snandc); -+ -+ cfg0 = (ecc_cfg->cfg0 & ~(7U << CW_PER_PAGE)) | -+ (num_cw - 1) << CW_PER_PAGE; -+ cfg1 = ecc_cfg->cfg1; -+ ecc_bch_cfg = ecc_cfg->ecc_bch_cfg; -+ -+ snandc->regs->addr0 = snandc->qspi->addr1; -+ snandc->regs->addr1 = snandc->qspi->addr2; -+ snandc->regs->cmd = snandc->qspi->cmd; -+ snandc->regs->cfg0 = cpu_to_le32(cfg0); -+ snandc->regs->cfg1 = cpu_to_le32(cfg1); -+ snandc->regs->ecc_bch_cfg = cpu_to_le32(ecc_bch_cfg); -+ snandc->regs->clrflashstatus = cpu_to_le32(ecc_cfg->clrflashstatus); -+ snandc->regs->clrreadstatus = cpu_to_le32(ecc_cfg->clrreadstatus); -+ snandc->regs->exec = cpu_to_le32(1); -+ -+ qcom_spi_set_read_loc(snandc, 0, 0, 0, ecc_cfg->cw_data, 1); -+ -+ qcom_write_reg_dma(snandc, &snandc->regs->addr0, NAND_ADDR0, 2, 0); -+ qcom_write_reg_dma(snandc, &snandc->regs->cfg0, NAND_DEV0_CFG0, 3, 0); -+ qcom_write_reg_dma(snandc, &snandc->regs->erased_cw_detect_cfg_clr, -+ NAND_ERASED_CW_DETECT_CFG, 1, 0); -+ qcom_write_reg_dma(snandc, &snandc->regs->erased_cw_detect_cfg_set, -+ NAND_ERASED_CW_DETECT_CFG, 1, -+ NAND_ERASED_CW_SET | NAND_BAM_NEXT_SGL); -+ -+ for (i = 0; i < num_cw; i++) { -+ int data_size, oob_size; -+ -+ if (i == (num_cw - 1)) { -+ data_size = NANDC_STEP_SIZE - ((num_cw - 1) << 2); -+ oob_size = (num_cw << 2) + ecc_cfg->ecc_bytes_hw + -+ ecc_cfg->spare_bytes; -+ } else { -+ data_size = ecc_cfg->cw_data; -+ oob_size = ecc_cfg->ecc_bytes_hw + ecc_cfg->spare_bytes; -+ } -+ -+ qcom_spi_set_read_loc(snandc, i, 0, data_size, oob_size, 1); -+ -+ qcom_spi_config_cw_read(snandc, true, i); -+ -+ if (oob_buf) { -+ int j; -+ -+ for (j = 0; j < ecc_cfg->bbm_size; j++) -+ *oob_buf++ = 0xff; -+ -+ qcom_read_data_dma(snandc, FLASH_BUF_ACC + data_size, -+ oob_buf, oob_size, 0); -+ } -+ -+ if (oob_buf) -+ oob_buf += oob_size; -+ } -+ -+ ret = qcom_submit_descs(snandc); -+ if (ret) { -+ dev_err(snandc->dev, "failure to read oob\n"); -+ return ret; -+ } -+ -+ return qcom_spi_check_error(snandc, data_buf_start, oob_buf_start); -+} -+ -+static int qcom_spi_read_page(struct qcom_nand_controller *snandc, -+ const struct spi_mem_op *op) -+{ -+ if (snandc->qspi->page_rw && snandc->qspi->raw_rw) -+ return qcom_spi_read_page_raw(snandc, op); -+ -+ if (snandc->qspi->page_rw) -+ return qcom_spi_read_page_ecc(snandc, op); -+ -+ if (snandc->qspi->oob_rw && snandc->qspi->raw_rw) -+ return qcom_spi_read_last_cw(snandc, op); -+ -+ if (snandc->qspi->oob_rw) -+ return qcom_spi_read_page_oob(snandc, op); -+ -+ return 0; -+} -+ -+static void qcom_spi_config_page_write(struct qcom_nand_controller *snandc) -+{ -+ qcom_write_reg_dma(snandc, &snandc->regs->addr0, NAND_ADDR0, 2, 0); -+ qcom_write_reg_dma(snandc, &snandc->regs->cfg0, NAND_DEV0_CFG0, 3, 0); -+ qcom_write_reg_dma(snandc, &snandc->regs->ecc_buf_cfg, NAND_EBI2_ECC_BUF_CFG, -+ 1, NAND_BAM_NEXT_SGL); -+} -+ -+static void qcom_spi_config_cw_write(struct qcom_nand_controller *snandc) -+{ -+ qcom_write_reg_dma(snandc, &snandc->regs->cmd, NAND_FLASH_CMD, 1, NAND_BAM_NEXT_SGL); -+ qcom_write_reg_dma(snandc, &snandc->regs->exec, NAND_EXEC_CMD, 1, NAND_BAM_NEXT_SGL); -+ qcom_read_reg_dma(snandc, NAND_FLASH_STATUS, 1, NAND_BAM_NEXT_SGL); -+ -+ qcom_write_reg_dma(snandc, &snandc->regs->clrflashstatus, NAND_FLASH_STATUS, 1, 0); -+ qcom_write_reg_dma(snandc, &snandc->regs->clrreadstatus, NAND_READ_STATUS, 1, -+ NAND_BAM_NEXT_SGL); -+} -+ -+static int qcom_spi_program_raw(struct qcom_nand_controller *snandc, -+ const struct spi_mem_op *op) -+{ -+ struct qpic_ecc *ecc_cfg = snandc->qspi->ecc; -+ struct mtd_info *mtd = snandc->qspi->mtd; -+ u8 *data_buf = NULL, *oob_buf = NULL; -+ int i, ret; -+ int num_cw = snandc->qspi->num_cw; -+ u32 cfg0, cfg1, ecc_bch_cfg; -+ -+ cfg0 = (ecc_cfg->cfg0_raw & ~(7U << CW_PER_PAGE)) | -+ (num_cw - 1) << CW_PER_PAGE; -+ cfg1 = ecc_cfg->cfg1_raw; -+ ecc_bch_cfg = ECC_CFG_ECC_DISABLE; -+ -+ data_buf = snandc->qspi->data_buf; -+ -+ oob_buf = snandc->qspi->oob_buf; -+ memset(oob_buf, 0xff, OOB_BUF_SIZE); -+ -+ snandc->buf_count = 0; -+ snandc->buf_start = 0; -+ qcom_clear_read_regs(snandc); -+ qcom_clear_bam_transaction(snandc); -+ -+ snandc->regs->addr0 = snandc->qspi->addr1; -+ snandc->regs->addr1 = snandc->qspi->addr2; -+ snandc->regs->cmd = snandc->qspi->cmd; -+ snandc->regs->cfg0 = cpu_to_le32(cfg0); -+ snandc->regs->cfg1 = cpu_to_le32(cfg1); -+ snandc->regs->ecc_bch_cfg = cpu_to_le32(ecc_bch_cfg); -+ snandc->regs->clrflashstatus = cpu_to_le32(ecc_cfg->clrflashstatus); -+ snandc->regs->clrreadstatus = cpu_to_le32(ecc_cfg->clrreadstatus); -+ snandc->regs->exec = cpu_to_le32(1); -+ -+ qcom_spi_config_page_write(snandc); -+ -+ for (i = 0; i < num_cw; i++) { -+ int data_size1, data_size2, oob_size1, oob_size2; -+ int reg_off = FLASH_BUF_ACC; -+ -+ data_size1 = mtd->writesize - ecc_cfg->cw_size * (num_cw - 1); -+ oob_size1 = ecc_cfg->bbm_size; -+ -+ if (i == (num_cw - 1)) { -+ data_size2 = NANDC_STEP_SIZE - data_size1 - -+ ((num_cw - 1) << 2); -+ oob_size2 = (num_cw << 2) + ecc_cfg->ecc_bytes_hw + -+ ecc_cfg->spare_bytes; -+ } else { -+ data_size2 = ecc_cfg->cw_data - data_size1; -+ oob_size2 = ecc_cfg->ecc_bytes_hw + ecc_cfg->spare_bytes; -+ } -+ -+ qcom_write_data_dma(snandc, reg_off, data_buf, data_size1, -+ NAND_BAM_NO_EOT); -+ reg_off += data_size1; -+ data_buf += data_size1; -+ -+ qcom_write_data_dma(snandc, reg_off, oob_buf, oob_size1, -+ NAND_BAM_NO_EOT); -+ oob_buf += oob_size1; -+ reg_off += oob_size1; -+ -+ qcom_write_data_dma(snandc, reg_off, data_buf, data_size2, -+ NAND_BAM_NO_EOT); -+ reg_off += data_size2; -+ data_buf += data_size2; -+ -+ qcom_write_data_dma(snandc, reg_off, oob_buf, oob_size2, 0); -+ oob_buf += oob_size2; -+ -+ qcom_spi_config_cw_write(snandc); -+ } -+ -+ ret = qcom_submit_descs(snandc); -+ if (ret) { -+ dev_err(snandc->dev, "failure to write raw page\n"); -+ return ret; -+ } -+ -+ return 0; -+} -+ -+static int qcom_spi_program_ecc(struct qcom_nand_controller *snandc, -+ const struct spi_mem_op *op) -+{ -+ struct qpic_ecc *ecc_cfg = snandc->qspi->ecc; -+ u8 *data_buf = NULL, *oob_buf = NULL; -+ int i, ret; -+ int num_cw = snandc->qspi->num_cw; -+ u32 cfg0, cfg1, ecc_bch_cfg, ecc_buf_cfg; -+ -+ cfg0 = (ecc_cfg->cfg0 & ~(7U << CW_PER_PAGE)) | -+ (num_cw - 1) << CW_PER_PAGE; -+ cfg1 = ecc_cfg->cfg1; -+ ecc_bch_cfg = ecc_cfg->ecc_bch_cfg; -+ ecc_buf_cfg = ecc_cfg->ecc_buf_cfg; -+ -+ if (snandc->qspi->data_buf) -+ data_buf = snandc->qspi->data_buf; -+ -+ oob_buf = snandc->qspi->oob_buf; -+ -+ snandc->buf_count = 0; -+ snandc->buf_start = 0; -+ qcom_clear_read_regs(snandc); -+ qcom_clear_bam_transaction(snandc); -+ -+ snandc->regs->addr0 = snandc->qspi->addr1; -+ snandc->regs->addr1 = snandc->qspi->addr2; -+ snandc->regs->cmd = snandc->qspi->cmd; -+ snandc->regs->cfg0 = cpu_to_le32(cfg0); -+ snandc->regs->cfg1 = cpu_to_le32(cfg1); -+ snandc->regs->ecc_bch_cfg = cpu_to_le32(ecc_bch_cfg); -+ snandc->regs->ecc_buf_cfg = cpu_to_le32(ecc_buf_cfg); -+ snandc->regs->exec = cpu_to_le32(1); -+ -+ qcom_spi_config_page_write(snandc); -+ -+ for (i = 0; i < num_cw; i++) { -+ int data_size, oob_size; -+ -+ if (i == (num_cw - 1)) { -+ data_size = NANDC_STEP_SIZE - ((num_cw - 1) << 2); -+ oob_size = (num_cw << 2) + ecc_cfg->ecc_bytes_hw + -+ ecc_cfg->spare_bytes; -+ } else { -+ data_size = ecc_cfg->cw_data; -+ oob_size = ecc_cfg->bytes; -+ } -+ -+ if (data_buf) -+ qcom_write_data_dma(snandc, FLASH_BUF_ACC, data_buf, data_size, -+ i == (num_cw - 1) ? NAND_BAM_NO_EOT : 0); -+ -+ if (i == (num_cw - 1)) { -+ if (oob_buf) { -+ oob_buf += ecc_cfg->bbm_size; -+ qcom_write_data_dma(snandc, FLASH_BUF_ACC + data_size, -+ oob_buf, oob_size, 0); -+ } -+ } -+ -+ qcom_spi_config_cw_write(snandc); -+ -+ if (data_buf) -+ data_buf += data_size; -+ if (oob_buf) -+ oob_buf += oob_size; -+ } -+ -+ ret = qcom_submit_descs(snandc); -+ if (ret) { -+ dev_err(snandc->dev, "failure to write page\n"); -+ return ret; -+ } -+ -+ return 0; -+} -+ -+static int qcom_spi_program_oob(struct qcom_nand_controller *snandc, -+ const struct spi_mem_op *op) -+{ -+ struct qpic_ecc *ecc_cfg = snandc->qspi->ecc; -+ u8 *oob_buf = NULL; -+ int ret, col, data_size, oob_size; -+ int num_cw = snandc->qspi->num_cw; -+ u32 cfg0, cfg1, ecc_bch_cfg, ecc_buf_cfg; -+ -+ cfg0 = (ecc_cfg->cfg0 & ~(7U << CW_PER_PAGE)) | -+ (num_cw - 1) << CW_PER_PAGE; -+ cfg1 = ecc_cfg->cfg1; -+ ecc_bch_cfg = ecc_cfg->ecc_bch_cfg; -+ ecc_buf_cfg = ecc_cfg->ecc_buf_cfg; -+ -+ col = ecc_cfg->cw_size * (num_cw - 1); -+ -+ oob_buf = snandc->qspi->data_buf; -+ -+ snandc->buf_count = 0; -+ snandc->buf_start = 0; -+ qcom_clear_read_regs(snandc); -+ qcom_clear_bam_transaction(snandc); -+ snandc->regs->addr0 = (snandc->qspi->addr1 | cpu_to_le32(col)); -+ snandc->regs->addr1 = snandc->qspi->addr2; -+ snandc->regs->cmd = snandc->qspi->cmd; -+ snandc->regs->cfg0 = cpu_to_le32(cfg0); -+ snandc->regs->cfg1 = cpu_to_le32(cfg1); -+ snandc->regs->ecc_bch_cfg = cpu_to_le32(ecc_bch_cfg); -+ snandc->regs->ecc_buf_cfg = cpu_to_le32(ecc_buf_cfg); -+ snandc->regs->exec = cpu_to_le32(1); -+ -+ /* calculate the data and oob size for the last codeword/step */ -+ data_size = NANDC_STEP_SIZE - ((num_cw - 1) << 2); -+ oob_size = snandc->qspi->mtd->oobavail; -+ -+ memset(snandc->data_buffer, 0xff, ecc_cfg->cw_data); -+ /* override new oob content to last codeword */ -+ mtd_ooblayout_get_databytes(snandc->qspi->mtd, snandc->data_buffer + data_size, -+ oob_buf, 0, snandc->qspi->mtd->oobavail); -+ qcom_spi_config_page_write(snandc); -+ qcom_write_data_dma(snandc, FLASH_BUF_ACC, snandc->data_buffer, data_size + oob_size, 0); -+ qcom_spi_config_cw_write(snandc); -+ -+ ret = qcom_submit_descs(snandc); -+ if (ret) { -+ dev_err(snandc->dev, "failure to write oob\n"); -+ return ret; -+ } -+ -+ return 0; -+} -+ -+static int qcom_spi_program_execute(struct qcom_nand_controller *snandc, -+ const struct spi_mem_op *op) -+{ -+ if (snandc->qspi->page_rw && snandc->qspi->raw_rw) -+ return qcom_spi_program_raw(snandc, op); -+ -+ if (snandc->qspi->page_rw) -+ return qcom_spi_program_ecc(snandc, op); -+ -+ if (snandc->qspi->oob_rw) -+ return qcom_spi_program_oob(snandc, op); -+ -+ return 0; -+} -+ -+static int qcom_spi_cmd_mapping(struct qcom_nand_controller *snandc, u32 opcode, u32 *cmd) -+{ -+ switch (opcode) { -+ case SPINAND_RESET: -+ *cmd = (SPI_WP | SPI_HOLD | SPI_TRANSFER_MODE_x1 | OP_RESET_DEVICE); -+ break; -+ case SPINAND_READID: -+ *cmd = (SPI_WP | SPI_HOLD | SPI_TRANSFER_MODE_x1 | OP_FETCH_ID); -+ break; -+ case SPINAND_GET_FEATURE: -+ *cmd = (SPI_TRANSFER_MODE_x1 | SPI_WP | SPI_HOLD | ACC_FEATURE); -+ break; -+ case SPINAND_SET_FEATURE: -+ *cmd = (SPI_TRANSFER_MODE_x1 | SPI_WP | SPI_HOLD | ACC_FEATURE | -+ QPIC_SET_FEATURE); -+ break; -+ case SPINAND_READ: -+ if (snandc->qspi->raw_rw) { -+ *cmd = (PAGE_ACC | LAST_PAGE | SPI_TRANSFER_MODE_x1 | -+ SPI_WP | SPI_HOLD | OP_PAGE_READ); -+ } else { -+ *cmd = (PAGE_ACC | LAST_PAGE | SPI_TRANSFER_MODE_x1 | -+ SPI_WP | SPI_HOLD | OP_PAGE_READ_WITH_ECC); -+ } -+ -+ break; -+ case SPINAND_ERASE: -+ *cmd = OP_BLOCK_ERASE | PAGE_ACC | LAST_PAGE | SPI_WP | -+ SPI_HOLD | SPI_TRANSFER_MODE_x1; -+ break; -+ case SPINAND_WRITE_EN: -+ *cmd = SPINAND_WRITE_EN; -+ break; -+ case SPINAND_PROGRAM_EXECUTE: -+ *cmd = (PAGE_ACC | LAST_PAGE | SPI_TRANSFER_MODE_x1 | -+ SPI_WP | SPI_HOLD | OP_PROGRAM_PAGE); -+ break; -+ case SPINAND_PROGRAM_LOAD: -+ *cmd = SPINAND_PROGRAM_LOAD; -+ break; -+ default: -+ dev_err(snandc->dev, "Opcode not supported: %u\n", opcode); -+ return -EOPNOTSUPP; -+ } -+ -+ return 0; -+} -+ -+static int qcom_spi_write_page(struct qcom_nand_controller *snandc, -+ const struct spi_mem_op *op) -+{ -+ int ret; -+ u32 cmd; -+ -+ ret = qcom_spi_cmd_mapping(snandc, op->cmd.opcode, &cmd); -+ if (ret < 0) -+ return ret; -+ -+ if (op->cmd.opcode == SPINAND_PROGRAM_LOAD) -+ snandc->qspi->data_buf = (u8 *)op->data.buf.out; -+ -+ return 0; -+} -+ -+static int qcom_spi_send_cmdaddr(struct qcom_nand_controller *snandc, -+ const struct spi_mem_op *op) -+{ -+ struct qpic_snand_op s_op = {}; -+ u32 cmd; -+ int ret, opcode; -+ -+ ret = qcom_spi_cmd_mapping(snandc, op->cmd.opcode, &cmd); -+ if (ret < 0) -+ return ret; -+ -+ s_op.cmd_reg = cmd; -+ s_op.addr1_reg = op->addr.val; -+ s_op.addr2_reg = 0; -+ -+ opcode = op->cmd.opcode; -+ -+ switch (opcode) { -+ case SPINAND_WRITE_EN: -+ return 0; -+ case SPINAND_PROGRAM_EXECUTE: -+ s_op.addr1_reg = op->addr.val << 16; -+ s_op.addr2_reg = op->addr.val >> 16 & 0xff; -+ snandc->qspi->addr1 = cpu_to_le32(s_op.addr1_reg); -+ snandc->qspi->addr2 = cpu_to_le32(s_op.addr2_reg); -+ snandc->qspi->cmd = cpu_to_le32(cmd); -+ return qcom_spi_program_execute(snandc, op); -+ case SPINAND_READ: -+ s_op.addr1_reg = (op->addr.val << 16); -+ s_op.addr2_reg = op->addr.val >> 16 & 0xff; -+ snandc->qspi->addr1 = cpu_to_le32(s_op.addr1_reg); -+ snandc->qspi->addr2 = cpu_to_le32(s_op.addr2_reg); -+ snandc->qspi->cmd = cpu_to_le32(cmd); -+ return 0; -+ case SPINAND_ERASE: -+ s_op.addr2_reg = (op->addr.val >> 16) & 0xffff; -+ s_op.addr1_reg = op->addr.val; -+ snandc->qspi->addr1 = cpu_to_le32(s_op.addr1_reg << 16); -+ snandc->qspi->addr2 = cpu_to_le32(s_op.addr2_reg); -+ snandc->qspi->cmd = cpu_to_le32(cmd); -+ qcom_spi_block_erase(snandc); -+ return 0; -+ default: -+ break; -+ } -+ -+ snandc->buf_count = 0; -+ snandc->buf_start = 0; -+ qcom_clear_read_regs(snandc); -+ qcom_clear_bam_transaction(snandc); -+ -+ snandc->regs->cmd = cpu_to_le32(s_op.cmd_reg); -+ snandc->regs->exec = cpu_to_le32(1); -+ snandc->regs->addr0 = cpu_to_le32(s_op.addr1_reg); -+ snandc->regs->addr1 = cpu_to_le32(s_op.addr2_reg); -+ -+ qcom_write_reg_dma(snandc, &snandc->regs->cmd, NAND_FLASH_CMD, 3, NAND_BAM_NEXT_SGL); -+ qcom_write_reg_dma(snandc, &snandc->regs->exec, NAND_EXEC_CMD, 1, NAND_BAM_NEXT_SGL); -+ -+ ret = qcom_submit_descs(snandc); -+ if (ret) -+ dev_err(snandc->dev, "failure in submitting cmd descriptor\n"); -+ -+ return ret; -+} -+ -+static int qcom_spi_io_op(struct qcom_nand_controller *snandc, const struct spi_mem_op *op) -+{ -+ int ret, val, opcode; -+ bool copy = false, copy_ftr = false; -+ -+ ret = qcom_spi_send_cmdaddr(snandc, op); -+ if (ret) -+ return ret; -+ -+ snandc->buf_count = 0; -+ snandc->buf_start = 0; -+ qcom_clear_read_regs(snandc); -+ qcom_clear_bam_transaction(snandc); -+ opcode = op->cmd.opcode; -+ -+ switch (opcode) { -+ case SPINAND_READID: -+ snandc->buf_count = 4; -+ qcom_read_reg_dma(snandc, NAND_READ_ID, 1, NAND_BAM_NEXT_SGL); -+ copy = true; -+ break; -+ case SPINAND_GET_FEATURE: -+ snandc->buf_count = 4; -+ qcom_read_reg_dma(snandc, NAND_FLASH_FEATURES, 1, NAND_BAM_NEXT_SGL); -+ copy_ftr = true; -+ break; -+ case SPINAND_SET_FEATURE: -+ snandc->regs->flash_feature = cpu_to_le32(*(u32 *)op->data.buf.out); -+ qcom_write_reg_dma(snandc, &snandc->regs->flash_feature, -+ NAND_FLASH_FEATURES, 1, NAND_BAM_NEXT_SGL); -+ break; -+ case SPINAND_PROGRAM_EXECUTE: -+ case SPINAND_WRITE_EN: -+ case SPINAND_RESET: -+ case SPINAND_ERASE: -+ case SPINAND_READ: -+ return 0; -+ default: -+ return -EOPNOTSUPP; -+ } -+ -+ ret = qcom_submit_descs(snandc); -+ if (ret) -+ dev_err(snandc->dev, "failure in submitting descriptor for:%d\n", opcode); -+ -+ if (copy) { -+ qcom_nandc_dev_to_mem(snandc, true); -+ memcpy(op->data.buf.in, snandc->reg_read_buf, snandc->buf_count); -+ } -+ -+ if (copy_ftr) { -+ qcom_nandc_dev_to_mem(snandc, true); -+ val = le32_to_cpu(*(__le32 *)snandc->reg_read_buf); -+ val >>= 8; -+ memcpy(op->data.buf.in, &val, snandc->buf_count); -+ } -+ -+ return ret; -+} -+ -+static bool qcom_spi_is_page_op(const struct spi_mem_op *op) -+{ -+ if (op->addr.buswidth != 1 && op->addr.buswidth != 2 && op->addr.buswidth != 4) -+ return false; -+ -+ if (op->data.dir == SPI_MEM_DATA_IN) { -+ if (op->addr.buswidth == 4 && op->data.buswidth == 4) -+ return true; -+ -+ if (op->addr.nbytes == 2 && op->addr.buswidth == 1) -+ return true; -+ -+ } else if (op->data.dir == SPI_MEM_DATA_OUT) { -+ if (op->data.buswidth == 4) -+ return true; -+ if (op->addr.nbytes == 2 && op->addr.buswidth == 1) -+ return true; -+ } -+ -+ return false; -+} -+ -+static bool qcom_spi_supports_op(struct spi_mem *mem, const struct spi_mem_op *op) -+{ -+ if (!spi_mem_default_supports_op(mem, op)) -+ return false; -+ -+ if (op->cmd.nbytes != 1 || op->cmd.buswidth != 1) -+ return false; -+ -+ if (qcom_spi_is_page_op(op)) -+ return true; -+ -+ return ((!op->addr.nbytes || op->addr.buswidth == 1) && -+ (!op->dummy.nbytes || op->dummy.buswidth == 1) && -+ (!op->data.nbytes || op->data.buswidth == 1)); -+} -+ -+static int qcom_spi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) -+{ -+ struct qcom_nand_controller *snandc = spi_controller_get_devdata(mem->spi->controller); -+ -+ dev_dbg(snandc->dev, "OP %02x ADDR %08llX@%d:%u DATA %d:%u", op->cmd.opcode, -+ op->addr.val, op->addr.buswidth, op->addr.nbytes, -+ op->data.buswidth, op->data.nbytes); -+ -+ if (qcom_spi_is_page_op(op)) { -+ if (op->data.dir == SPI_MEM_DATA_IN) -+ return qcom_spi_read_page(snandc, op); -+ if (op->data.dir == SPI_MEM_DATA_OUT) -+ return qcom_spi_write_page(snandc, op); -+ } else { -+ return qcom_spi_io_op(snandc, op); -+ } -+ -+ return 0; -+} -+ -+static const struct spi_controller_mem_ops qcom_spi_mem_ops = { -+ .supports_op = qcom_spi_supports_op, -+ .exec_op = qcom_spi_exec_op, -+}; -+ -+static const struct spi_controller_mem_caps qcom_spi_mem_caps = { -+ .ecc = true, -+}; -+ -+static int qcom_spi_probe(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ struct spi_controller *ctlr; -+ struct qcom_nand_controller *snandc; -+ struct qpic_spi_nand *qspi; -+ struct qpic_ecc *ecc; -+ struct resource *res; -+ const void *dev_data; -+ int ret; -+ -+ ecc = devm_kzalloc(dev, sizeof(*ecc), GFP_KERNEL); -+ if (!ecc) -+ return -ENOMEM; -+ -+ qspi = devm_kzalloc(dev, sizeof(*qspi), GFP_KERNEL); -+ if (!qspi) -+ return -ENOMEM; -+ -+ ctlr = __devm_spi_alloc_controller(dev, sizeof(*snandc), false); -+ if (!ctlr) -+ return -ENOMEM; -+ -+ platform_set_drvdata(pdev, ctlr); -+ -+ snandc = spi_controller_get_devdata(ctlr); -+ qspi->snandc = snandc; -+ -+ snandc->dev = dev; -+ snandc->qspi = qspi; -+ snandc->qspi->ctlr = ctlr; -+ snandc->qspi->ecc = ecc; -+ -+ dev_data = of_device_get_match_data(dev); -+ if (!dev_data) { -+ dev_err(&pdev->dev, "failed to get device data\n"); -+ return -ENODEV; -+ } -+ -+ snandc->props = dev_data; -+ snandc->dev = &pdev->dev; -+ -+ snandc->core_clk = devm_clk_get(dev, "core"); -+ if (IS_ERR(snandc->core_clk)) -+ return PTR_ERR(snandc->core_clk); -+ -+ snandc->aon_clk = devm_clk_get(dev, "aon"); -+ if (IS_ERR(snandc->aon_clk)) -+ return PTR_ERR(snandc->aon_clk); -+ -+ snandc->qspi->iomacro_clk = devm_clk_get(dev, "iom"); -+ if (IS_ERR(snandc->qspi->iomacro_clk)) -+ return PTR_ERR(snandc->qspi->iomacro_clk); -+ -+ snandc->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); -+ if (IS_ERR(snandc->base)) -+ return PTR_ERR(snandc->base); -+ -+ snandc->base_phys = res->start; -+ snandc->base_dma = dma_map_resource(dev, res->start, resource_size(res), -+ DMA_BIDIRECTIONAL, 0); -+ if (dma_mapping_error(dev, snandc->base_dma)) -+ return -ENXIO; -+ -+ ret = clk_prepare_enable(snandc->core_clk); -+ if (ret) -+ goto err_dis_core_clk; -+ -+ ret = clk_prepare_enable(snandc->aon_clk); -+ if (ret) -+ goto err_dis_aon_clk; -+ -+ ret = clk_prepare_enable(snandc->qspi->iomacro_clk); -+ if (ret) -+ goto err_dis_iom_clk; -+ -+ ret = qcom_nandc_alloc(snandc); -+ if (ret) -+ goto err_snand_alloc; -+ -+ ret = qcom_spi_init(snandc); -+ if (ret) -+ goto err_spi_init; -+ -+ /* setup ECC engine */ -+ snandc->qspi->ecc_eng.dev = &pdev->dev; -+ snandc->qspi->ecc_eng.integration = NAND_ECC_ENGINE_INTEGRATION_PIPELINED; -+ snandc->qspi->ecc_eng.ops = &qcom_spi_ecc_engine_ops_pipelined; -+ snandc->qspi->ecc_eng.priv = snandc; -+ -+ ret = nand_ecc_register_on_host_hw_engine(&snandc->qspi->ecc_eng); -+ if (ret) { -+ dev_err(&pdev->dev, "failed to register ecc engine:%d\n", ret); -+ goto err_spi_init; -+ } -+ -+ ctlr->num_chipselect = QPIC_QSPI_NUM_CS; -+ ctlr->mem_ops = &qcom_spi_mem_ops; -+ ctlr->mem_caps = &qcom_spi_mem_caps; -+ ctlr->dev.of_node = pdev->dev.of_node; -+ ctlr->mode_bits = SPI_TX_DUAL | SPI_RX_DUAL | -+ SPI_TX_QUAD | SPI_RX_QUAD; -+ -+ ret = spi_register_controller(ctlr); -+ if (ret) { -+ dev_err(&pdev->dev, "spi_register_controller failed.\n"); -+ goto err_spi_init; -+ } -+ -+ return 0; -+ -+err_spi_init: -+ qcom_nandc_unalloc(snandc); -+err_snand_alloc: -+ clk_disable_unprepare(snandc->qspi->iomacro_clk); -+err_dis_iom_clk: -+ clk_disable_unprepare(snandc->aon_clk); -+err_dis_aon_clk: -+ clk_disable_unprepare(snandc->core_clk); -+err_dis_core_clk: -+ dma_unmap_resource(dev, res->start, resource_size(res), -+ DMA_BIDIRECTIONAL, 0); -+ return ret; -+} -+ -+static void qcom_spi_remove(struct platform_device *pdev) -+{ -+ struct spi_controller *ctlr = platform_get_drvdata(pdev); -+ struct qcom_nand_controller *snandc = spi_controller_get_devdata(ctlr); -+ struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ -+ spi_unregister_controller(ctlr); -+ -+ qcom_nandc_unalloc(snandc); -+ -+ clk_disable_unprepare(snandc->aon_clk); -+ clk_disable_unprepare(snandc->core_clk); -+ clk_disable_unprepare(snandc->qspi->iomacro_clk); -+ -+ dma_unmap_resource(&pdev->dev, snandc->base_dma, resource_size(res), -+ DMA_BIDIRECTIONAL, 0); -+} -+ -+static const struct qcom_nandc_props ipq9574_snandc_props = { -+ .dev_cmd_reg_start = 0x7000, -+ .supports_bam = true, -+}; -+ -+static const struct of_device_id qcom_snandc_of_match[] = { -+ { -+ .compatible = "qcom,ipq9574-snand", -+ .data = &ipq9574_snandc_props, -+ }, -+ {} -+} -+MODULE_DEVICE_TABLE(of, qcom_snandc_of_match); -+ -+static struct platform_driver qcom_spi_driver = { -+ .driver = { -+ .name = "qcom_snand", -+ .of_match_table = qcom_snandc_of_match, -+ }, -+ .probe = qcom_spi_probe, -+ .remove_new = qcom_spi_remove, -+}; -+module_platform_driver(qcom_spi_driver); -+ -+MODULE_DESCRIPTION("SPI driver for QPIC QSPI cores"); -+MODULE_AUTHOR("Md Sadre Alam "); -+MODULE_LICENSE("GPL"); -+ ---- a/include/linux/mtd/nand-qpic-common.h -+++ b/include/linux/mtd/nand-qpic-common.h -@@ -325,6 +325,10 @@ struct nandc_regs { - __le32 read_location_last1; - __le32 read_location_last2; - __le32 read_location_last3; -+ __le32 spi_cfg; -+ __le32 num_addr_cycle; -+ __le32 busy_wait_cnt; -+ __le32 flash_feature; - - __le32 erased_cw_detect_cfg_clr; - __le32 erased_cw_detect_cfg_set; -@@ -339,6 +343,7 @@ struct nandc_regs { - * - * @core_clk: controller clock - * @aon_clk: another controller clock -+ * @iomacro_clk: io macro clock - * - * @regs: a contiguous chunk of memory for DMA register - * writes. contains the register values to be -@@ -348,6 +353,7 @@ struct nandc_regs { - * initialized via DT match data - * - * @controller: base controller structure -+ * @qspi: qpic spi structure - * @host_list: list containing all the chips attached to the - * controller - * -@@ -392,6 +398,7 @@ struct qcom_nand_controller { - const struct qcom_nandc_props *props; - - struct nand_controller *controller; -+ struct qpic_spi_nand *qspi; - struct list_head host_list; - - union { diff --git a/target/linux/generic/backport-6.18/410-08-v6.15-spi-spi-qpic-snand-Fix-ECC_CFG_ECC_DISABLE-shift-in-.patch b/target/linux/generic/backport-6.18/410-08-v6.15-spi-spi-qpic-snand-Fix-ECC_CFG_ECC_DISABLE-shift-in-.patch deleted file mode 100644 index ad43f8dff1..0000000000 --- a/target/linux/generic/backport-6.18/410-08-v6.15-spi-spi-qpic-snand-Fix-ECC_CFG_ECC_DISABLE-shift-in-.patch +++ /dev/null @@ -1,28 +0,0 @@ -From cf1ba3cb245020459f2ca446b7a7b199839f5d83 Mon Sep 17 00:00:00 2001 -From: Dan Carpenter -Date: Thu, 6 Mar 2025 12:40:01 +0300 -Subject: [PATCH] spi: spi-qpic-snand: Fix ECC_CFG_ECC_DISABLE shift in - qcom_spi_read_last_cw() - -The ECC_CFG_ECC_DISABLE define is BIT(0). It's supposed to be used -directly instead of used as a shifter. - -Fixes: 7304d1909080 ("spi: spi-qpic: add driver for QCOM SPI NAND flash Interface") -Signed-off-by: Dan Carpenter -Link: https://patch.msgid.link/2f4b0a0b-2c03-41c0-8a4a-3d789a83832d@stanley.mountain -Signed-off-by: Mark Brown ---- - drivers/spi/spi-qpic-snand.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/spi/spi-qpic-snand.c -+++ b/drivers/spi/spi-qpic-snand.c -@@ -514,7 +514,7 @@ static int qcom_spi_read_last_cw(struct - cfg0 = (ecc_cfg->cfg0_raw & ~(7U << CW_PER_PAGE)) | - 0 << CW_PER_PAGE; - cfg1 = ecc_cfg->cfg1_raw; -- ecc_bch_cfg = 1 << ECC_CFG_ECC_DISABLE; -+ ecc_bch_cfg = ECC_CFG_ECC_DISABLE; - - snandc->regs->cmd = snandc->qspi->cmd; - snandc->regs->cfg0 = cpu_to_le32(cfg0); diff --git a/target/linux/generic/backport-6.18/410-09-v6.15-spi-spi-qpic-snand-avoid-memleak-in-qcom_spi_ecc_ini.patch b/target/linux/generic/backport-6.18/410-09-v6.15-spi-spi-qpic-snand-avoid-memleak-in-qcom_spi_ecc_ini.patch deleted file mode 100644 index 1e2a3b0298..0000000000 --- a/target/linux/generic/backport-6.18/410-09-v6.15-spi-spi-qpic-snand-avoid-memleak-in-qcom_spi_ecc_ini.patch +++ /dev/null @@ -1,35 +0,0 @@ -From d450cdd9c4398add1f2aa7200f2c95f1e3b9f9fa Mon Sep 17 00:00:00 2001 -From: Gabor Juhos -Date: Thu, 13 Mar 2025 19:31:21 +0100 -Subject: [PATCH] spi: spi-qpic-snand: avoid memleak in - qcom_spi_ecc_init_ctx_pipelined() - -When the allocation of the OOB buffer fails, the -qcom_spi_ecc_init_ctx_pipelined() function returns without freeing -the memory allocated for 'ecc_cfg' thus it can cause a memory leak. - -Call kfree() to free 'ecc_cfg' before returning from the function -to avoid that. - -Fixes: 7304d1909080 ("spi: spi-qpic: add driver for QCOM SPI NAND flash Interface") -Signed-off-by: Gabor Juhos -Link: https://patch.msgid.link/20250313-qpic-snand-memleak-fix-v1-1-e54e78d1da3a@gmail.com -Signed-off-by: Mark Brown ---- - drivers/spi/spi-qpic-snand.c | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - ---- a/drivers/spi/spi-qpic-snand.c -+++ b/drivers/spi/spi-qpic-snand.c -@@ -263,8 +263,10 @@ static int qcom_spi_ecc_init_ctx_pipelin - return -ENOMEM; - snandc->qspi->oob_buf = kzalloc(mtd->writesize + mtd->oobsize, - GFP_KERNEL); -- if (!snandc->qspi->oob_buf) -+ if (!snandc->qspi->oob_buf) { -+ kfree(ecc_cfg); - return -ENOMEM; -+ } - - memset(snandc->qspi->oob_buf, 0xff, mtd->writesize + mtd->oobsize); - diff --git a/target/linux/generic/backport-6.18/410-10-v6.15-spi-SPI_QPIC_SNAND-should-be-tristate-and-depend-on-.patch b/target/linux/generic/backport-6.18/410-10-v6.15-spi-SPI_QPIC_SNAND-should-be-tristate-and-depend-on-.patch deleted file mode 100644 index 5e92048438..0000000000 --- a/target/linux/generic/backport-6.18/410-10-v6.15-spi-SPI_QPIC_SNAND-should-be-tristate-and-depend-on-.patch +++ /dev/null @@ -1,49 +0,0 @@ -From d32c4e58545f17caaa854415f854691e32d42075 Mon Sep 17 00:00:00 2001 -From: Geert Uytterhoeven -Date: Wed, 26 Mar 2025 15:22:19 +0100 -Subject: [PATCH] spi: SPI_QPIC_SNAND should be tristate and depend on MTD - -SPI_QPIC_SNAND is the only driver that selects MTD instead of depending -on it, which could lead to circular dependencies. Moreover, as -SPI_QPIC_SNAND is bool, this forces MTD (and various related symbols) to -be built-in, as can be seen in an allmodconfig kernel. - -Except for a missing semicolon, there is no reason why SPI_QPIC_SNAND -cannot be tristate; all MODULE_*() boilerplate is already present. -Hence make SPI_QPIC_SNAND tristate, let it depend on MTD, and add the -missing semicolon. - -Fixes: 7304d1909080ef0c ("spi: spi-qpic: add driver for QCOM SPI NAND flash Interface") -Signed-off-by: Geert Uytterhoeven -Link: https://patch.msgid.link/b63db431cbf35223a4400e44c296293d32c4543c.1742998909.git.geert+renesas@glider.be -Signed-off-by: Mark Brown ---- - drivers/spi/Kconfig | 4 ++-- - drivers/spi/spi-qpic-snand.c | 2 +- - 2 files changed, 3 insertions(+), 3 deletions(-) - ---- a/drivers/spi/Kconfig -+++ b/drivers/spi/Kconfig -@@ -899,9 +899,9 @@ config SPI_QCOM_QSPI - QSPI(Quad SPI) driver for Qualcomm QSPI controller. - - config SPI_QPIC_SNAND -- bool "QPIC SNAND controller" -+ tristate "QPIC SNAND controller" - depends on ARCH_QCOM || COMPILE_TEST -- select MTD -+ depends on MTD - help - QPIC_SNAND (QPIC SPI NAND) driver for Qualcomm QPIC controller. - QPIC controller supports both parallel nand and serial nand. ---- a/drivers/spi/spi-qpic-snand.c -+++ b/drivers/spi/spi-qpic-snand.c -@@ -1614,7 +1614,7 @@ static const struct of_device_id qcom_sn - .data = &ipq9574_snandc_props, - }, - {} --} -+}; - MODULE_DEVICE_TABLE(of, qcom_snandc_of_match); - - static struct platform_driver qcom_spi_driver = { diff --git a/target/linux/generic/backport-6.18/410-11-v6.15-spi-spi-qpic-snand-propagate-errors-from-qcom_spi_block_erase.patch b/target/linux/generic/backport-6.18/410-11-v6.15-spi-spi-qpic-snand-propagate-errors-from-qcom_spi_block_erase.patch deleted file mode 100644 index 9da531bed1..0000000000 --- a/target/linux/generic/backport-6.18/410-11-v6.15-spi-spi-qpic-snand-propagate-errors-from-qcom_spi_block_erase.patch +++ /dev/null @@ -1,36 +0,0 @@ -From: Gabor Juhos -Date: Wed, 23 Apr 2025 21:31:57 +0200 -Subject: [PATCH] spi: spi-qpic-snand: propagate errors from - qcom_spi_block_erase() - -The qcom_spi_block_erase() function returns with error in case of -failure. Change the qcom_spi_send_cmdaddr() function to propagate -these errors to the callers instead of returning with success. - -Fixes: 7304d1909080 ("spi: spi-qpic: add driver for QCOM SPI NAND flash Interface") -Signed-off-by: Gabor Juhos -Reviewed-by: Abel Vesa -Reviewed-by: Md Sadre Alam ---- - drivers/spi/spi-qpic-snand.c | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - - ---- -base-commit: 9c32cda43eb78f78c73aee4aa344b777714e259b -change-id: 20250422-qpic-snand-propagate-error-9c95811ab811 - -Best regards, - ---- a/drivers/spi/spi-qpic-snand.c -+++ b/drivers/spi/spi-qpic-snand.c -@@ -1307,8 +1307,7 @@ static int qcom_spi_send_cmdaddr(struct - snandc->qspi->addr1 = cpu_to_le32(s_op.addr1_reg << 16); - snandc->qspi->addr2 = cpu_to_le32(s_op.addr2_reg); - snandc->qspi->cmd = cpu_to_le32(cmd); -- qcom_spi_block_erase(snandc); -- return 0; -+ return qcom_spi_block_erase(snandc); - default: - break; - } diff --git a/target/linux/generic/backport-6.18/410-12-v6.15-spi-spi-qpic-snand-fix-NAND_READ_LOCATION_2-register-handling.patch b/target/linux/generic/backport-6.18/410-12-v6.15-spi-spi-qpic-snand-fix-NAND_READ_LOCATION_2-register-handling.patch deleted file mode 100644 index a2cd636fee..0000000000 --- a/target/linux/generic/backport-6.18/410-12-v6.15-spi-spi-qpic-snand-fix-NAND_READ_LOCATION_2-register-handling.patch +++ /dev/null @@ -1,35 +0,0 @@ -From: Gabor Juhos -Date: Mon, 28 Apr 2025 09:30:55 +0200 -Subject: [PATCH] spi: spi-qpic-snand: fix NAND_READ_LOCATION_2 register - handling - -The precomputed value for the NAND_READ_LOCATION_2 register should be -stored in 'snandc->regs->read_location2'. - -Fix the qcom_spi_set_read_loc_first() function accordingly. - -Fixes: 7304d1909080 ("spi: spi-qpic: add driver for QCOM SPI NAND flash Interface") -Signed-off-by: Gabor Juhos -Reviewed-by: Md Sadre Alam ---- - drivers/spi/spi-qpic-snand.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - - ---- -base-commit: 15cfe55ec58ace931a73e19e5367598734ceb074 -change-id: 20250428-qpic-snand-readloc2-fix-bccd07cf26d3 - -Best regards, - ---- a/drivers/spi/spi-qpic-snand.c -+++ b/drivers/spi/spi-qpic-snand.c -@@ -142,7 +142,7 @@ static void qcom_spi_set_read_loc_first( - else if (reg == NAND_READ_LOCATION_1) - snandc->regs->read_location1 = locreg_val; - else if (reg == NAND_READ_LOCATION_2) -- snandc->regs->read_location1 = locreg_val; -+ snandc->regs->read_location2 = locreg_val; - else if (reg == NAND_READ_LOCATION_3) - snandc->regs->read_location3 = locreg_val; - } diff --git a/target/linux/generic/backport-6.18/410-13-v6.15-spi-spi-qpic-snand-use-kmalloc-for-OOB-buffer-alloca.patch b/target/linux/generic/backport-6.18/410-13-v6.15-spi-spi-qpic-snand-use-kmalloc-for-OOB-buffer-alloca.patch deleted file mode 100644 index 5a3d498bcb..0000000000 --- a/target/linux/generic/backport-6.18/410-13-v6.15-spi-spi-qpic-snand-use-kmalloc-for-OOB-buffer-alloca.patch +++ /dev/null @@ -1,29 +0,0 @@ -From f48d80503504257682e493dc17408f2f0b47bcfa Mon Sep 17 00:00:00 2001 -From: Gabor Juhos -Date: Thu, 20 Mar 2025 19:11:59 +0100 -Subject: [PATCH] spi: spi-qpic-snand: use kmalloc() for OOB buffer allocation - -The qcom_spi_ecc_init_ctx_pipelined() function allocates zeroed -memory for the OOB buffer, then it fills the buffer with '0xff' -bytes right after the allocation. In this case zeroing the memory -during allocation is superfluous, so use kmalloc() instead of -kzalloc() to avoid that. - -Signed-off-by: Gabor Juhos -Link: https://patch.msgid.link/20250320-qpic-snand-kmalloc-v1-1-94e267550675@gmail.com -Signed-off-by: Mark Brown ---- - drivers/spi/spi-qpic-snand.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/spi/spi-qpic-snand.c -+++ b/drivers/spi/spi-qpic-snand.c -@@ -261,7 +261,7 @@ static int qcom_spi_ecc_init_ctx_pipelin - ecc_cfg = kzalloc(sizeof(*ecc_cfg), GFP_KERNEL); - if (!ecc_cfg) - return -ENOMEM; -- snandc->qspi->oob_buf = kzalloc(mtd->writesize + mtd->oobsize, -+ snandc->qspi->oob_buf = kmalloc(mtd->writesize + mtd->oobsize, - GFP_KERNEL); - if (!snandc->qspi->oob_buf) { - kfree(ecc_cfg); diff --git a/target/linux/generic/backport-6.18/410-14-v6.16-spi-spi-qpic-snand-remove-unused-wlen-member-of-struct-qpic_spi_nand.patch b/target/linux/generic/backport-6.18/410-14-v6.16-spi-spi-qpic-snand-remove-unused-wlen-member-of-struct-qpic_spi_nand.patch deleted file mode 100644 index 55e84daf09..0000000000 --- a/target/linux/generic/backport-6.18/410-14-v6.16-spi-spi-qpic-snand-remove-unused-wlen-member-of-struct-qpic_spi_nand.patch +++ /dev/null @@ -1,30 +0,0 @@ -From: Gabor Juhos -Date: Thu, 24 Apr 2025 20:10:59 +0200 -Subject: [PATCH] spi: spi-qpic-snand: remove unused 'wlen' member of - 'struct qpic_spi_nand' - -The 'wlen' member of the qpic_spi_nand structure is never used in the -code so remove that. - -Signed-off-by: Gabor Juhos ---- - drivers/spi/spi-qpic-snand.c | 1 - - 1 file changed, 1 deletion(-) - - ---- -base-commit: 9c32cda43eb78f78c73aee4aa344b777714e259b -change-id: 20250424-qpic-snand-remove-wlen-c0cef3801a7f - -Best regards, - ---- a/drivers/spi/spi-qpic-snand.c -+++ b/drivers/spi/spi-qpic-snand.c -@@ -116,7 +116,6 @@ struct qpic_spi_nand { - struct nand_ecc_engine ecc_eng; - u8 *data_buf; - u8 *oob_buf; -- u32 wlen; - __le32 addr1; - __le32 addr2; - __le32 cmd; diff --git a/target/linux/generic/backport-6.18/411-v6.15-mtd-nand-Drop-explicit-test-for-built-in-CONFIG_SPI_.patch b/target/linux/generic/backport-6.18/411-v6.15-mtd-nand-Drop-explicit-test-for-built-in-CONFIG_SPI_.patch deleted file mode 100644 index 8019d2ccac..0000000000 --- a/target/linux/generic/backport-6.18/411-v6.15-mtd-nand-Drop-explicit-test-for-built-in-CONFIG_SPI_.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 36c6468724aa98d33fea9a1d7e07ddda6302f5d4 Mon Sep 17 00:00:00 2001 -From: Geert Uytterhoeven -Date: Fri, 28 Mar 2025 09:24:01 +0100 -Subject: mtd: nand: Drop explicit test for built-in CONFIG_SPI_QPIC_SNAND - -If CONFIG_SPI_QPIC_SNAND=m, but CONFIG_MTD_NAND_QCOM=n: - - ERROR: modpost: "qcom_nandc_unalloc" [drivers/spi/spi-qpic-snand.ko] undefined! - ... - -Fix this by dropping the explicit test for a built-in -CONFIG_SPI_QPIC_SNAND completely. Kbuild handles multiple and mixed -obj-y/obj-m rules for the same object file fine. - -Reported-by: kernel test robot -Closes: https://lore.kernel.org/oe-kbuild-all/202503280759.XhwLcV7m-lkp@intel.com/ -Fixes: 7304d1909080ef0c ("spi: spi-qpic: add driver for QCOM SPI NAND flash Interface") -Signed-off-by: Geert Uytterhoeven -Signed-off-by: Miquel Raynal ---- - drivers/mtd/nand/Makefile | 3 --- - 1 file changed, 3 deletions(-) - ---- a/drivers/mtd/nand/Makefile -+++ b/drivers/mtd/nand/Makefile -@@ -3,11 +3,8 @@ - nandcore-objs := core.o bbt.o - obj-$(CONFIG_MTD_NAND_CORE) += nandcore.o - obj-$(CONFIG_MTD_NAND_ECC_MEDIATEK) += ecc-mtk.o --ifeq ($(CONFIG_SPI_QPIC_SNAND),y) - obj-$(CONFIG_SPI_QPIC_SNAND) += qpic_common.o --else - obj-$(CONFIG_MTD_NAND_QCOM) += qpic_common.o --endif - obj-y += onenand/ - obj-y += raw/ - obj-y += spi/ diff --git a/target/linux/generic/backport-6.18/412-v6.16-next-spi-spi-qpic-snand-validate-user-chip-specific-ECC-properties.patch b/target/linux/generic/backport-6.18/412-v6.16-next-spi-spi-qpic-snand-validate-user-chip-specific-ECC-properties.patch deleted file mode 100644 index 2f951564c1..0000000000 --- a/target/linux/generic/backport-6.18/412-v6.16-next-spi-spi-qpic-snand-validate-user-chip-specific-ECC-properties.patch +++ /dev/null @@ -1,166 +0,0 @@ -From 65cb56d49f6edea409600a3c61effc70ee5d43d8 Mon Sep 17 00:00:00 2001 -From: Gabor Juhos -Date: Thu, 1 May 2025 18:19:16 +0200 -Subject: spi: spi-qpic-snand: validate user/chip specific ECC properties - -The driver only supports 512 bytes ECC step size and 4 bit ECC strength -at the moment, however it does not reject unsupported step/strength -configurations. Due to this, whenever the driver is used with a flash -chip which needs stronger ECC protection, the following warning is shown -in the kernel log: - - [ 0.574648] spi-nand spi0.0: GigaDevice SPI NAND was found. - [ 0.635748] spi-nand spi0.0: 256 MiB, block size: 128 KiB, page size: 2048, OOB size: 128 - [ 0.649079] nand: WARNING: (null): the ECC used on your system is too weak compared to the one required by the NAND chip - -Although the message indicates that something is wrong, but it often gets -unnoticed, which can cause serious problems. For example when the user -writes something into the flash chip despite the warning, the written data -may won't be readable by the bootloader or by the boot ROM. In the worst -case, when the attached SPI NAND chip is the boot device, the board may not -be able to boot anymore. - -Also, it is not even possible to create a backup of the flash, because -reading its content results in bogus data. For example, dumping the first -page of the flash gives this: - - # hexdump -C -n 2048 /dev/mtd0 - 00000000 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f |................| - * - 00000040 0f 0f 0f 0f 0f 0f 0f 0d 0f 0f 0f 0f 0f 0f 0f 0f |................| - 00000050 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f |................| - * - 000001c0 0f 0f 0f 0f ff 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f |................| - 000001d0 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f |................| - * - 00000200 0f 0f 0f 0f f5 5b ff ff 0f 0f 0f 0f 0f 0f 0f 0f |.....[..........| - 00000210 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f |................| - * - 000002f0 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 1f 0f 0f |................| - 00000300 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f |................| - * - 000003c0 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f ff 0f 0f 0f |................| - 000003d0 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f |................| - * - 00000400 0f 0f 0f 0f 0f 0f 0f 0f e9 74 c9 06 f5 5b ff ff |.........t...[..| - 00000410 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f |................| - * - 000005d0 0f 0f 0f 0f ff 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f |................| - 000005e0 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f |................| - * - 00000600 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f c6 be 0f c3 |................| - 00000610 e9 74 c9 06 f5 5b ff ff 0f 0f 0f 0f 0f 0f 0f 0f |.t...[..........| - 00000620 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f |................| - * - 00000770 0f 0f 0f 0f 8f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f |................| - 00000780 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f |................| - * - 00000800 - # - -Doing the same by using the downstream kernel results in different output: - - # hexdump -C -n 2048 /dev/mtd0 - 00000000 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f |................| - * - 00000800 - # - -This patch adds some sanity checks to the code to prevent using the driver -with unsupported ECC step/strength configurations. After the change, probing -of the driver fails in such cases: - - [ 0.655038] spi-nand spi0.0: GigaDevice SPI NAND was found. - [ 0.659159] spi-nand spi0.0: 256 MiB, block size: 128 KiB, page size: 2048, OOB size: 128 - [ 0.669138] qcom_snand 79b0000.spi: only 4 bits ECC strength is supported - [ 0.677476] nand: No suitable ECC configuration - [ 0.689909] spi-nand spi0.0: probe with driver spi-nand failed with error -95 - -This helps to avoid the aforementioned hassles until support for 8 bit ECC -strength gets implemented. - -Fixes: 7304d1909080 ("spi: spi-qpic: add driver for QCOM SPI NAND flash Interface") -Signed-off-by: Gabor Juhos -Link: https://patch.msgid.link/20250501-qpic-snand-validate-ecc-v1-1-532776581a66@gmail.com -Signed-off-by: Mark Brown ---- - drivers/spi/spi-qpic-snand.c | 42 +++++++++++++++++++++++++++++++----- - 1 file changed, 37 insertions(+), 5 deletions(-) - ---- a/drivers/spi/spi-qpic-snand.c -+++ b/drivers/spi/spi-qpic-snand.c -@@ -249,9 +249,11 @@ static const struct mtd_ooblayout_ops qc - static int qcom_spi_ecc_init_ctx_pipelined(struct nand_device *nand) - { - struct qcom_nand_controller *snandc = nand_to_qcom_snand(nand); -+ struct nand_ecc_props *reqs = &nand->ecc.requirements; -+ struct nand_ecc_props *user = &nand->ecc.user_conf; - struct nand_ecc_props *conf = &nand->ecc.ctx.conf; - struct mtd_info *mtd = nanddev_to_mtd(nand); -- int cwperpage, bad_block_byte; -+ int cwperpage, bad_block_byte, ret; - struct qpic_ecc *ecc_cfg; - - cwperpage = mtd->writesize / NANDC_STEP_SIZE; -@@ -260,11 +262,39 @@ static int qcom_spi_ecc_init_ctx_pipelin - ecc_cfg = kzalloc(sizeof(*ecc_cfg), GFP_KERNEL); - if (!ecc_cfg) - return -ENOMEM; -+ -+ if (user->step_size && user->strength) { -+ ecc_cfg->step_size = user->step_size; -+ ecc_cfg->strength = user->strength; -+ } else if (reqs->step_size && reqs->strength) { -+ ecc_cfg->step_size = reqs->step_size; -+ ecc_cfg->strength = reqs->strength; -+ } else { -+ /* use defaults */ -+ ecc_cfg->step_size = NANDC_STEP_SIZE; -+ ecc_cfg->strength = 4; -+ } -+ -+ if (ecc_cfg->step_size != NANDC_STEP_SIZE) { -+ dev_err(snandc->dev, -+ "only %u bytes ECC step size is supported\n", -+ NANDC_STEP_SIZE); -+ ret = -EOPNOTSUPP; -+ goto err_free_ecc_cfg; -+ } -+ -+ if (ecc_cfg->strength != 4) { -+ dev_err(snandc->dev, -+ "only 4 bits ECC strength is supported\n"); -+ ret = -EOPNOTSUPP; -+ goto err_free_ecc_cfg; -+ } -+ - snandc->qspi->oob_buf = kmalloc(mtd->writesize + mtd->oobsize, - GFP_KERNEL); - if (!snandc->qspi->oob_buf) { -- kfree(ecc_cfg); -- return -ENOMEM; -+ ret = -ENOMEM; -+ goto err_free_ecc_cfg; - } - - memset(snandc->qspi->oob_buf, 0xff, mtd->writesize + mtd->oobsize); -@@ -279,8 +309,6 @@ static int qcom_spi_ecc_init_ctx_pipelin - ecc_cfg->bytes = ecc_cfg->ecc_bytes_hw + ecc_cfg->spare_bytes + ecc_cfg->bbm_size; - - ecc_cfg->steps = 4; -- ecc_cfg->strength = 4; -- ecc_cfg->step_size = 512; - ecc_cfg->cw_data = 516; - ecc_cfg->cw_size = ecc_cfg->cw_data + ecc_cfg->bytes; - bad_block_byte = mtd->writesize - ecc_cfg->cw_size * (cwperpage - 1) + 1; -@@ -338,6 +366,10 @@ static int qcom_spi_ecc_init_ctx_pipelin - ecc_cfg->strength, ecc_cfg->step_size); - - return 0; -+ -+err_free_ecc_cfg: -+ kfree(ecc_cfg); -+ return ret; - } - - static void qcom_spi_ecc_cleanup_ctx_pipelined(struct nand_device *nand) diff --git a/target/linux/generic/backport-6.18/413-v6.16-spi-spi-qpic-snand-use-CW_PER_PAGE_MASK-bitmask.patch b/target/linux/generic/backport-6.18/413-v6.16-spi-spi-qpic-snand-use-CW_PER_PAGE_MASK-bitmask.patch deleted file mode 100644 index 10c1651b3b..0000000000 --- a/target/linux/generic/backport-6.18/413-v6.16-spi-spi-qpic-snand-use-CW_PER_PAGE_MASK-bitmask.patch +++ /dev/null @@ -1,113 +0,0 @@ -From 2abf107dcd797c60c86e9f17319cd1658862f6b2 Mon Sep 17 00:00:00 2001 -From: Gabor Juhos -Date: Thu, 15 May 2025 20:58:05 +0200 -Subject: spi: spi-qpic-snand: use CW_PER_PAGE_MASK bitmask - -Change the code to use the already defined CW_PER_PAGE_MASK -bitmask along with the FIELD_PREP() macro instead of using -magic values. - -This makes the code more readable. It also syncs the affected -codes with their counterparts in the 'qcom_nandc' driver, so it -makes it easier to spot the differences between the two -implementations. - -No functional changes intended. - -Signed-off-by: Gabor Juhos -Reviewed-by: Md Sadre Alam -Link: https://patch.msgid.link/20250515-qpic-snand-use-bitmasks-v1-1-11729aeae73b@gmail.com -Signed-off-by: Mark Brown ---- - drivers/spi/spi-qpic-snand.c | 31 ++++++++++++++++--------------- - 1 file changed, 16 insertions(+), 15 deletions(-) - ---- a/drivers/spi/spi-qpic-snand.c -+++ b/drivers/spi/spi-qpic-snand.c -@@ -483,7 +483,8 @@ static int qcom_spi_block_erase(struct q - snandc->regs->cmd = snandc->qspi->cmd; - snandc->regs->addr0 = snandc->qspi->addr1; - snandc->regs->addr1 = snandc->qspi->addr2; -- snandc->regs->cfg0 = cpu_to_le32(ecc_cfg->cfg0_raw & ~(7 << CW_PER_PAGE)); -+ snandc->regs->cfg0 = cpu_to_le32((ecc_cfg->cfg0_raw & ~CW_PER_PAGE_MASK) | -+ FIELD_PREP(CW_PER_PAGE_MASK, 0)); - snandc->regs->cfg1 = cpu_to_le32(ecc_cfg->cfg1_raw); - snandc->regs->exec = cpu_to_le32(1); - -@@ -544,8 +545,8 @@ static int qcom_spi_read_last_cw(struct - snandc->regs->addr0 = (snandc->qspi->addr1 | cpu_to_le32(col)); - snandc->regs->addr1 = snandc->qspi->addr2; - -- cfg0 = (ecc_cfg->cfg0_raw & ~(7U << CW_PER_PAGE)) | -- 0 << CW_PER_PAGE; -+ cfg0 = (ecc_cfg->cfg0_raw & ~CW_PER_PAGE_MASK) | -+ FIELD_PREP(CW_PER_PAGE_MASK, 0); - cfg1 = ecc_cfg->cfg1_raw; - ecc_bch_cfg = ECC_CFG_ECC_DISABLE; - -@@ -687,8 +688,8 @@ static int qcom_spi_read_cw_raw(struct q - qcom_clear_bam_transaction(snandc); - raw_cw = num_cw - 1; - -- cfg0 = (ecc_cfg->cfg0_raw & ~(7U << CW_PER_PAGE)) | -- 0 << CW_PER_PAGE; -+ cfg0 = (ecc_cfg->cfg0_raw & ~CW_PER_PAGE_MASK) | -+ FIELD_PREP(CW_PER_PAGE_MASK, 0); - cfg1 = ecc_cfg->cfg1_raw; - ecc_bch_cfg = ECC_CFG_ECC_DISABLE; - -@@ -808,8 +809,8 @@ static int qcom_spi_read_page_ecc(struct - snandc->buf_start = 0; - qcom_clear_read_regs(snandc); - -- cfg0 = (ecc_cfg->cfg0 & ~(7U << CW_PER_PAGE)) | -- (num_cw - 1) << CW_PER_PAGE; -+ cfg0 = (ecc_cfg->cfg0 & ~CW_PER_PAGE_MASK) | -+ FIELD_PREP(CW_PER_PAGE_MASK, num_cw - 1); - cfg1 = ecc_cfg->cfg1; - ecc_bch_cfg = ecc_cfg->ecc_bch_cfg; - -@@ -904,8 +905,8 @@ static int qcom_spi_read_page_oob(struct - qcom_clear_read_regs(snandc); - qcom_clear_bam_transaction(snandc); - -- cfg0 = (ecc_cfg->cfg0 & ~(7U << CW_PER_PAGE)) | -- (num_cw - 1) << CW_PER_PAGE; -+ cfg0 = (ecc_cfg->cfg0 & ~CW_PER_PAGE_MASK) | -+ FIELD_PREP(CW_PER_PAGE_MASK, num_cw - 1); - cfg1 = ecc_cfg->cfg1; - ecc_bch_cfg = ecc_cfg->ecc_bch_cfg; - -@@ -1015,8 +1016,8 @@ static int qcom_spi_program_raw(struct q - int num_cw = snandc->qspi->num_cw; - u32 cfg0, cfg1, ecc_bch_cfg; - -- cfg0 = (ecc_cfg->cfg0_raw & ~(7U << CW_PER_PAGE)) | -- (num_cw - 1) << CW_PER_PAGE; -+ cfg0 = (ecc_cfg->cfg0_raw & ~CW_PER_PAGE_MASK) | -+ FIELD_PREP(CW_PER_PAGE_MASK, num_cw - 1); - cfg1 = ecc_cfg->cfg1_raw; - ecc_bch_cfg = ECC_CFG_ECC_DISABLE; - -@@ -1098,8 +1099,8 @@ static int qcom_spi_program_ecc(struct q - int num_cw = snandc->qspi->num_cw; - u32 cfg0, cfg1, ecc_bch_cfg, ecc_buf_cfg; - -- cfg0 = (ecc_cfg->cfg0 & ~(7U << CW_PER_PAGE)) | -- (num_cw - 1) << CW_PER_PAGE; -+ cfg0 = (ecc_cfg->cfg0 & ~CW_PER_PAGE_MASK) | -+ FIELD_PREP(CW_PER_PAGE_MASK, num_cw - 1); - cfg1 = ecc_cfg->cfg1; - ecc_bch_cfg = ecc_cfg->ecc_bch_cfg; - ecc_buf_cfg = ecc_cfg->ecc_buf_cfg; -@@ -1175,8 +1176,8 @@ static int qcom_spi_program_oob(struct q - int num_cw = snandc->qspi->num_cw; - u32 cfg0, cfg1, ecc_bch_cfg, ecc_buf_cfg; - -- cfg0 = (ecc_cfg->cfg0 & ~(7U << CW_PER_PAGE)) | -- (num_cw - 1) << CW_PER_PAGE; -+ cfg0 = (ecc_cfg->cfg0 & ~CW_PER_PAGE_MASK) | -+ FIELD_PREP(CW_PER_PAGE_MASK, num_cw - 1); - cfg1 = ecc_cfg->cfg1; - ecc_bch_cfg = ecc_cfg->ecc_bch_cfg; - ecc_buf_cfg = ecc_cfg->ecc_buf_cfg; diff --git a/target/linux/generic/backport-6.18/414-v6.16-spi-spi-qpic-snand-reallocate-BAM-transactions.patch b/target/linux/generic/backport-6.18/414-v6.16-spi-spi-qpic-snand-reallocate-BAM-transactions.patch deleted file mode 100644 index 6d61016556..0000000000 --- a/target/linux/generic/backport-6.18/414-v6.16-spi-spi-qpic-snand-reallocate-BAM-transactions.patch +++ /dev/null @@ -1,81 +0,0 @@ -From d85d0380292a7e618915069c3579ae23c7c80339 Mon Sep 17 00:00:00 2001 -From: Gabor Juhos -Date: Wed, 18 Jun 2025 22:22:49 +0200 -Subject: spi: spi-qpic-snand: reallocate BAM transactions - -Using the mtd_nandbiterrs module for testing the driver occasionally -results in weird things like below. - -1. swiotlb mapping fails with the following message: - - [ 85.926216] qcom_snand 79b0000.spi: swiotlb buffer is full (sz: 4294967294 bytes), total 512 (slots), used 0 (slots) - [ 85.932937] qcom_snand 79b0000.spi: failure in mapping desc - [ 87.999314] qcom_snand 79b0000.spi: failure to write raw page - [ 87.999352] mtd_nandbiterrs: error: write_oob failed (-110) - - Rebooting the board after this causes a panic due to a NULL pointer - dereference. - -2. If the swiotlb mapping does not fail, rebooting the board may result - in a different panic due to a bad spinlock magic: - - [ 256.104459] BUG: spinlock bad magic on CPU#3, procd/2241 - [ 256.104488] Unable to handle kernel paging request at virtual address ffffffff0000049b - ... - -Investigating the issue revealed that these symptoms are results of -memory corruption which is caused by out of bounds access within the -driver. - -The driver uses a dynamically allocated structure for BAM transactions, -which structure must have enough space for all possible variations of -different flash operations initiated by the driver. The required space -heavily depends on the actual number of 'codewords' which is calculated -from the pagesize of the actual NAND chip. - -Although the qcom_nandc_alloc() function allocates memory for the BAM -transactions during probe, but since the actual number of 'codewords' -is not yet know the allocation is done for one 'codeword' only. - -Because of this, whenever the driver does a flash operation, and the -number of the required transactions exceeds the size of the allocated -arrays the driver accesses memory out of the allocated range. - -To avoid this, change the code to free the initially allocated BAM -transactions memory, and allocate a new one once the actual number of -'codewords' required for a given NAND chip is known. - -Fixes: 7304d1909080 ("spi: spi-qpic: add driver for QCOM SPI NAND flash Interface") -Reviewed-by: Md Sadre Alam -Signed-off-by: Gabor Juhos -Link: https://patch.msgid.link/20250618-qpic-snand-avoid-mem-corruption-v3-1-319c71296cda@gmail.com -Signed-off-by: Mark Brown ---- - drivers/spi/spi-qpic-snand.c | 16 ++++++++++++++++ - 1 file changed, 16 insertions(+) - ---- a/drivers/spi/spi-qpic-snand.c -+++ b/drivers/spi/spi-qpic-snand.c -@@ -315,6 +315,22 @@ static int qcom_spi_ecc_init_ctx_pipelin - - mtd_set_ooblayout(mtd, &qcom_spi_ooblayout); - -+ /* -+ * Free the temporary BAM transaction allocated initially by -+ * qcom_nandc_alloc(), and allocate a new one based on the -+ * updated max_cwperpage value. -+ */ -+ qcom_free_bam_transaction(snandc); -+ -+ snandc->max_cwperpage = cwperpage; -+ -+ snandc->bam_txn = qcom_alloc_bam_transaction(snandc); -+ if (!snandc->bam_txn) { -+ dev_err(snandc->dev, "failed to allocate BAM transaction\n"); -+ ret = -ENOMEM; -+ goto err_free_ecc_cfg; -+ } -+ - ecc_cfg->cfg0 = FIELD_PREP(CW_PER_PAGE_MASK, (cwperpage - 1)) | - FIELD_PREP(UD_SIZE_BYTES_MASK, ecc_cfg->cw_data) | - FIELD_PREP(DISABLE_STATUS_AFTER_WRITE, 1) | diff --git a/target/linux/generic/backport-6.18/415-v6.16-spi-spi-qpic-snand-don-t-hardcode-ECC-steps.patch b/target/linux/generic/backport-6.18/415-v6.16-spi-spi-qpic-snand-don-t-hardcode-ECC-steps.patch deleted file mode 100644 index eab7b792aa..0000000000 --- a/target/linux/generic/backport-6.18/415-v6.16-spi-spi-qpic-snand-don-t-hardcode-ECC-steps.patch +++ /dev/null @@ -1,31 +0,0 @@ -From f820034864dd463cdcd2bebe7940f2eca0eb4223 Mon Sep 17 00:00:00 2001 -From: Gabor Juhos -Date: Wed, 23 Jul 2025 10:06:43 +0200 -Subject: spi: spi-qpic-snand: don't hardcode ECC steps - -NAND devices with different page sizes requires different number -of ECC steps, yet the qcom_spi_ecc_init_ctx_pipelined() function -sets 4 steps in 'ecc_cfg' unconditionally. - -The correct number of the steps is calculated earlier in the -function already, so use that instead of the hardcoded value. - -Fixes: 7304d1909080 ("spi: spi-qpic: add driver for QCOM SPI NAND flash Interface") -Signed-off-by: Gabor Juhos -Link: https://patch.msgid.link/20250723-qpic-snand-fix-steps-v1-1-d800695dde4c@gmail.com -Signed-off-by: Mark Brown ---- - drivers/spi/spi-qpic-snand.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/spi/spi-qpic-snand.c -+++ b/drivers/spi/spi-qpic-snand.c -@@ -308,7 +308,7 @@ static int qcom_spi_ecc_init_ctx_pipelin - ecc_cfg->bch_enabled = true; - ecc_cfg->bytes = ecc_cfg->ecc_bytes_hw + ecc_cfg->spare_bytes + ecc_cfg->bbm_size; - -- ecc_cfg->steps = 4; -+ ecc_cfg->steps = cwperpage; - ecc_cfg->cw_data = 516; - ecc_cfg->cw_size = ecc_cfg->cw_data + ecc_cfg->bytes; - bad_block_byte = mtd->writesize - ecc_cfg->cw_size * (cwperpage - 1) + 1; diff --git a/target/linux/generic/backport-6.18/416-v6.17-mtd-nand-qpic-common-add-defines-for-ECC_MODE-values.patch b/target/linux/generic/backport-6.18/416-v6.17-mtd-nand-qpic-common-add-defines-for-ECC_MODE-values.patch deleted file mode 100644 index 7ddf15ef70..0000000000 --- a/target/linux/generic/backport-6.18/416-v6.17-mtd-nand-qpic-common-add-defines-for-ECC_MODE-values.patch +++ /dev/null @@ -1,74 +0,0 @@ -From 0dc7e656ddd54c3267b7cc18c1ac8ec1297ed02f Mon Sep 17 00:00:00 2001 -From: Gabor Juhos -Date: Wed, 2 Jul 2025 14:35:23 +0200 -Subject: mtd: nand: qpic-common: add defines for ECC_MODE values - -Add defines for the values of the ECC_MODE field of the NAND_DEV0_ECC_CFG -register and change both the 'qcom-nandc' and 'spi-qpic-snand' drivers to -use those instead of magic numbers. - -No functional changes. This is in preparation for adding 8 bit ECC strength -support for the 'spi-qpic-snand' driver. - -Reviewed-by: Md Sadre Alam -Signed-off-by: Gabor Juhos -Acked-by: Miquel Raynal -Link: https://patch.msgid.link/20250702-qpic-snand-8bit-ecc-v2-1-ae2c17a30bb7@gmail.com -Signed-off-by: Mark Brown ---- - drivers/mtd/nand/raw/qcom_nandc.c | 6 +++--- - drivers/spi/spi-qpic-snand.c | 2 +- - include/linux/mtd/nand-qpic-common.h | 2 ++ - 3 files changed, 6 insertions(+), 4 deletions(-) - ---- a/drivers/mtd/nand/raw/qcom_nandc.c -+++ b/drivers/mtd/nand/raw/qcom_nandc.c -@@ -1379,7 +1379,7 @@ static int qcom_nand_attach_chip(struct - struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); - int cwperpage, bad_block_byte, ret; - bool wide_bus; -- int ecc_mode = 1; -+ int ecc_mode = ECC_MODE_8BIT; - - /* controller only supports 512 bytes data steps */ - ecc->size = NANDC_STEP_SIZE; -@@ -1400,7 +1400,7 @@ static int qcom_nand_attach_chip(struct - if (ecc->strength >= 8) { - /* 8 bit ECC defaults to BCH ECC on all platforms */ - host->bch_enabled = true; -- ecc_mode = 1; -+ ecc_mode = ECC_MODE_8BIT; - - if (wide_bus) { - host->ecc_bytes_hw = 14; -@@ -1420,7 +1420,7 @@ static int qcom_nand_attach_chip(struct - if (nandc->props->ecc_modes & ECC_BCH_4BIT) { - /* BCH */ - host->bch_enabled = true; -- ecc_mode = 0; -+ ecc_mode = ECC_MODE_4BIT; - - if (wide_bus) { - host->ecc_bytes_hw = 8; ---- a/drivers/spi/spi-qpic-snand.c -+++ b/drivers/spi/spi-qpic-snand.c -@@ -365,7 +365,7 @@ static int qcom_spi_ecc_init_ctx_pipelin - FIELD_PREP(ECC_SW_RESET, 0) | - FIELD_PREP(ECC_NUM_DATA_BYTES_MASK, ecc_cfg->cw_data) | - FIELD_PREP(ECC_FORCE_CLK_OPEN, 1) | -- FIELD_PREP(ECC_MODE_MASK, 0) | -+ FIELD_PREP(ECC_MODE_MASK, ECC_MODE_4BIT) | - FIELD_PREP(ECC_PARITY_SIZE_BYTES_BCH_MASK, ecc_cfg->ecc_bytes_hw); - - ecc_cfg->ecc_buf_cfg = 0x203 << NUM_STEPS; ---- a/include/linux/mtd/nand-qpic-common.h -+++ b/include/linux/mtd/nand-qpic-common.h -@@ -101,6 +101,8 @@ - #define ECC_SW_RESET BIT(1) - #define ECC_MODE 4 - #define ECC_MODE_MASK GENMASK(5, 4) -+#define ECC_MODE_4BIT 0 -+#define ECC_MODE_8BIT 1 - #define ECC_PARITY_SIZE_BYTES_BCH 8 - #define ECC_PARITY_SIZE_BYTES_BCH_MASK GENMASK(12, 8) - #define ECC_NUM_DATA_BYTES 16 diff --git a/target/linux/generic/backport-6.18/417-v6.17-spi-spi-qpic-snand-add-support-for-8-bits-ECC-strength.patch b/target/linux/generic/backport-6.18/417-v6.17-spi-spi-qpic-snand-add-support-for-8-bits-ECC-strength.patch deleted file mode 100644 index 4eff84f419..0000000000 --- a/target/linux/generic/backport-6.18/417-v6.17-spi-spi-qpic-snand-add-support-for-8-bits-ECC-strength.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 913bf8d50cbd144c87e9660b591781179182ff59 Mon Sep 17 00:00:00 2001 -From: Gabor Juhos -Date: Wed, 2 Jul 2025 14:35:24 +0200 -Subject: spi: spi-qpic-snand: add support for 8 bits ECC strength - -Even though the hardware supports 8 bits ECC strength, but that is not -handled in the driver yet. This change adds the missing bits in order -to allow using the driver with chips which require 8 bits ECC strength. - -No functional changes intended with regard to the existing 4 bits ECC -strength support. - -Tested on an IPQ9574 platform using a GigaDevice GD5F2GM7REYIG chip. - -Signed-off-by: Gabor Juhos -Link: https://patch.msgid.link/20250702-qpic-snand-8bit-ecc-v2-2-ae2c17a30bb7@gmail.com -Signed-off-by: Mark Brown ---- - drivers/spi/spi-qpic-snand.c | 21 ++++++++++++++++----- - 1 file changed, 16 insertions(+), 5 deletions(-) - ---- a/drivers/spi/spi-qpic-snand.c -+++ b/drivers/spi/spi-qpic-snand.c -@@ -283,9 +283,22 @@ static int qcom_spi_ecc_init_ctx_pipelin - goto err_free_ecc_cfg; - } - -- if (ecc_cfg->strength != 4) { -+ switch (ecc_cfg->strength) { -+ case 4: -+ ecc_cfg->ecc_mode = ECC_MODE_4BIT; -+ ecc_cfg->ecc_bytes_hw = 7; -+ ecc_cfg->spare_bytes = 4; -+ break; -+ -+ case 8: -+ ecc_cfg->ecc_mode = ECC_MODE_8BIT; -+ ecc_cfg->ecc_bytes_hw = 13; -+ ecc_cfg->spare_bytes = 2; -+ break; -+ -+ default: - dev_err(snandc->dev, -- "only 4 bits ECC strength is supported\n"); -+ "only 4 or 8 bits ECC strength is supported\n"); - ret = -EOPNOTSUPP; - goto err_free_ecc_cfg; - } -@@ -302,8 +315,6 @@ static int qcom_spi_ecc_init_ctx_pipelin - nand->ecc.ctx.priv = ecc_cfg; - snandc->qspi->mtd = mtd; - -- ecc_cfg->ecc_bytes_hw = 7; -- ecc_cfg->spare_bytes = 4; - ecc_cfg->bbm_size = 1; - ecc_cfg->bch_enabled = true; - ecc_cfg->bytes = ecc_cfg->ecc_bytes_hw + ecc_cfg->spare_bytes + ecc_cfg->bbm_size; -@@ -365,7 +376,7 @@ static int qcom_spi_ecc_init_ctx_pipelin - FIELD_PREP(ECC_SW_RESET, 0) | - FIELD_PREP(ECC_NUM_DATA_BYTES_MASK, ecc_cfg->cw_data) | - FIELD_PREP(ECC_FORCE_CLK_OPEN, 1) | -- FIELD_PREP(ECC_MODE_MASK, ECC_MODE_4BIT) | -+ FIELD_PREP(ECC_MODE_MASK, ecc_cfg->ecc_mode) | - FIELD_PREP(ECC_PARITY_SIZE_BYTES_BCH_MASK, ecc_cfg->ecc_bytes_hw); - - ecc_cfg->ecc_buf_cfg = 0x203 << NUM_STEPS; diff --git a/target/linux/generic/backport-6.18/418-v6.17-spi-spi-qpic-snand-use-correct-CW_PER_PAGE-value-for.patch b/target/linux/generic/backport-6.18/418-v6.17-spi-spi-qpic-snand-use-correct-CW_PER_PAGE-value-for.patch deleted file mode 100644 index b67645e07c..0000000000 --- a/target/linux/generic/backport-6.18/418-v6.17-spi-spi-qpic-snand-use-correct-CW_PER_PAGE-value-for.patch +++ /dev/null @@ -1,56 +0,0 @@ -From 6bc829220b33da8522572cc50fdf5067c51d3bf3 Mon Sep 17 00:00:00 2001 -From: Gabor Juhos -Date: Fri, 1 Aug 2025 09:58:35 +0200 -Subject: spi: spi-qpic-snand: use correct CW_PER_PAGE value for OOB write - -The qcom_spi_program_oob() function uses only the last codeword to write -the OOB data into the flash, but it sets the CW_PER_PAGE field in the -CFG0 register as it would use all codewords. - -It seems that this confuses the hardware somehow, and any access to the -flash fails with a timeout error after the function is called. The problem -can be easily reproduced with the following commands: - - # dd if=/dev/zero bs=2176 count=1 > /tmp/test.bin - 1+0 records in - 1+0 records out - # flash_erase /dev/mtd4 0 0 - Erasing 128 Kibyte @ 0 -- 100 % complete - # nandwrite -O /dev/mtd4 /tmp/test.bin - Writing data to block 0 at offset 0x0 - # nanddump -o /dev/mtd4 >/dev/null - ECC failed: 0 - ECC corrected: 0 - Number of bad blocks: 0 - Number of bbt blocks: 0 - Block size 131072, page size 2048, OOB size 128 - Dumping data starting at 0x00000000 and ending at 0x00020000... - [ 33.197605] qcom_snand 79b0000.spi: failure to read oob - libmtd: error!: MEMREADOOB64 ioctl failed for mtd4, offset 0 (eraseblock 0) - error 110 (Operation timed out) - [ 35.277582] qcom_snand 79b0000.spi: failure in submitting cmd descriptor - libmtd: error!: cannot read 2048 bytes from mtd4 (eraseblock 0, offset 2048) - error 110 (Operation timed out) - nanddump: error!: mtd_read - -Change the code to use the correct CW_PER_PAGE value to avoid this. - -Fixes: 7304d1909080 ("spi: spi-qpic: add driver for QCOM SPI NAND flash Interface") -Signed-off-by: Gabor Juhos -Link: https://patch.msgid.link/20250801-qpic-snand-oob-cwpp-fix-v1-1-f5a41b86af2e@gmail.com -Signed-off-by: Mark Brown ---- - drivers/spi/spi-qpic-snand.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/spi/spi-qpic-snand.c -+++ b/drivers/spi/spi-qpic-snand.c -@@ -1204,7 +1204,7 @@ static int qcom_spi_program_oob(struct q - u32 cfg0, cfg1, ecc_bch_cfg, ecc_buf_cfg; - - cfg0 = (ecc_cfg->cfg0 & ~CW_PER_PAGE_MASK) | -- FIELD_PREP(CW_PER_PAGE_MASK, num_cw - 1); -+ FIELD_PREP(CW_PER_PAGE_MASK, 0); - cfg1 = ecc_cfg->cfg1; - ecc_bch_cfg = ecc_cfg->ecc_bch_cfg; - ecc_buf_cfg = ecc_cfg->ecc_buf_cfg; diff --git a/target/linux/generic/backport-6.18/419-v6.17-spi-spi-qpic-snand-fix-calculating-of-ECC-OOB-region.patch b/target/linux/generic/backport-6.18/419-v6.17-spi-spi-qpic-snand-fix-calculating-of-ECC-OOB-region.patch deleted file mode 100644 index 35d5d30232..0000000000 --- a/target/linux/generic/backport-6.18/419-v6.17-spi-spi-qpic-snand-fix-calculating-of-ECC-OOB-region.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 13d0fe84a214658254a7412b2b46ec1507dc51f0 Mon Sep 17 00:00:00 2001 -From: Gabor Juhos -Date: Tue, 5 Aug 2025 18:05:42 +0200 -Subject: spi: spi-qpic-snand: fix calculating of ECC OOB regions' properties - -The OOB layout used by the driver has two distinct regions which contains -hardware specific ECC data, yet the qcom_spi_ooblayout_ecc() function sets -the same offset and length values for both regions which is clearly wrong. - -Change the code to calculate the correct values for both regions. - -For reference, the following table shows the computed offset and length -values for various OOB size/ECC strength configurations: - - +-----------------+-----------------+ - |before the change| after the change| - +-------+----------+--------+--------+--------+--------+--------+ - | OOB | ECC | region | region | region | region | region | - | size | strength | index | offset | length | offset | length | - +-------+----------+--------+--------+--------+--------+--------+ - | 128 | 8 | 0 | 113 | 15 | 0 | 49 | - | | | 1 | 113 | 15 | 65 | 63 | - +-------+----------+--------+--------+--------+--------+--------+ - | 128 | 4 | 0 | 117 | 11 | 0 | 37 | - | | | 1 | 117 | 11 | 53 | 75 | - +-------+----------+--------+--------+--------+--------+--------+ - | 64 | 4 | 0 | 53 | 11 | 0 | 37 | - | | | 1 | 53 | 11 | 53 | 11 | - +-------+----------+--------+--------+--------+--------+--------+ - -Fixes: 7304d1909080 ("spi: spi-qpic: add driver for QCOM SPI NAND flash Interface") -Signed-off-by: Gabor Juhos -Reviewed-by: Konrad Dybcio -Link: https://patch.msgid.link/20250805-qpic-snand-oob-ecc-fix-v2-1-e6f811c70d6f@gmail.com -Signed-off-by: Mark Brown ---- - drivers/spi/spi-qpic-snand.c | 20 ++++++++++++++------ - 1 file changed, 14 insertions(+), 6 deletions(-) - ---- a/drivers/spi/spi-qpic-snand.c -+++ b/drivers/spi/spi-qpic-snand.c -@@ -216,13 +216,21 @@ static int qcom_spi_ooblayout_ecc(struct - struct qcom_nand_controller *snandc = nand_to_qcom_snand(nand); - struct qpic_ecc *qecc = snandc->qspi->ecc; - -- if (section > 1) -- return -ERANGE; -+ switch (section) { -+ case 0: -+ oobregion->offset = 0; -+ oobregion->length = qecc->bytes * (qecc->steps - 1) + -+ qecc->bbm_size; -+ return 0; -+ case 1: -+ oobregion->offset = qecc->bytes * (qecc->steps - 1) + -+ qecc->bbm_size + -+ qecc->steps * 4; -+ oobregion->length = mtd->oobsize - oobregion->offset; -+ return 0; -+ } - -- oobregion->length = qecc->ecc_bytes_hw + qecc->spare_bytes; -- oobregion->offset = mtd->oobsize - oobregion->length; -- -- return 0; -+ return -ERANGE; - } - - static int qcom_spi_ooblayout_free(struct mtd_info *mtd, int section, diff --git a/target/linux/generic/backport-6.18/420-01-v6.16-mtd-rawnand-brcmnand-remove-unused-parameters.patch b/target/linux/generic/backport-6.18/420-01-v6.16-mtd-rawnand-brcmnand-remove-unused-parameters.patch deleted file mode 100644 index 3bc6038711..0000000000 --- a/target/linux/generic/backport-6.18/420-01-v6.16-mtd-rawnand-brcmnand-remove-unused-parameters.patch +++ /dev/null @@ -1,88 +0,0 @@ -From 56fce75470041b5b0d92ae10637416e1a4cceb1b Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= -Date: Wed, 14 May 2025 08:14:54 +0200 -Subject: [PATCH] mtd: rawnand: brcmnand: remove unused parameters -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -last_cmd and last_byte are now unused brcmnand_host members. -last_addr is only written and never read so we can remove it too. - -Signed-off-by: Álvaro Fernández Rojas -Reviewed-by: Florian Fainelli -Reviewed-by: William Zhang -Signed-off-by: Miquel Raynal ---- - drivers/mtd/nand/raw/brcmnand/brcmnand.c | 24 ++++++------------------ - 1 file changed, 6 insertions(+), 18 deletions(-) - ---- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c -+++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c -@@ -310,9 +310,6 @@ struct brcmnand_host { - struct platform_device *pdev; - int cs; - -- unsigned int last_cmd; -- unsigned int last_byte; -- u64 last_addr; - struct brcmnand_cfg hwcfg; - struct brcmnand_controller *ctrl; - }; -@@ -2233,14 +2230,11 @@ static int brcmnand_read_page(struct nan - int oob_required, int page) - { - struct mtd_info *mtd = nand_to_mtd(chip); -- struct brcmnand_host *host = nand_get_controller_data(chip); - u8 *oob = oob_required ? (u8 *)chip->oob_poi : NULL; - u64 addr = (u64)page << chip->page_shift; - -- host->last_addr = addr; -- -- return brcmnand_read(mtd, chip, host->last_addr, -- mtd->writesize >> FC_SHIFT, (u32 *)buf, oob); -+ return brcmnand_read(mtd, chip, addr, mtd->writesize >> FC_SHIFT, -+ (u32 *)buf, oob); - } - - static int brcmnand_read_page_raw(struct nand_chip *chip, uint8_t *buf, -@@ -2252,11 +2246,9 @@ static int brcmnand_read_page_raw(struct - int ret; - u64 addr = (u64)page << chip->page_shift; - -- host->last_addr = addr; -- - brcmnand_set_ecc_enabled(host, 0); -- ret = brcmnand_read(mtd, chip, host->last_addr, -- mtd->writesize >> FC_SHIFT, (u32 *)buf, oob); -+ ret = brcmnand_read(mtd, chip, addr, mtd->writesize >> FC_SHIFT, -+ (u32 *)buf, oob); - brcmnand_set_ecc_enabled(host, 1); - return ret; - } -@@ -2363,13 +2355,10 @@ static int brcmnand_write_page(struct na - int oob_required, int page) - { - struct mtd_info *mtd = nand_to_mtd(chip); -- struct brcmnand_host *host = nand_get_controller_data(chip); - void *oob = oob_required ? chip->oob_poi : NULL; - u64 addr = (u64)page << chip->page_shift; - -- host->last_addr = addr; -- -- return brcmnand_write(mtd, chip, host->last_addr, (const u32 *)buf, oob); -+ return brcmnand_write(mtd, chip, addr, (const u32 *)buf, oob); - } - - static int brcmnand_write_page_raw(struct nand_chip *chip, const uint8_t *buf, -@@ -2381,9 +2370,8 @@ static int brcmnand_write_page_raw(struc - u64 addr = (u64)page << chip->page_shift; - int ret = 0; - -- host->last_addr = addr; - brcmnand_set_ecc_enabled(host, 0); -- ret = brcmnand_write(mtd, chip, host->last_addr, (const u32 *)buf, oob); -+ ret = brcmnand_write(mtd, chip, addr, (const u32 *)buf, oob); - brcmnand_set_ecc_enabled(host, 1); - - return ret; diff --git a/target/linux/generic/backport-6.18/420-02-v6.16-mtd-nand-brcmnand-fix-NAND-timeout-when-accessing-eM.patch b/target/linux/generic/backport-6.18/420-02-v6.16-mtd-nand-brcmnand-fix-NAND-timeout-when-accessing-eM.patch deleted file mode 100644 index d3dbde8b9e..0000000000 --- a/target/linux/generic/backport-6.18/420-02-v6.16-mtd-nand-brcmnand-fix-NAND-timeout-when-accessing-eM.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 528b541b71cf03e263272b051b70696f92258e9d Mon Sep 17 00:00:00 2001 -From: David Regan -Date: Thu, 22 May 2025 10:25:17 -0700 -Subject: [PATCH] mtd: nand: brcmnand: fix NAND timeout when accessing eMMC - -When booting a board to NAND and accessing NAND while eMMC -transactions are occurring the NAND will sometimes timeout. This -is due to both NAND and eMMC controller sharing the same data bus -on BCMBCA chips. Fix is to extend NAND timeout to allow eMMC -transactions time to complete. - -Signed-off-by: David Regan -Reviewed-by: William Zhang -Reviewed-by: Florian Fainelli -Signed-off-by: Miquel Raynal ---- - drivers/mtd/nand/raw/brcmnand/brcmnand.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c -+++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c -@@ -101,7 +101,7 @@ struct brcm_nand_dma_desc { - #define BRCMNAND_MIN_DEVSIZE (4ULL * 1024 * 1024) - - #define NAND_CTRL_RDY (INTFC_CTLR_READY | INTFC_FLASH_READY) --#define NAND_POLL_STATUS_TIMEOUT_MS 100 -+#define NAND_POLL_STATUS_TIMEOUT_MS 500 - - #define EDU_CMD_WRITE 0x00 - #define EDU_CMD_READ 0x01 diff --git a/target/linux/generic/backport-6.18/420-03-v6.16-mtd-rawnand-brcmnand-legacy-exec_op-implementation.patch b/target/linux/generic/backport-6.18/420-03-v6.16-mtd-rawnand-brcmnand-legacy-exec_op-implementation.patch deleted file mode 100644 index 6c75c2bbf2..0000000000 --- a/target/linux/generic/backport-6.18/420-03-v6.16-mtd-rawnand-brcmnand-legacy-exec_op-implementation.patch +++ /dev/null @@ -1,299 +0,0 @@ -From 3bfb22cecfe6b6f0d8ee56ef4b533cf68599c5d9 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= -Date: Wed, 21 May 2025 10:03:25 +0200 -Subject: [PATCH] mtd: rawnand: brcmnand: legacy exec_op implementation -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Commit 3c8260ce7663 ("mtd: rawnand: brcmnand: exec_op implementation") -removed legacy interface functions, breaking < v5.0 controllers support. -In order to fix older controllers we need to add an alternative exec_op -implementation which doesn't rely on low level registers. - -Fixes: 3c8260ce7663 ("mtd: rawnand: brcmnand: exec_op implementation") -Signed-off-by: Álvaro Fernández Rojas -Reviewed-by: David Regan -Reviewed-by: Florian Fainelli -Reviewed-by: William Zhang -Signed-off-by: Miquel Raynal ---- - drivers/mtd/nand/raw/brcmnand/brcmnand.c | 222 ++++++++++++++++++++++- - 1 file changed, 215 insertions(+), 7 deletions(-) - ---- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c -+++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c -@@ -65,6 +65,7 @@ module_param(wp_on, int, 0444); - #define CMD_PARAMETER_READ 0x0e - #define CMD_PARAMETER_CHANGE_COL 0x0f - #define CMD_LOW_LEVEL_OP 0x10 -+#define CMD_NOT_SUPPORTED 0xff - - struct brcm_nand_dma_desc { - u32 next_desc; -@@ -199,6 +200,30 @@ static const u16 flash_dma_regs_v4[] = { - [FLASH_DMA_CURRENT_DESC_EXT] = 0x34, - }; - -+/* Native command conversion for legacy controllers (< v5.0) */ -+static const u8 native_cmd_conv[] = { -+ [NAND_CMD_READ0] = CMD_NOT_SUPPORTED, -+ [NAND_CMD_READ1] = CMD_NOT_SUPPORTED, -+ [NAND_CMD_RNDOUT] = CMD_PARAMETER_CHANGE_COL, -+ [NAND_CMD_PAGEPROG] = CMD_NOT_SUPPORTED, -+ [NAND_CMD_READOOB] = CMD_NOT_SUPPORTED, -+ [NAND_CMD_ERASE1] = CMD_BLOCK_ERASE, -+ [NAND_CMD_STATUS] = CMD_NOT_SUPPORTED, -+ [NAND_CMD_SEQIN] = CMD_NOT_SUPPORTED, -+ [NAND_CMD_RNDIN] = CMD_NOT_SUPPORTED, -+ [NAND_CMD_READID] = CMD_DEVICE_ID_READ, -+ [NAND_CMD_ERASE2] = CMD_NULL, -+ [NAND_CMD_PARAM] = CMD_PARAMETER_READ, -+ [NAND_CMD_GET_FEATURES] = CMD_NOT_SUPPORTED, -+ [NAND_CMD_SET_FEATURES] = CMD_NOT_SUPPORTED, -+ [NAND_CMD_RESET] = CMD_NOT_SUPPORTED, -+ [NAND_CMD_READSTART] = CMD_NOT_SUPPORTED, -+ [NAND_CMD_READCACHESEQ] = CMD_NOT_SUPPORTED, -+ [NAND_CMD_READCACHEEND] = CMD_NOT_SUPPORTED, -+ [NAND_CMD_RNDOUTSTART] = CMD_NULL, -+ [NAND_CMD_CACHEDPROG] = CMD_NOT_SUPPORTED, -+}; -+ - /* Controller feature flags */ - enum { - BRCMNAND_HAS_1K_SECTORS = BIT(0), -@@ -237,6 +262,12 @@ struct brcmnand_controller { - /* List of NAND hosts (one for each chip-select) */ - struct list_head host_list; - -+ /* Functions to be called from exec_op */ -+ int (*check_instr)(struct nand_chip *chip, -+ const struct nand_operation *op); -+ int (*exec_instr)(struct nand_chip *chip, -+ const struct nand_operation *op); -+ - /* EDU info, per-transaction */ - const u16 *edu_offsets; - void __iomem *edu_base; -@@ -2478,18 +2509,190 @@ static int brcmnand_op_is_reset(const st - return 0; - } - -+static int brcmnand_check_instructions(struct nand_chip *chip, -+ const struct nand_operation *op) -+{ -+ return 0; -+} -+ -+static int brcmnand_exec_instructions(struct nand_chip *chip, -+ const struct nand_operation *op) -+{ -+ struct brcmnand_host *host = nand_get_controller_data(chip); -+ unsigned int i; -+ int ret = 0; -+ -+ for (i = 0; i < op->ninstrs; i++) { -+ ret = brcmnand_exec_instr(host, i, op); -+ if (ret) -+ break; -+ } -+ -+ return ret; -+} -+ -+static int brcmnand_check_instructions_legacy(struct nand_chip *chip, -+ const struct nand_operation *op) -+{ -+ const struct nand_op_instr *instr; -+ unsigned int i; -+ u8 cmd; -+ -+ for (i = 0; i < op->ninstrs; i++) { -+ instr = &op->instrs[i]; -+ -+ switch (instr->type) { -+ case NAND_OP_CMD_INSTR: -+ cmd = native_cmd_conv[instr->ctx.cmd.opcode]; -+ if (cmd == CMD_NOT_SUPPORTED) -+ return -EOPNOTSUPP; -+ break; -+ case NAND_OP_ADDR_INSTR: -+ case NAND_OP_DATA_IN_INSTR: -+ case NAND_OP_WAITRDY_INSTR: -+ break; -+ default: -+ return -EOPNOTSUPP; -+ } -+ } -+ -+ return 0; -+} -+ -+static int brcmnand_exec_instructions_legacy(struct nand_chip *chip, -+ const struct nand_operation *op) -+{ -+ struct mtd_info *mtd = nand_to_mtd(chip); -+ struct brcmnand_host *host = nand_get_controller_data(chip); -+ struct brcmnand_controller *ctrl = host->ctrl; -+ const struct nand_op_instr *instr; -+ unsigned int i, j; -+ u8 cmd = CMD_NULL, last_cmd = CMD_NULL; -+ int ret = 0; -+ u64 last_addr; -+ -+ for (i = 0; i < op->ninstrs; i++) { -+ instr = &op->instrs[i]; -+ -+ if (instr->type == NAND_OP_CMD_INSTR) { -+ cmd = native_cmd_conv[instr->ctx.cmd.opcode]; -+ if (cmd == CMD_NOT_SUPPORTED) { -+ dev_err(ctrl->dev, "unsupported cmd=%d\n", -+ instr->ctx.cmd.opcode); -+ ret = -EOPNOTSUPP; -+ break; -+ } -+ } else if (instr->type == NAND_OP_ADDR_INSTR) { -+ u64 addr = 0; -+ -+ if (cmd == CMD_NULL) -+ continue; -+ -+ if (instr->ctx.addr.naddrs > 8) { -+ dev_err(ctrl->dev, "unsupported naddrs=%u\n", -+ instr->ctx.addr.naddrs); -+ ret = -EOPNOTSUPP; -+ break; -+ } -+ -+ for (j = 0; j < instr->ctx.addr.naddrs; j++) -+ addr |= (instr->ctx.addr.addrs[j]) << (j << 3); -+ -+ if (cmd == CMD_BLOCK_ERASE) -+ addr <<= chip->page_shift; -+ else if (cmd == CMD_PARAMETER_CHANGE_COL) -+ addr &= ~((u64)(FC_BYTES - 1)); -+ -+ brcmnand_set_cmd_addr(mtd, addr); -+ brcmnand_send_cmd(host, cmd); -+ last_addr = addr; -+ last_cmd = cmd; -+ cmd = CMD_NULL; -+ brcmnand_waitfunc(chip); -+ -+ if (last_cmd == CMD_PARAMETER_READ || -+ last_cmd == CMD_PARAMETER_CHANGE_COL) { -+ /* Copy flash cache word-wise */ -+ u32 *flash_cache = (u32 *)ctrl->flash_cache; -+ -+ brcmnand_soc_data_bus_prepare(ctrl->soc, true); -+ -+ /* -+ * Must cache the FLASH_CACHE now, since changes in -+ * SECTOR_SIZE_1K may invalidate it -+ */ -+ for (j = 0; j < FC_WORDS; j++) -+ /* -+ * Flash cache is big endian for parameter pages, at -+ * least on STB SoCs -+ */ -+ flash_cache[j] = be32_to_cpu(brcmnand_read_fc(ctrl, j)); -+ -+ brcmnand_soc_data_bus_unprepare(ctrl->soc, true); -+ } -+ } else if (instr->type == NAND_OP_DATA_IN_INSTR) { -+ u8 *in = instr->ctx.data.buf.in; -+ -+ if (last_cmd == CMD_DEVICE_ID_READ) { -+ u32 val; -+ -+ if (instr->ctx.data.len > 8) { -+ dev_err(ctrl->dev, "unsupported len=%u\n", -+ instr->ctx.data.len); -+ ret = -EOPNOTSUPP; -+ break; -+ } -+ -+ for (j = 0; j < instr->ctx.data.len; j++) { -+ if (j == 0) -+ val = brcmnand_read_reg(ctrl, BRCMNAND_ID); -+ else if (j == 4) -+ val = brcmnand_read_reg(ctrl, BRCMNAND_ID_EXT); -+ -+ in[j] = (val >> (24 - ((j % 4) << 3))) & 0xff; -+ } -+ } else if (last_cmd == CMD_PARAMETER_READ || -+ last_cmd == CMD_PARAMETER_CHANGE_COL) { -+ u64 addr; -+ u32 offs; -+ -+ for (j = 0; j < instr->ctx.data.len; j++) { -+ addr = last_addr + j; -+ offs = addr & (FC_BYTES - 1); -+ -+ if (j > 0 && offs == 0) -+ nand_change_read_column_op(chip, addr, NULL, 0, -+ false); -+ -+ in[j] = ctrl->flash_cache[offs]; -+ } -+ } -+ } else if (instr->type == NAND_OP_WAITRDY_INSTR) { -+ ret = bcmnand_ctrl_poll_status(host, NAND_CTRL_RDY, NAND_CTRL_RDY, 0); -+ if (ret) -+ break; -+ } else { -+ dev_err(ctrl->dev, "unsupported instruction type: %d\n", instr->type); -+ ret = -EOPNOTSUPP; -+ break; -+ } -+ } -+ -+ return ret; -+} -+ - static int brcmnand_exec_op(struct nand_chip *chip, - const struct nand_operation *op, - bool check_only) - { - struct brcmnand_host *host = nand_get_controller_data(chip); -+ struct brcmnand_controller *ctrl = host->ctrl; - struct mtd_info *mtd = nand_to_mtd(chip); - u8 *status; -- unsigned int i; - int ret = 0; - - if (check_only) -- return 0; -+ return ctrl->check_instr(chip, op); - - if (brcmnand_op_is_status(op)) { - status = op->instrs[1].ctx.data.buf.in; -@@ -2513,11 +2716,7 @@ static int brcmnand_exec_op(struct nand_ - if (op->deassert_wp) - brcmnand_wp(mtd, 0); - -- for (i = 0; i < op->ninstrs; i++) { -- ret = brcmnand_exec_instr(host, i, op); -- if (ret) -- break; -- } -+ ret = ctrl->exec_instr(chip, op); - - if (op->deassert_wp) - brcmnand_wp(mtd, 1); -@@ -3130,6 +3329,15 @@ int brcmnand_probe(struct platform_devic - if (ret) - goto err; - -+ /* Only v5.0+ controllers have low level ops support */ -+ if (ctrl->nand_version >= 0x0500) { -+ ctrl->check_instr = brcmnand_check_instructions; -+ ctrl->exec_instr = brcmnand_exec_instructions; -+ } else { -+ ctrl->check_instr = brcmnand_check_instructions_legacy; -+ ctrl->exec_instr = brcmnand_exec_instructions_legacy; -+ } -+ - /* - * Most chips have this cache at a fixed offset within 'nand' block. - * Some must specify this region separately. diff --git a/target/linux/generic/backport-6.18/422-v6.17-spi-spi-qpic-snand-unregister-ECC-engine-on-probe-er.patch b/target/linux/generic/backport-6.18/422-v6.17-spi-spi-qpic-snand-unregister-ECC-engine-on-probe-er.patch deleted file mode 100644 index 46184b53c5..0000000000 --- a/target/linux/generic/backport-6.18/422-v6.17-spi-spi-qpic-snand-unregister-ECC-engine-on-probe-er.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 1991a458528588ff34e98b6365362560d208710f Mon Sep 17 00:00:00 2001 -From: Gabor Juhos -Date: Wed, 3 Sep 2025 13:56:24 +0200 -Subject: spi: spi-qpic-snand: unregister ECC engine on probe error and device - remove - -The on-host hardware ECC engine remains registered both when -the spi_register_controller() function returns with an error -and also on device removal. - -Change the qcom_spi_probe() function to unregister the engine -on the error path, and add the missing unregistering call to -qcom_spi_remove() to avoid possible use-after-free issues. - -Fixes: 7304d1909080 ("spi: spi-qpic: add driver for QCOM SPI NAND flash Interface") -Signed-off-by: Gabor Juhos -Message-ID: <20250903-qpic-snand-unregister-ecceng-v1-1-ef5387b0abdc@gmail.com> -Signed-off-by: Mark Brown ---- - drivers/spi/spi-qpic-snand.c | 6 ++++-- - 1 file changed, 4 insertions(+), 2 deletions(-) - ---- a/drivers/spi/spi-qpic-snand.c -+++ b/drivers/spi/spi-qpic-snand.c -@@ -1632,11 +1632,13 @@ static int qcom_spi_probe(struct platfor - ret = spi_register_controller(ctlr); - if (ret) { - dev_err(&pdev->dev, "spi_register_controller failed.\n"); -- goto err_spi_init; -+ goto err_register_controller; - } - - return 0; - -+err_register_controller: -+ nand_ecc_unregister_on_host_hw_engine(&snandc->qspi->ecc_eng); - err_spi_init: - qcom_nandc_unalloc(snandc); - err_snand_alloc: -@@ -1658,7 +1660,7 @@ static void qcom_spi_remove(struct platf - struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - - spi_unregister_controller(ctlr); -- -+ nand_ecc_unregister_on_host_hw_engine(&snandc->qspi->ecc_eng); - qcom_nandc_unalloc(snandc); - - clk_disable_unprepare(snandc->aon_clk); diff --git a/target/linux/generic/backport-6.18/429-01-v6.18-mtd-spinand-fix-direct-mapping-creation-sizes.patch b/target/linux/generic/backport-6.18/429-01-v6.18-mtd-spinand-fix-direct-mapping-creation-sizes.patch deleted file mode 100644 index 6abc202337..0000000000 --- a/target/linux/generic/backport-6.18/429-01-v6.18-mtd-spinand-fix-direct-mapping-creation-sizes.patch +++ /dev/null @@ -1,63 +0,0 @@ -From e4a0cf9f1d90e6888e5373da3314f761024f6c97 Mon Sep 17 00:00:00 2001 -From: Mikhail Kshevetskiy -Date: Thu, 18 Sep 2025 00:53:59 +0300 -Subject: mtd: spinand: fix direct mapping creation sizes - -Continuous mode is only supported for data reads, thus writing -requires only single flash page mapping. - -Signed-off-by: Mikhail Kshevetskiy -Signed-off-by: Miquel Raynal ---- - drivers/mtd/nand/spi/core.c | 14 +++++++------- - 1 file changed, 7 insertions(+), 7 deletions(-) - ---- a/drivers/mtd/nand/spi/core.c -+++ b/drivers/mtd/nand/spi/core.c -@@ -1036,18 +1036,13 @@ static int spinand_create_dirmap(struct - unsigned int plane) - { - struct nand_device *nand = spinand_to_nand(spinand); -- struct spi_mem_dirmap_info info = { -- .length = nanddev_page_size(nand) + -- nanddev_per_page_oobsize(nand), -- }; -+ struct spi_mem_dirmap_info info = { 0 }; - struct spi_mem_dirmap_desc *desc; - -- if (spinand->cont_read_possible) -- info.length = nanddev_eraseblock_size(nand); -- - /* The plane number is passed in MSB just above the column address */ - info.offset = plane << fls(nand->memorg.pagesize); - -+ info.length = nanddev_page_size(nand) + nanddev_per_page_oobsize(nand); - info.op_tmpl = *spinand->op_templates.update_cache; - desc = devm_spi_mem_dirmap_create(&spinand->spimem->spi->dev, - spinand->spimem, &info); -@@ -1056,6 +1051,8 @@ static int spinand_create_dirmap(struct - - spinand->dirmaps[plane].wdesc = desc; - -+ if (spinand->cont_read_possible) -+ info.length = nanddev_eraseblock_size(nand); - info.op_tmpl = *spinand->op_templates.read_cache; - desc = devm_spi_mem_dirmap_create(&spinand->spimem->spi->dev, - spinand->spimem, &info); -@@ -1071,6 +1068,7 @@ static int spinand_create_dirmap(struct - return 0; - } - -+ info.length = nanddev_page_size(nand) + nanddev_per_page_oobsize(nand); - info.op_tmpl = *spinand->op_templates.update_cache; - info.op_tmpl.data.ecc = true; - desc = devm_spi_mem_dirmap_create(&spinand->spimem->spi->dev, -@@ -1080,6 +1078,8 @@ static int spinand_create_dirmap(struct - - spinand->dirmaps[plane].wdesc_ecc = desc; - -+ if (spinand->cont_read_possible) -+ info.length = nanddev_eraseblock_size(nand); - info.op_tmpl = *spinand->op_templates.read_cache; - info.op_tmpl.data.ecc = true; - desc = devm_spi_mem_dirmap_create(&spinand->spimem->spi->dev, diff --git a/target/linux/generic/backport-6.18/429-02-v6.18-mtd-spinand-try-a-regular-dirmap-if-creating-a-di.patch b/target/linux/generic/backport-6.18/429-02-v6.18-mtd-spinand-try-a-regular-dirmap-if-creating-a-di.patch deleted file mode 100644 index cc94e6d957..0000000000 --- a/target/linux/generic/backport-6.18/429-02-v6.18-mtd-spinand-try-a-regular-dirmap-if-creating-a-di.patch +++ /dev/null @@ -1,98 +0,0 @@ -From 004f8ea0d9917398aabff7388b3bf62a84a4088b Mon Sep 17 00:00:00 2001 -From: Mikhail Kshevetskiy -Date: Thu, 18 Sep 2025 00:54:00 +0300 -Subject: mtd: spinand: try a regular dirmap if creating a dirmap for - continuous reading fails - -Continuous reading may result in multiple flash pages reading in one -operation. Typically only one flash page has read/written (a little bit -more than 2-4 Kb), but continuous reading requires the spi controller -to read up to 512 Kb in one operation without toggling CS in beetween. - -Roughly speaking spi controllers can be divided on 2 categories: - * spi controllers without dirmap acceleration support - * spi controllers with dirmap acceleration support - -Firt of them will have issues with continuous reading if restriction on -the transfer length is implemented in the adjust_op_size() handler. -Second group often supports acceleration of single page only reading. -Thus enabling of continuous reading can break flash reading. - -This patch tries to create dirmap for continuous reading first and -fallback to regular reading if spi controller refuses to create it. - -Signed-off-by: Mikhail Kshevetskiy -Signed-off-by: Miquel Raynal ---- - drivers/mtd/nand/spi/core.c | 43 ++++++++++++++++++++++++++++++------- - 1 file changed, 35 insertions(+), 8 deletions(-) - ---- a/drivers/mtd/nand/spi/core.c -+++ b/drivers/mtd/nand/spi/core.c -@@ -1032,6 +1032,39 @@ static int spinand_mtd_block_isreserved( - return ret; - } - -+static struct spi_mem_dirmap_desc *spinand_create_rdesc( -+ struct spinand_device *spinand, -+ struct spi_mem_dirmap_info *info) -+{ -+ struct nand_device *nand = spinand_to_nand(spinand); -+ struct spi_mem_dirmap_desc *desc = NULL; -+ -+ if (spinand->cont_read_possible) { -+ /* -+ * spi controller may return an error if info->length is -+ * too large -+ */ -+ info->length = nanddev_eraseblock_size(nand); -+ desc = devm_spi_mem_dirmap_create(&spinand->spimem->spi->dev, -+ spinand->spimem, info); -+ } -+ -+ if (IS_ERR_OR_NULL(desc)) { -+ /* -+ * continuous reading is not supported by flash or -+ * its spi controller, use regular reading -+ */ -+ spinand->cont_read_possible = false; -+ -+ info->length = nanddev_page_size(nand) + -+ nanddev_per_page_oobsize(nand); -+ desc = devm_spi_mem_dirmap_create(&spinand->spimem->spi->dev, -+ spinand->spimem, info); -+ } -+ -+ return desc; -+} -+ - static int spinand_create_dirmap(struct spinand_device *spinand, - unsigned int plane) - { -@@ -1051,11 +1084,8 @@ static int spinand_create_dirmap(struct - - spinand->dirmaps[plane].wdesc = desc; - -- if (spinand->cont_read_possible) -- info.length = nanddev_eraseblock_size(nand); - info.op_tmpl = *spinand->op_templates.read_cache; -- desc = devm_spi_mem_dirmap_create(&spinand->spimem->spi->dev, -- spinand->spimem, &info); -+ desc = spinand_create_rdesc(spinand, &info); - if (IS_ERR(desc)) - return PTR_ERR(desc); - -@@ -1078,12 +1108,9 @@ static int spinand_create_dirmap(struct - - spinand->dirmaps[plane].wdesc_ecc = desc; - -- if (spinand->cont_read_possible) -- info.length = nanddev_eraseblock_size(nand); - info.op_tmpl = *spinand->op_templates.read_cache; - info.op_tmpl.data.ecc = true; -- desc = devm_spi_mem_dirmap_create(&spinand->spimem->spi->dev, -- spinand->spimem, &info); -+ desc = spinand_create_rdesc(spinand, &info); - if (IS_ERR(desc)) - return PTR_ERR(desc); - diff --git a/target/linux/generic/backport-6.18/429-03-v6.18-mtd-spinand-repeat-reading-in-regular-mode-if-con.patch b/target/linux/generic/backport-6.18/429-03-v6.18-mtd-spinand-repeat-reading-in-regular-mode-if-con.patch deleted file mode 100644 index 38d5712249..0000000000 --- a/target/linux/generic/backport-6.18/429-03-v6.18-mtd-spinand-repeat-reading-in-regular-mode-if-con.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 010dc7f2dd6a0078ade3f88f627ed5fbf45ceb94 Mon Sep 17 00:00:00 2001 -From: Mikhail Kshevetskiy -Date: Thu, 18 Sep 2025 00:54:01 +0300 -Subject: mtd: spinand: repeat reading in regular mode if continuous reading - fails - -Continuous reading may result in multiple flash pages reading in one -operation. Unfortunately, not all spinand controllers support such -large reading. They will read less data. Unfortunately, the operation -can't be continued. - -In this case: - * disable continuous reading on this (not good enough) spi controller - * repeat reading in regular mode. - -Signed-off-by: Mikhail Kshevetskiy -Signed-off-by: Miquel Raynal ---- - drivers/mtd/nand/spi/core.c | 25 +++++++++++++++++++++---- - 1 file changed, 21 insertions(+), 4 deletions(-) - ---- a/drivers/mtd/nand/spi/core.c -+++ b/drivers/mtd/nand/spi/core.c -@@ -427,8 +427,16 @@ static int spinand_read_from_cache_op(st - * Dirmap accesses are allowed to toggle the CS. - * Toggling the CS during a continuous read is forbidden. - */ -- if (nbytes && req->continuous) -- return -EIO; -+ if (nbytes && req->continuous) { -+ /* -+ * Spi controller with broken support of continuous -+ * reading was detected. Disable future use of -+ * continuous reading and return -EAGAIN to retry -+ * reading within regular mode. -+ */ -+ spinand->cont_read_possible = false; -+ return -EAGAIN; -+ } - } - - if (req->datalen) -@@ -849,10 +857,19 @@ static int spinand_mtd_read(struct mtd_i - - old_stats = mtd->ecc_stats; - -- if (spinand_use_cont_read(mtd, from, ops)) -+ if (spinand_use_cont_read(mtd, from, ops)) { - ret = spinand_mtd_continuous_page_read(mtd, from, ops, &max_bitflips); -- else -+ if (ret == -EAGAIN && !spinand->cont_read_possible) { -+ /* -+ * Spi controller with broken support of continuous -+ * reading was detected (see spinand_read_from_cache_op()), -+ * repeat reading in regular mode. -+ */ -+ ret = spinand_mtd_regular_page_read(mtd, from, ops, &max_bitflips); -+ } -+ } else { - ret = spinand_mtd_regular_page_read(mtd, from, ops, &max_bitflips); -+ } - - if (ops->stats) { - ops->stats->uncorrectable_errors += diff --git a/target/linux/generic/backport-6.18/430-v6.14-mtd-spinand-Introduce-a-way-to-avoid-raw-access.patch b/target/linux/generic/backport-6.18/430-v6.14-mtd-spinand-Introduce-a-way-to-avoid-raw-access.patch deleted file mode 100644 index 094d89b9f4..0000000000 --- a/target/linux/generic/backport-6.18/430-v6.14-mtd-spinand-Introduce-a-way-to-avoid-raw-access.patch +++ /dev/null @@ -1,81 +0,0 @@ -From 6d9d6ab3a82af50e36e13e7bc8e2d1b970e39f79 Mon Sep 17 00:00:00 2001 -From: Takahiro Kuwano -Date: Tue, 3 Dec 2024 11:46:49 +0900 -Subject: [PATCH 1/1] mtd: spinand: Introduce a way to avoid raw access - -SkyHigh spinand device has ECC enable bit in configuration register but -it must be always enabled. If ECC is disabled, read and write ops -results in undetermined state. For such devices, a way to avoid raw -access is needed. - -Introduce SPINAND_NO_RAW_ACCESS flag to advertise the device does not -support raw access. In such devices, the on-die ECC engine ops returns -error to I/O request in raw mode. - -Checking and marking BBM need to be cared as special case, by adding -fallback mechanism that tries read/write OOB with ECC enabled. - -Signed-off-by: Takahiro Kuwano -Signed-off-by: Miquel Raynal ---- - drivers/mtd/nand/spi/core.c | 22 ++++++++++++++++++++-- - include/linux/mtd/spinand.h | 1 + - 2 files changed, 21 insertions(+), 2 deletions(-) - ---- a/drivers/mtd/nand/spi/core.c -+++ b/drivers/mtd/nand/spi/core.c -@@ -294,6 +294,9 @@ static int spinand_ondie_ecc_prepare_io_ - struct spinand_device *spinand = nand_to_spinand(nand); - bool enable = (req->mode != MTD_OPS_RAW); - -+ if (!enable && spinand->flags & SPINAND_NO_RAW_ACCESS) -+ return -EOPNOTSUPP; -+ - memset(spinand->oobbuf, 0xff, nanddev_per_page_oobsize(nand)); - - /* Only enable or disable the engine */ -@@ -929,9 +932,17 @@ static bool spinand_isbad(struct nand_de - .oobbuf.in = marker, - .mode = MTD_OPS_RAW, - }; -+ int ret; - - spinand_select_target(spinand, pos->target); -- spinand_read_page(spinand, &req); -+ -+ ret = spinand_read_page(spinand, &req); -+ if (ret == -EOPNOTSUPP) { -+ /* Retry with ECC in case raw access is not supported */ -+ req.mode = MTD_OPS_PLACE_OOB; -+ spinand_read_page(spinand, &req); -+ } -+ - if (marker[0] != 0xff || marker[1] != 0xff) - return true; - -@@ -974,7 +985,14 @@ static int spinand_markbad(struct nand_d - if (ret) - return ret; - -- return spinand_write_page(spinand, &req); -+ ret = spinand_write_page(spinand, &req); -+ if (ret == -EOPNOTSUPP) { -+ /* Retry with ECC in case raw access is not supported */ -+ req.mode = MTD_OPS_PLACE_OOB; -+ ret = spinand_write_page(spinand, &req); -+ } -+ -+ return ret; - } - - static int spinand_mtd_block_markbad(struct mtd_info *mtd, loff_t offs) ---- a/include/linux/mtd/spinand.h -+++ b/include/linux/mtd/spinand.h -@@ -315,6 +315,7 @@ struct spinand_ecc_info { - #define SPINAND_HAS_CR_FEAT_BIT BIT(1) - #define SPINAND_HAS_PROG_PLANE_SELECT_BIT BIT(2) - #define SPINAND_HAS_READ_PLANE_SELECT_BIT BIT(3) -+#define SPINAND_NO_RAW_ACCESS BIT(4) - - /** - * struct spinand_ondie_ecc_conf - private SPI-NAND on-die ECC engine structure diff --git a/target/linux/generic/backport-6.18/431-v6.14-mtd-spinand-Add-support-for-SkyHigh-S35ML-3-family.patch b/target/linux/generic/backport-6.18/431-v6.14-mtd-spinand-Add-support-for-SkyHigh-S35ML-3-family.patch deleted file mode 100644 index 762978d47d..0000000000 --- a/target/linux/generic/backport-6.18/431-v6.14-mtd-spinand-Add-support-for-SkyHigh-S35ML-3-family.patch +++ /dev/null @@ -1,201 +0,0 @@ -From 1a50e3612de9187857f55ee14a573f7f8e7d4ebc Mon Sep 17 00:00:00 2001 -From: Takahiro Kuwano -Date: Tue, 3 Dec 2024 11:46:50 +0900 -Subject: [PATCH] mtd: spinand: Add support for SkyHigh S35ML-3 family - -SkyHigh S35ML01G300, S35ML01G301, S35ML02G300, and S35ML04G300 are 1Gb, -2Gb, and 4Gb SLC SPI NAND flash family. This family of devices has -on-die ECC which parity bits are stored to hidden area. In this family -the on-die ECC cannot be disabled so raw access needs to be prevented. - -Link: https://www.skyhighmemory.com/download/SPI_S35ML01_04G3_002_19205.pdf?v=P -Co-developed-by: KR Kim -Signed-off-by: KR Kim -Signed-off-by: Takahiro Kuwano -Signed-off-by: Miquel Raynal ---- - drivers/mtd/nand/spi/Makefile | 2 +- - drivers/mtd/nand/spi/core.c | 1 + - drivers/mtd/nand/spi/skyhigh.c | 147 +++++++++++++++++++++++++++++++++ - include/linux/mtd/spinand.h | 1 + - 4 files changed, 150 insertions(+), 1 deletion(-) - create mode 100644 drivers/mtd/nand/spi/skyhigh.c - ---- a/drivers/mtd/nand/spi/Makefile -+++ b/drivers/mtd/nand/spi/Makefile -@@ -1,4 +1,4 @@ - # SPDX-License-Identifier: GPL-2.0 - spinand-objs := core.o alliancememory.o ato.o esmt.o fmsh.o foresee.o gigadevice.o macronix.o --spinand-objs += micron.o paragon.o toshiba.o winbond.o xtx.o -+spinand-objs += micron.o paragon.o skyhigh.o toshiba.o winbond.o xtx.o - obj-$(CONFIG_MTD_SPI_NAND) += spinand.o ---- a/drivers/mtd/nand/spi/core.c -+++ b/drivers/mtd/nand/spi/core.c -@@ -1191,6 +1191,7 @@ static const struct spinand_manufacturer - ¯onix_spinand_manufacturer, - µn_spinand_manufacturer, - ¶gon_spinand_manufacturer, -+ &skyhigh_spinand_manufacturer, - &toshiba_spinand_manufacturer, - &winbond_spinand_manufacturer, - &xtx_spinand_manufacturer, ---- /dev/null -+++ b/drivers/mtd/nand/spi/skyhigh.c -@@ -0,0 +1,147 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (c) 2024 SkyHigh Memory Limited -+ * -+ * Author: Takahiro Kuwano -+ * Co-Author: KR Kim -+ */ -+ -+#include -+#include -+#include -+ -+#define SPINAND_MFR_SKYHIGH 0x01 -+#define SKYHIGH_STATUS_ECC_1TO2_BITFLIPS (1 << 4) -+#define SKYHIGH_STATUS_ECC_3TO6_BITFLIPS (2 << 4) -+#define SKYHIGH_STATUS_ECC_UNCOR_ERROR (3 << 4) -+#define SKYHIGH_CONFIG_PROTECT_EN BIT(1) -+ -+static SPINAND_OP_VARIANTS(read_cache_variants, -+ SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 4, NULL, 0), -+ SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0), -+ SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 2, NULL, 0), -+ SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0), -+ SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0), -+ SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0)); -+ -+static SPINAND_OP_VARIANTS(write_cache_variants, -+ SPINAND_PROG_LOAD_X4(true, 0, NULL, 0), -+ SPINAND_PROG_LOAD(true, 0, NULL, 0)); -+ -+static SPINAND_OP_VARIANTS(update_cache_variants, -+ SPINAND_PROG_LOAD_X4(false, 0, NULL, 0), -+ SPINAND_PROG_LOAD(false, 0, NULL, 0)); -+ -+static int skyhigh_spinand_ooblayout_ecc(struct mtd_info *mtd, int section, -+ struct mtd_oob_region *region) -+{ -+ /* ECC bytes are stored in hidden area. */ -+ return -ERANGE; -+} -+ -+static int skyhigh_spinand_ooblayout_free(struct mtd_info *mtd, int section, -+ struct mtd_oob_region *region) -+{ -+ if (section) -+ return -ERANGE; -+ -+ /* ECC bytes are stored in hidden area. Reserve 2 bytes for the BBM. */ -+ region->offset = 2; -+ region->length = mtd->oobsize - 2; -+ -+ return 0; -+} -+ -+static const struct mtd_ooblayout_ops skyhigh_spinand_ooblayout = { -+ .ecc = skyhigh_spinand_ooblayout_ecc, -+ .free = skyhigh_spinand_ooblayout_free, -+}; -+ -+static int skyhigh_spinand_ecc_get_status(struct spinand_device *spinand, -+ u8 status) -+{ -+ switch (status & STATUS_ECC_MASK) { -+ case STATUS_ECC_NO_BITFLIPS: -+ return 0; -+ -+ case SKYHIGH_STATUS_ECC_UNCOR_ERROR: -+ return -EBADMSG; -+ -+ case SKYHIGH_STATUS_ECC_1TO2_BITFLIPS: -+ return 2; -+ -+ case SKYHIGH_STATUS_ECC_3TO6_BITFLIPS: -+ return 6; -+ -+ default: -+ break; -+ } -+ -+ return -EINVAL; -+} -+ -+static const struct spinand_info skyhigh_spinand_table[] = { -+ SPINAND_INFO("S35ML01G301", -+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x15), -+ NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1), -+ NAND_ECCREQ(6, 32), -+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants, -+ &write_cache_variants, -+ &update_cache_variants), -+ SPINAND_NO_RAW_ACCESS, -+ SPINAND_ECCINFO(&skyhigh_spinand_ooblayout, -+ skyhigh_spinand_ecc_get_status)), -+ SPINAND_INFO("S35ML01G300", -+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x14), -+ NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1), -+ NAND_ECCREQ(6, 32), -+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants, -+ &write_cache_variants, -+ &update_cache_variants), -+ SPINAND_NO_RAW_ACCESS, -+ SPINAND_ECCINFO(&skyhigh_spinand_ooblayout, -+ skyhigh_spinand_ecc_get_status)), -+ SPINAND_INFO("S35ML02G300", -+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x25), -+ NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 2, 1, 1), -+ NAND_ECCREQ(6, 32), -+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants, -+ &write_cache_variants, -+ &update_cache_variants), -+ SPINAND_NO_RAW_ACCESS, -+ SPINAND_ECCINFO(&skyhigh_spinand_ooblayout, -+ skyhigh_spinand_ecc_get_status)), -+ SPINAND_INFO("S35ML04G300", -+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x35), -+ NAND_MEMORG(1, 2048, 128, 64, 4096, 80, 2, 1, 1), -+ NAND_ECCREQ(6, 32), -+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants, -+ &write_cache_variants, -+ &update_cache_variants), -+ SPINAND_NO_RAW_ACCESS, -+ SPINAND_ECCINFO(&skyhigh_spinand_ooblayout, -+ skyhigh_spinand_ecc_get_status)), -+}; -+ -+static int skyhigh_spinand_init(struct spinand_device *spinand) -+{ -+ /* -+ * Config_Protect_En (bit 1 in Block Lock register) must be set to 1 -+ * before writing other bits. Do it here before core unlocks all blocks -+ * by writing block protection bits. -+ */ -+ return spinand_write_reg_op(spinand, REG_BLOCK_LOCK, -+ SKYHIGH_CONFIG_PROTECT_EN); -+} -+ -+static const struct spinand_manufacturer_ops skyhigh_spinand_manuf_ops = { -+ .init = skyhigh_spinand_init, -+}; -+ -+const struct spinand_manufacturer skyhigh_spinand_manufacturer = { -+ .id = SPINAND_MFR_SKYHIGH, -+ .name = "SkyHigh", -+ .chips = skyhigh_spinand_table, -+ .nchips = ARRAY_SIZE(skyhigh_spinand_table), -+ .ops = &skyhigh_spinand_manuf_ops, -+}; ---- a/include/linux/mtd/spinand.h -+++ b/include/linux/mtd/spinand.h -@@ -269,6 +269,7 @@ extern const struct spinand_manufacturer - extern const struct spinand_manufacturer macronix_spinand_manufacturer; - extern const struct spinand_manufacturer micron_spinand_manufacturer; - extern const struct spinand_manufacturer paragon_spinand_manufacturer; -+extern const struct spinand_manufacturer skyhigh_spinand_manufacturer; - extern const struct spinand_manufacturer toshiba_spinand_manufacturer; - extern const struct spinand_manufacturer winbond_spinand_manufacturer; - extern const struct spinand_manufacturer xtx_spinand_manufacturer; diff --git a/target/linux/generic/backport-6.18/500-01-v6.13-block-add-support-for-defining-read-only-partitions.patch b/target/linux/generic/backport-6.18/500-01-v6.13-block-add-support-for-defining-read-only-partitions.patch deleted file mode 100644 index cdf505f3ce..0000000000 --- a/target/linux/generic/backport-6.18/500-01-v6.13-block-add-support-for-defining-read-only-partitions.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 03cb793b26834ddca170ba87057c8f883772dd45 Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Thu, 3 Oct 2024 00:11:41 +0200 -Subject: [PATCH 1/5] block: add support for defining read-only partitions - -Add support for defining read-only partitions and complete support for -it in the cmdline partition parser as the additional "ro" after a -partition is scanned but never actually applied. - -Signed-off-by: Christian Marangi -Reviewed-by: Christoph Hellwig -Link: https://lore.kernel.org/r/20241002221306.4403-2-ansuelsmth@gmail.com -Signed-off-by: Jens Axboe ---- - block/blk.h | 1 + - block/partitions/cmdline.c | 3 +++ - block/partitions/core.c | 3 +++ - 3 files changed, 7 insertions(+) - ---- a/block/blk.h -+++ b/block/blk.h -@@ -574,6 +574,7 @@ void blk_free_ext_minor(unsigned int min - #define ADDPART_FLAG_NONE 0 - #define ADDPART_FLAG_RAID 1 - #define ADDPART_FLAG_WHOLEDISK 2 -+#define ADDPART_FLAG_READONLY 4 - int bdev_add_partition(struct gendisk *disk, int partno, sector_t start, - sector_t length); - int bdev_del_partition(struct gendisk *disk, int partno); ---- a/block/partitions/cmdline.c -+++ b/block/partitions/cmdline.c -@@ -237,6 +237,9 @@ static int add_part(int slot, struct cmd - put_partition(state, slot, subpart->from >> 9, - subpart->size >> 9); - -+ if (subpart->flags & PF_RDONLY) -+ state->parts[slot].flags |= ADDPART_FLAG_READONLY; -+ - info = &state->parts[slot].info; - - strscpy(info->volname, subpart->name, sizeof(info->volname)); ---- a/block/partitions/core.c -+++ b/block/partitions/core.c -@@ -373,6 +373,9 @@ static struct block_device *add_partitio - goto out_del; - } - -+ if (flags & ADDPART_FLAG_READONLY) -+ bdev_set_flag(bdev, BD_READ_ONLY); -+ - /* everything is up and running, commence */ - err = xa_insert(&disk->part_tbl, partno, bdev, GFP_KERNEL); - if (err) diff --git a/target/linux/generic/backport-6.18/500-02-v6.13-block-introduce-add_disk_fwnode.patch b/target/linux/generic/backport-6.18/500-02-v6.13-block-introduce-add_disk_fwnode.patch deleted file mode 100644 index 381838d8ea..0000000000 --- a/target/linux/generic/backport-6.18/500-02-v6.13-block-introduce-add_disk_fwnode.patch +++ /dev/null @@ -1,94 +0,0 @@ -From e5f587242b6072ffab4f4a084a459a59f3035873 Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Thu, 3 Oct 2024 00:11:43 +0200 -Subject: [PATCH 3/5] block: introduce add_disk_fwnode() - -Introduce add_disk_fwnode() as a replacement of device_add_disk() that -permits to pass and attach a fwnode to disk dev. - -This variant can be useful for eMMC that might have the partition table -for the disk defined in DT. A parser can later make use of the attached -fwnode to parse the related table and init the hardcoded partition for -the disk. - -device_add_disk() is converted to a simple wrapper of add_disk_fwnode() -with the fwnode entry set as NULL. - -Signed-off-by: Christian Marangi -Reviewed-by: Christoph Hellwig -Link: https://lore.kernel.org/r/20241002221306.4403-4-ansuelsmth@gmail.com -Signed-off-by: Jens Axboe ---- - block/genhd.c | 28 ++++++++++++++++++++++++---- - include/linux/blkdev.h | 3 +++ - 2 files changed, 27 insertions(+), 4 deletions(-) - ---- a/block/genhd.c -+++ b/block/genhd.c -@@ -383,16 +383,18 @@ int disk_scan_partitions(struct gendisk - } - - /** -- * device_add_disk - add disk information to kernel list -+ * add_disk_fwnode - add disk information to kernel list with fwnode - * @parent: parent device for the disk - * @disk: per-device partitioning information - * @groups: Additional per-device sysfs groups -+ * @fwnode: attached disk fwnode - * - * This function registers the partitioning information in @disk -- * with the kernel. -+ * with the kernel. Also attach a fwnode to the disk device. - */ --int __must_check device_add_disk(struct device *parent, struct gendisk *disk, -- const struct attribute_group **groups) -+int __must_check add_disk_fwnode(struct device *parent, struct gendisk *disk, -+ const struct attribute_group **groups, -+ struct fwnode_handle *fwnode) - - { - struct device *ddev = disk_to_dev(disk); -@@ -452,6 +454,8 @@ int __must_check device_add_disk(struct - ddev->parent = parent; - ddev->groups = groups; - dev_set_name(ddev, "%s", disk->disk_name); -+ if (fwnode) -+ device_set_node(ddev, fwnode); - if (!(disk->flags & GENHD_FL_HIDDEN)) - ddev->devt = MKDEV(disk->major, disk->first_minor); - ret = device_add(ddev); -@@ -553,6 +557,22 @@ out_exit_elevator: - elevator_exit(disk->queue); - return ret; - } -+EXPORT_SYMBOL_GPL(add_disk_fwnode); -+ -+/** -+ * device_add_disk - add disk information to kernel list -+ * @parent: parent device for the disk -+ * @disk: per-device partitioning information -+ * @groups: Additional per-device sysfs groups -+ * -+ * This function registers the partitioning information in @disk -+ * with the kernel. -+ */ -+int __must_check device_add_disk(struct device *parent, struct gendisk *disk, -+ const struct attribute_group **groups) -+{ -+ return add_disk_fwnode(parent, disk, groups, NULL); -+} - EXPORT_SYMBOL(device_add_disk); - - static void blk_report_disk_dead(struct gendisk *disk, bool surprise) ---- a/include/linux/blkdev.h -+++ b/include/linux/blkdev.h -@@ -789,6 +789,9 @@ static inline unsigned int blk_queue_dep - #define for_each_bio(_bio) \ - for (; _bio; _bio = _bio->bi_next) - -+int __must_check add_disk_fwnode(struct device *parent, struct gendisk *disk, -+ const struct attribute_group **groups, -+ struct fwnode_handle *fwnode); - int __must_check device_add_disk(struct device *parent, struct gendisk *disk, - const struct attribute_group **groups); - static inline int __must_check add_disk(struct gendisk *disk) diff --git a/target/linux/generic/backport-6.18/500-03-v6.13-mmc-block-attach-partitions-fwnode-if-found-in-mmc-c.patch b/target/linux/generic/backport-6.18/500-03-v6.13-mmc-block-attach-partitions-fwnode-if-found-in-mmc-c.patch deleted file mode 100644 index 0bdeaa85e4..0000000000 --- a/target/linux/generic/backport-6.18/500-03-v6.13-mmc-block-attach-partitions-fwnode-if-found-in-mmc-c.patch +++ /dev/null @@ -1,104 +0,0 @@ -From 45ff6c340ddfc2dade74d5b7a8962c778ab7042c Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Thu, 3 Oct 2024 00:11:44 +0200 -Subject: [PATCH 4/5] mmc: block: attach partitions fwnode if found in mmc-card - -Attach partitions fwnode if found in mmc-card and register disk with it. - -This permits block partition to reference the node and register a -partition table defined in DT for the special case for embedded device -that doesn't have a partition table flashed but have an hardcoded -partition table passed from the system. - -JEDEC BOOT partition boot0/boot1 are supported but in DT we refer with -the JEDEC name of boot1 and boot2 to better adhere to documentation. - -Also JEDEC GP partition gp0/1/2/3 are supported but in DT we refer with -the JEDEC name of gp1/2/3/4 to better adhere to documentration. - -Signed-off-by: Christian Marangi -Reviewed-by: Linus Walleij -Link: https://lore.kernel.org/r/20241002221306.4403-5-ansuelsmth@gmail.com -Signed-off-by: Jens Axboe ---- - drivers/mmc/core/block.c | 55 +++++++++++++++++++++++++++++++++++++++- - 1 file changed, 54 insertions(+), 1 deletion(-) - ---- a/drivers/mmc/core/block.c -+++ b/drivers/mmc/core/block.c -@@ -2517,6 +2517,56 @@ static inline int mmc_blk_readonly(struc - !(card->csd.cmdclass & CCC_BLOCK_WRITE); - } - -+/* -+ * Search for a declared partitions node for the disk in mmc-card related node. -+ * -+ * This is to permit support for partition table defined in DT in special case -+ * where a partition table is not written in the disk and is expected to be -+ * passed from the running system. -+ * -+ * For the user disk, "partitions" node is searched. -+ * For the special HW disk, "partitions-" node with the appended name is used -+ * following this conversion table (to adhere to JEDEC naming) -+ * - boot0 -> partitions-boot1 -+ * - boot1 -> partitions-boot2 -+ * - gp0 -> partitions-gp1 -+ * - gp1 -> partitions-gp2 -+ * - gp2 -> partitions-gp3 -+ * - gp3 -> partitions-gp4 -+ */ -+static struct fwnode_handle *mmc_blk_get_partitions_node(struct device *mmc_dev, -+ const char *subname) -+{ -+ const char *node_name = "partitions"; -+ -+ if (subname) { -+ mmc_dev = mmc_dev->parent; -+ -+ /* -+ * Check if we are allocating a BOOT disk boot0/1 disk. -+ * In DT we use the JEDEC naming boot1/2. -+ */ -+ if (!strcmp(subname, "boot0")) -+ node_name = "partitions-boot1"; -+ if (!strcmp(subname, "boot1")) -+ node_name = "partitions-boot2"; -+ /* -+ * Check if we are allocating a GP disk gp0/1/2/3 disk. -+ * In DT we use the JEDEC naming gp1/2/3/4. -+ */ -+ if (!strcmp(subname, "gp0")) -+ node_name = "partitions-gp1"; -+ if (!strcmp(subname, "gp1")) -+ node_name = "partitions-gp2"; -+ if (!strcmp(subname, "gp2")) -+ node_name = "partitions-gp3"; -+ if (!strcmp(subname, "gp3")) -+ node_name = "partitions-gp4"; -+ } -+ -+ return device_get_named_child_node(mmc_dev, node_name); -+} -+ - static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card, - struct device *parent, - sector_t size, -@@ -2525,6 +2575,7 @@ static struct mmc_blk_data *mmc_blk_allo - int area_type, - unsigned int part_type) - { -+ struct fwnode_handle *disk_fwnode; - struct mmc_blk_data *md; - int devidx, ret; - char cap_str[10]; -@@ -2626,7 +2677,9 @@ static struct mmc_blk_data *mmc_blk_allo - /* used in ->open, must be set before add_disk: */ - if (area_type == MMC_BLK_DATA_AREA_MAIN) - dev_set_drvdata(&card->dev, md); -- ret = device_add_disk(md->parent, md->disk, mmc_disk_attr_groups); -+ disk_fwnode = mmc_blk_get_partitions_node(parent, subname); -+ ret = add_disk_fwnode(md->parent, md->disk, mmc_disk_attr_groups, -+ disk_fwnode); - if (ret) - goto err_put_disk; - return md; diff --git a/target/linux/generic/backport-6.18/500-04-v6.13-block-add-support-for-partition-table-defined-in-OF.patch b/target/linux/generic/backport-6.18/500-04-v6.13-block-add-support-for-partition-table-defined-in-OF.patch deleted file mode 100644 index d260be168c..0000000000 --- a/target/linux/generic/backport-6.18/500-04-v6.13-block-add-support-for-partition-table-defined-in-OF.patch +++ /dev/null @@ -1,200 +0,0 @@ -From 884555b557e5e6d41c866e2cd8d7b32f50ec974b Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Thu, 3 Oct 2024 00:11:45 +0200 -Subject: [PATCH 5/5] block: add support for partition table defined in OF - -Add support for partition table defined in Device Tree. Similar to how -it's done with MTD, add support for defining a fixed partition table in -device tree. - -A common scenario for this is fixed block (eMMC) embedded devices that -have no MBR or GPT partition table to save storage space. Bootloader -access the block device with absolute address of data. - -This is to complete the functionality with an equivalent implementation -with providing partition table with bootargs, for case where the booargs -can't be modified and tweaking the Device Tree is the only solution to -have an usabe partition table. - -The implementation follow the fixed-partitions parser used on MTD -devices where a "partitions" node is expected to be declared with -"fixed-partitions" compatible in the OF node of the disk device -(mmc-card for eMMC for example) and each child node declare a label -and a reg with offset and size. If label is not declared, the node name -is used as fallback. Eventually is also possible to declare the read-only -property to flag the partition as read-only. - -Signed-off-by: Christian Marangi -Reviewed-by: Christoph Hellwig -Link: https://lore.kernel.org/r/20241002221306.4403-6-ansuelsmth@gmail.com -Signed-off-by: Jens Axboe ---- - block/partitions/Kconfig | 9 ++++ - block/partitions/Makefile | 1 + - block/partitions/check.h | 1 + - block/partitions/core.c | 3 ++ - block/partitions/of.c | 110 ++++++++++++++++++++++++++++++++++++++ - 5 files changed, 124 insertions(+) - create mode 100644 block/partitions/of.c - ---- a/block/partitions/Kconfig -+++ b/block/partitions/Kconfig -@@ -270,4 +270,13 @@ config CMDLINE_PARTITION - Say Y here if you want to read the partition table from bootargs. - The format for the command line is just like mtdparts. - -+config OF_PARTITION -+ bool "Device Tree partition support" if PARTITION_ADVANCED -+ depends on OF -+ help -+ Say Y here if you want to enable support for partition table -+ defined in Device Tree. (mainly for eMMC) -+ The format for the device tree node is just like MTD fixed-partition -+ schema. -+ - endmenu ---- a/block/partitions/Makefile -+++ b/block/partitions/Makefile -@@ -12,6 +12,7 @@ obj-$(CONFIG_CMDLINE_PARTITION) += cmdli - obj-$(CONFIG_MAC_PARTITION) += mac.o - obj-$(CONFIG_LDM_PARTITION) += ldm.o - obj-$(CONFIG_MSDOS_PARTITION) += msdos.o -+obj-$(CONFIG_OF_PARTITION) += of.o - obj-$(CONFIG_OSF_PARTITION) += osf.o - obj-$(CONFIG_SGI_PARTITION) += sgi.o - obj-$(CONFIG_SUN_PARTITION) += sun.o ---- a/block/partitions/check.h -+++ b/block/partitions/check.h -@@ -62,6 +62,7 @@ int karma_partition(struct parsed_partit - int ldm_partition(struct parsed_partitions *state); - int mac_partition(struct parsed_partitions *state); - int msdos_partition(struct parsed_partitions *state); -+int of_partition(struct parsed_partitions *state); - int osf_partition(struct parsed_partitions *state); - int sgi_partition(struct parsed_partitions *state); - int sun_partition(struct parsed_partitions *state); ---- a/block/partitions/core.c -+++ b/block/partitions/core.c -@@ -43,6 +43,9 @@ static int (*const check_part[])(struct - #ifdef CONFIG_CMDLINE_PARTITION - cmdline_partition, - #endif -+#ifdef CONFIG_OF_PARTITION -+ of_partition, /* cmdline have priority to OF */ -+#endif - #ifdef CONFIG_EFI_PARTITION - efi_partition, /* this must come before msdos */ - #endif ---- /dev/null -+++ b/block/partitions/of.c -@@ -0,0 +1,110 @@ -+// SPDX-License-Identifier: GPL-2.0 -+ -+#include -+#include -+#include -+#include -+#include "check.h" -+ -+static int validate_of_partition(struct device_node *np, int slot) -+{ -+ u64 offset, size; -+ int len; -+ -+ const __be32 *reg = of_get_property(np, "reg", &len); -+ int a_cells = of_n_addr_cells(np); -+ int s_cells = of_n_size_cells(np); -+ -+ /* Make sure reg len match the expected addr and size cells */ -+ if (len / sizeof(*reg) != a_cells + s_cells) -+ return -EINVAL; -+ -+ /* Validate offset conversion from bytes to sectors */ -+ offset = of_read_number(reg, a_cells); -+ if (offset % SECTOR_SIZE) -+ return -EINVAL; -+ -+ /* Validate size conversion from bytes to sectors */ -+ size = of_read_number(reg + a_cells, s_cells); -+ if (!size || size % SECTOR_SIZE) -+ return -EINVAL; -+ -+ return 0; -+} -+ -+static void add_of_partition(struct parsed_partitions *state, int slot, -+ struct device_node *np) -+{ -+ struct partition_meta_info *info; -+ char tmp[sizeof(info->volname) + 4]; -+ const char *partname; -+ int len; -+ -+ const __be32 *reg = of_get_property(np, "reg", &len); -+ int a_cells = of_n_addr_cells(np); -+ int s_cells = of_n_size_cells(np); -+ -+ /* Convert bytes to sector size */ -+ u64 offset = of_read_number(reg, a_cells) / SECTOR_SIZE; -+ u64 size = of_read_number(reg + a_cells, s_cells) / SECTOR_SIZE; -+ -+ put_partition(state, slot, offset, size); -+ -+ if (of_property_read_bool(np, "read-only")) -+ state->parts[slot].flags |= ADDPART_FLAG_READONLY; -+ -+ /* -+ * Follow MTD label logic, search for label property, -+ * fallback to node name if not found. -+ */ -+ info = &state->parts[slot].info; -+ partname = of_get_property(np, "label", &len); -+ if (!partname) -+ partname = of_get_property(np, "name", &len); -+ strscpy(info->volname, partname, sizeof(info->volname)); -+ -+ snprintf(tmp, sizeof(tmp), "(%s)", info->volname); -+ strlcat(state->pp_buf, tmp, PAGE_SIZE); -+} -+ -+int of_partition(struct parsed_partitions *state) -+{ -+ struct device *ddev = disk_to_dev(state->disk); -+ struct device_node *np; -+ int slot; -+ -+ struct device_node *partitions_np = of_node_get(ddev->of_node); -+ -+ if (!partitions_np || -+ !of_device_is_compatible(partitions_np, "fixed-partitions")) -+ return 0; -+ -+ slot = 1; -+ /* Validate parition offset and size */ -+ for_each_child_of_node(partitions_np, np) { -+ if (validate_of_partition(np, slot)) { -+ of_node_put(np); -+ of_node_put(partitions_np); -+ -+ return -1; -+ } -+ -+ slot++; -+ } -+ -+ slot = 1; -+ for_each_child_of_node(partitions_np, np) { -+ if (slot >= state->limit) { -+ of_node_put(np); -+ break; -+ } -+ -+ add_of_partition(state, slot, np); -+ -+ slot++; -+ } -+ -+ strlcat(state->pp_buf, "\n", PAGE_SIZE); -+ -+ return 1; -+} diff --git a/target/linux/generic/backport-6.18/600-01-v6.13-net-phylink-move-manual-flow-control-setting.patch b/target/linux/generic/backport-6.18/600-01-v6.13-net-phylink-move-manual-flow-control-setting.patch deleted file mode 100644 index a9b86c2508..0000000000 --- a/target/linux/generic/backport-6.18/600-01-v6.13-net-phylink-move-manual-flow-control-setting.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 8cc5f4cb94c0b1c7c1ba8013c14fd02ffb1a25f3 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Fri, 8 Nov 2024 16:01:44 +0000 -Subject: [PATCH 1/5] net: phylink: move manual flow control setting - -Move the handling of manual flow control configuration to a common -location during resolve. We currently evaluate this for all but -fixed links. - -Signed-off-by: Russell King (Oracle) -Link: https://patch.msgid.link/E1t9RQe-002Feh-T1@rmk-PC.armlinux.org.uk -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/phylink.c | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -1484,7 +1484,6 @@ static void phylink_resolve(struct work_ - switch (pl->cur_link_an_mode) { - case MLO_AN_PHY: - link_state = pl->phy_state; -- phylink_apply_manual_flow(pl, &link_state); - mac_config = link_state.link; - break; - -@@ -1545,11 +1544,13 @@ static void phylink_resolve(struct work_ - link_state.pause = pl->phy_state.pause; - mac_config = true; - } -- phylink_apply_manual_flow(pl, &link_state); - break; - } - } - -+ if (pl->cur_link_an_mode != MLO_AN_FIXED) -+ phylink_apply_manual_flow(pl, &link_state); -+ - if (mac_config) { - if (link_state.interface != pl->link_config.interface) { - /* The interface has changed, force the link down and diff --git a/target/linux/generic/backport-6.18/600-02-v6.13-net-phylink-move-MLO_AN_FIXED-resolve-handling-to-if.patch b/target/linux/generic/backport-6.18/600-02-v6.13-net-phylink-move-MLO_AN_FIXED-resolve-handling-to-if.patch deleted file mode 100644 index 7ff091e85f..0000000000 --- a/target/linux/generic/backport-6.18/600-02-v6.13-net-phylink-move-MLO_AN_FIXED-resolve-handling-to-if.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 92abfcb4ced482afbe65d18980e6734fe1e62a34 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Fri, 8 Nov 2024 16:01:50 +0000 -Subject: [PATCH 2/5] net: phylink: move MLO_AN_FIXED resolve handling to if() - statement - -The switch() statement doesn't sit very well with the preceeding if() -statements, and results in excessive indentation that spoils code -readability. Begin cleaning this up by converting the MLO_AN_FIXED case -to an if() statement. - -Signed-off-by: Russell King (Oracle) -Link: https://patch.msgid.link/E1t9RQk-002Fen-1A@rmk-PC.armlinux.org.uk -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/phylink.c | 8 +++----- - 1 file changed, 3 insertions(+), 5 deletions(-) - ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -1480,6 +1480,9 @@ static void phylink_resolve(struct work_ - } else if (pl->link_failed) { - link_state.link = false; - retrigger = true; -+ } else if (pl->cur_link_an_mode == MLO_AN_FIXED) { -+ phylink_get_fixed_state(pl, &link_state); -+ mac_config = link_state.link; - } else { - switch (pl->cur_link_an_mode) { - case MLO_AN_PHY: -@@ -1487,11 +1490,6 @@ static void phylink_resolve(struct work_ - mac_config = link_state.link; - break; - -- case MLO_AN_FIXED: -- phylink_get_fixed_state(pl, &link_state); -- mac_config = link_state.link; -- break; -- - case MLO_AN_INBAND: - phylink_mac_pcs_get_state(pl, &link_state); - diff --git a/target/linux/generic/backport-6.18/600-03-v6.13-net-phylink-move-MLO_AN_PHY-resolve-handling-to-if-s.patch b/target/linux/generic/backport-6.18/600-03-v6.13-net-phylink-move-MLO_AN_PHY-resolve-handling-to-if-s.patch deleted file mode 100644 index 76e76fbba1..0000000000 --- a/target/linux/generic/backport-6.18/600-03-v6.13-net-phylink-move-MLO_AN_PHY-resolve-handling-to-if-s.patch +++ /dev/null @@ -1,37 +0,0 @@ -From f0f46c2a3d8ea9d1427298c8103a777d9e616c29 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Fri, 8 Nov 2024 16:01:55 +0000 -Subject: [PATCH 3/5] net: phylink: move MLO_AN_PHY resolve handling to if() - statement - -The switch() statement doesn't sit very well with the preceeding if() -statements, and results in excessive indentation that spoils code -readability. Continue cleaning this up by converting the MLO_AN_PHY -case to use an if() statmeent. - -Signed-off-by: Russell King (Oracle) -Link: https://patch.msgid.link/E1t9RQp-002Fet-5W@rmk-PC.armlinux.org.uk -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/phylink.c | 8 +++----- - 1 file changed, 3 insertions(+), 5 deletions(-) - ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -1483,13 +1483,11 @@ static void phylink_resolve(struct work_ - } else if (pl->cur_link_an_mode == MLO_AN_FIXED) { - phylink_get_fixed_state(pl, &link_state); - mac_config = link_state.link; -+ } else if (pl->cur_link_an_mode == MLO_AN_PHY) { -+ link_state = pl->phy_state; -+ mac_config = link_state.link; - } else { - switch (pl->cur_link_an_mode) { -- case MLO_AN_PHY: -- link_state = pl->phy_state; -- mac_config = link_state.link; -- break; -- - case MLO_AN_INBAND: - phylink_mac_pcs_get_state(pl, &link_state); - diff --git a/target/linux/generic/backport-6.18/600-04-v6.13-net-phylink-remove-switch-statement-in-resolve-handl.patch b/target/linux/generic/backport-6.18/600-04-v6.13-net-phylink-remove-switch-statement-in-resolve-handl.patch deleted file mode 100644 index 989fc10b71..0000000000 --- a/target/linux/generic/backport-6.18/600-04-v6.13-net-phylink-remove-switch-statement-in-resolve-handl.patch +++ /dev/null @@ -1,127 +0,0 @@ -From d1a16dbbd84e02d2a6dcfcb8d5c4b8b2c0289f00 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Fri, 8 Nov 2024 16:02:00 +0000 -Subject: [PATCH 4/5] net: phylink: remove switch() statement in resolve - handling - -The switch() statement doesn't sit very well with the preceeding if() -statements, so let's just convert everything to if()s. As a result of -the two preceding commits, there is now only one case in the switch() -statement. Remove the switch statement and reduce the code indentation. -Code reformatting will be in the following commit. - -Signed-off-by: Russell King (Oracle) -Link: https://patch.msgid.link/E1t9RQu-002Fez-AA@rmk-PC.armlinux.org.uk -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/phylink.c | 94 +++++++++++++++++++-------------------- - 1 file changed, 45 insertions(+), 49 deletions(-) - ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -1487,60 +1487,56 @@ static void phylink_resolve(struct work_ - link_state = pl->phy_state; - mac_config = link_state.link; - } else { -- switch (pl->cur_link_an_mode) { -- case MLO_AN_INBAND: -- phylink_mac_pcs_get_state(pl, &link_state); -- -- /* The PCS may have a latching link-fail indicator. -- * If the link was up, bring the link down and -- * re-trigger the resolve. Otherwise, re-read the -- * PCS state to get the current status of the link. -+ phylink_mac_pcs_get_state(pl, &link_state); -+ -+ /* The PCS may have a latching link-fail indicator. -+ * If the link was up, bring the link down and -+ * re-trigger the resolve. Otherwise, re-read the -+ * PCS state to get the current status of the link. -+ */ -+ if (!link_state.link) { -+ if (cur_link_state) -+ retrigger = true; -+ else -+ phylink_mac_pcs_get_state(pl, -+ &link_state); -+ } -+ -+ /* If we have a phy, the "up" state is the union of -+ * both the PHY and the MAC -+ */ -+ if (pl->phydev) -+ link_state.link &= pl->phy_state.link; -+ -+ /* Only update if the PHY link is up */ -+ if (pl->phydev && pl->phy_state.link) { -+ /* If the interface has changed, force a -+ * link down event if the link isn't already -+ * down, and re-resolve. - */ -- if (!link_state.link) { -- if (cur_link_state) -- retrigger = true; -- else -- phylink_mac_pcs_get_state(pl, -- &link_state); -+ if (link_state.interface != -+ pl->phy_state.interface) { -+ retrigger = true; -+ link_state.link = false; - } -+ link_state.interface = pl->phy_state.interface; - -- /* If we have a phy, the "up" state is the union of -- * both the PHY and the MAC -+ /* If we are doing rate matching, then the -+ * link speed/duplex comes from the PHY - */ -- if (pl->phydev) -- link_state.link &= pl->phy_state.link; -- -- /* Only update if the PHY link is up */ -- if (pl->phydev && pl->phy_state.link) { -- /* If the interface has changed, force a -- * link down event if the link isn't already -- * down, and re-resolve. -- */ -- if (link_state.interface != -- pl->phy_state.interface) { -- retrigger = true; -- link_state.link = false; -- } -- link_state.interface = pl->phy_state.interface; -- -- /* If we are doing rate matching, then the -- * link speed/duplex comes from the PHY -- */ -- if (pl->phy_state.rate_matching) { -- link_state.rate_matching = -- pl->phy_state.rate_matching; -- link_state.speed = pl->phy_state.speed; -- link_state.duplex = -- pl->phy_state.duplex; -- } -- -- /* If we have a PHY, we need to update with -- * the PHY flow control bits. -- */ -- link_state.pause = pl->phy_state.pause; -- mac_config = true; -+ if (pl->phy_state.rate_matching) { -+ link_state.rate_matching = -+ pl->phy_state.rate_matching; -+ link_state.speed = pl->phy_state.speed; -+ link_state.duplex = -+ pl->phy_state.duplex; - } -- break; -+ -+ /* If we have a PHY, we need to update with -+ * the PHY flow control bits. -+ */ -+ link_state.pause = pl->phy_state.pause; -+ mac_config = true; - } - } - diff --git a/target/linux/generic/backport-6.18/600-05-v6.13-net-phylink-clean-up-phylink_resolve.patch b/target/linux/generic/backport-6.18/600-05-v6.13-net-phylink-clean-up-phylink_resolve.patch deleted file mode 100644 index 285eea862e..0000000000 --- a/target/linux/generic/backport-6.18/600-05-v6.13-net-phylink-clean-up-phylink_resolve.patch +++ /dev/null @@ -1,85 +0,0 @@ -From bc08ce37d99a3992e975a0f397503cb23404f25a Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Fri, 8 Nov 2024 16:02:05 +0000 -Subject: [PATCH 5/5] net: phylink: clean up phylink_resolve() - -Now that we have reduced the indentation level, clean up the code -formatting. - -Signed-off-by: Russell King (Oracle) -Link: https://patch.msgid.link/E1t9RQz-002Ff5-EA@rmk-PC.armlinux.org.uk -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/phylink.c | 35 ++++++++++++++++------------------- - 1 file changed, 16 insertions(+), 19 deletions(-) - ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -1489,51 +1489,48 @@ static void phylink_resolve(struct work_ - } else { - phylink_mac_pcs_get_state(pl, &link_state); - -- /* The PCS may have a latching link-fail indicator. -- * If the link was up, bring the link down and -- * re-trigger the resolve. Otherwise, re-read the -- * PCS state to get the current status of the link. -+ /* The PCS may have a latching link-fail indicator. If the link -+ * was up, bring the link down and re-trigger the resolve. -+ * Otherwise, re-read the PCS state to get the current status -+ * of the link. - */ - if (!link_state.link) { - if (cur_link_state) - retrigger = true; - else -- phylink_mac_pcs_get_state(pl, -- &link_state); -+ phylink_mac_pcs_get_state(pl, &link_state); - } - -- /* If we have a phy, the "up" state is the union of -- * both the PHY and the MAC -+ /* If we have a phy, the "up" state is the union of both the -+ * PHY and the MAC - */ - if (pl->phydev) - link_state.link &= pl->phy_state.link; - - /* Only update if the PHY link is up */ - if (pl->phydev && pl->phy_state.link) { -- /* If the interface has changed, force a -- * link down event if the link isn't already -- * down, and re-resolve. -+ /* If the interface has changed, force a link down -+ * event if the link isn't already down, and re-resolve. - */ -- if (link_state.interface != -- pl->phy_state.interface) { -+ if (link_state.interface != pl->phy_state.interface) { - retrigger = true; - link_state.link = false; - } -+ - link_state.interface = pl->phy_state.interface; - -- /* If we are doing rate matching, then the -- * link speed/duplex comes from the PHY -+ /* If we are doing rate matching, then the link -+ * speed/duplex comes from the PHY - */ - if (pl->phy_state.rate_matching) { - link_state.rate_matching = - pl->phy_state.rate_matching; - link_state.speed = pl->phy_state.speed; -- link_state.duplex = -- pl->phy_state.duplex; -+ link_state.duplex = pl->phy_state.duplex; - } - -- /* If we have a PHY, we need to update with -- * the PHY flow control bits. -+ /* If we have a PHY, we need to update with the PHY -+ * flow control bits. - */ - link_state.pause = pl->phy_state.pause; - mac_config = true; diff --git a/target/linux/generic/backport-6.18/601-01-v6.14-net-phylink-pass-phylink-and-pcs-into-phylink_pcs_ne.patch b/target/linux/generic/backport-6.18/601-01-v6.14-net-phylink-pass-phylink-and-pcs-into-phylink_pcs_ne.patch deleted file mode 100644 index 6868cd1518..0000000000 --- a/target/linux/generic/backport-6.18/601-01-v6.14-net-phylink-pass-phylink-and-pcs-into-phylink_pcs_ne.patch +++ /dev/null @@ -1,95 +0,0 @@ -From 17ed1911f9c8d4f9af8e13b2c95103ee06dadc0f Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Tue, 3 Dec 2024 15:30:47 +0000 -Subject: [PATCH 01/13] net: phylink: pass phylink and pcs into - phylink_pcs_neg_mode() - -Move the call to phylink_pcs_neg_mode() in phylink_major_config() after -we have selected the appropriate PCS to allow the PCS to be passed in. - -Add struct phylink and struct phylink_pcs pointers to -phylink_pcs_neg_mode() and pass in the appropriate structures. Set -pl->pcs_neg_mode before returning, and remove the return value. - -This will allow the capabilities of the PCS and any PHY to be used when -deciding which pcs_neg_mode should be used. - -Reviewed-by: Andrew Lunn -Signed-off-by: Russell King (Oracle) -Link: https://patch.msgid.link/E1tIUrP-006ITh-6u@rmk-PC.armlinux.org.uk -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/phylink.c | 26 +++++++++++++------------- - 1 file changed, 13 insertions(+), 13 deletions(-) - ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -1102,7 +1102,8 @@ static void phylink_pcs_an_restart(struc - - /** - * phylink_pcs_neg_mode() - helper to determine PCS inband mode -- * @mode: one of %MLO_AN_FIXED, %MLO_AN_PHY, %MLO_AN_INBAND. -+ * @pl: a pointer to a &struct phylink returned from phylink_create() -+ * @pcs: a pointer to &struct phylink_pcs - * @interface: interface mode to be used - * @advertising: adertisement ethtool link mode mask - * -@@ -1119,11 +1120,13 @@ static void phylink_pcs_an_restart(struc - * Note: this is for cases where the PCS itself is involved in negotiation - * (e.g. Clause 37, SGMII and similar) not Clause 73. - */ --static unsigned int phylink_pcs_neg_mode(unsigned int mode, -- phy_interface_t interface, -- const unsigned long *advertising) -+static void phylink_pcs_neg_mode(struct phylink *pl, struct phylink_pcs *pcs, -+ phy_interface_t interface, -+ const unsigned long *advertising) - { -- unsigned int neg_mode; -+ unsigned int neg_mode, mode; -+ -+ mode = pl->cur_link_an_mode; - - switch (interface) { - case PHY_INTERFACE_MODE_SGMII: -@@ -1164,7 +1167,7 @@ static unsigned int phylink_pcs_neg_mode - break; - } - -- return neg_mode; -+ pl->pcs_neg_mode = neg_mode; - } - - static void phylink_major_config(struct phylink *pl, bool restart, -@@ -1178,10 +1181,6 @@ static void phylink_major_config(struct - - phylink_dbg(pl, "major config %s\n", phy_modes(state->interface)); - -- pl->pcs_neg_mode = phylink_pcs_neg_mode(pl->cur_link_an_mode, -- state->interface, -- state->advertising); -- - if (pl->using_mac_select_pcs) { - pcs = pl->mac_ops->mac_select_pcs(pl->config, state->interface); - if (IS_ERR(pcs)) { -@@ -1194,6 +1193,8 @@ static void phylink_major_config(struct - pcs_changed = pcs && pl->pcs != pcs; - } - -+ phylink_pcs_neg_mode(pl, pcs, state->interface, state->advertising); -+ - phylink_pcs_poll_stop(pl); - - if (pl->mac_ops->mac_prepare) { -@@ -1284,9 +1285,8 @@ static int phylink_change_inband_advert( - pl->link_config.pause); - - /* Recompute the PCS neg mode */ -- pl->pcs_neg_mode = phylink_pcs_neg_mode(pl->cur_link_an_mode, -- pl->link_config.interface, -- pl->link_config.advertising); -+ phylink_pcs_neg_mode(pl, pl->pcs, pl->link_config.interface, -+ pl->link_config.advertising); - - neg_mode = pl->cur_link_an_mode; - if (pl->pcs->neg_mode) diff --git a/target/linux/generic/backport-6.18/601-02-v6.14-net-phylink-split-cur_link_an_mode-into-requested-an.patch b/target/linux/generic/backport-6.18/601-02-v6.14-net-phylink-split-cur_link_an_mode-into-requested-an.patch deleted file mode 100644 index 76f4d5a48b..0000000000 --- a/target/linux/generic/backport-6.18/601-02-v6.14-net-phylink-split-cur_link_an_mode-into-requested-an.patch +++ /dev/null @@ -1,290 +0,0 @@ -From 1f92ead7e15003f632b5f138e8138095e0997d3d Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Tue, 3 Dec 2024 15:30:52 +0000 -Subject: [PATCH 02/13] net: phylink: split cur_link_an_mode into requested and - active - -There is an interdependence between the current link_an_mode and -pcs_neg_mode that some drivers rely upon to know whether inband or PHY -mode will be used. - -In order to support detection of PCS and PHY inband capabilities -resulting in automatic selection of inband or PHY mode, we need to -cater for this, and support changing the MAC link_an_mode. However, we -end up with an inter-dependency between the current link_an_mode and -pcs_neg_mode. - -To solve this, split the current link_an_mode into the requested -link_an_mode and active link_an_mode. The requested link_an_mode will -always be passed to phylink_pcs_neg_mode(), and the active link_an_mode -will be used for everything else, and only updated during -phylink_major_config(). This will ensure that phylink_pcs_neg_mode()'s -link_an_mode will not depend on the active link_an_mode that will, -in a future patch, depend on pcs_neg_mode. - -Reviewed-by: Andrew Lunn -Signed-off-by: Russell King (Oracle) -Link: https://patch.msgid.link/E1tIUrU-006ITn-Ai@rmk-PC.armlinux.org.uk -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/phylink.c | 60 ++++++++++++++++++++------------------- - 1 file changed, 31 insertions(+), 29 deletions(-) - ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -56,7 +56,8 @@ struct phylink { - struct phy_device *phydev; - phy_interface_t link_interface; /* PHY_INTERFACE_xxx */ - u8 cfg_link_an_mode; /* MLO_AN_xxx */ -- u8 cur_link_an_mode; -+ u8 req_link_an_mode; /* Requested MLO_AN_xxx mode */ -+ u8 act_link_an_mode; /* Active MLO_AN_xxx mode */ - u8 link_port; /* The current non-phy ethtool port */ - __ETHTOOL_DECLARE_LINK_MODE_MASK(supported); - -@@ -1082,13 +1083,13 @@ static void phylink_mac_config(struct ph - - phylink_dbg(pl, - "%s: mode=%s/%s/%s adv=%*pb pause=%02x\n", -- __func__, phylink_an_mode_str(pl->cur_link_an_mode), -+ __func__, phylink_an_mode_str(pl->act_link_an_mode), - phy_modes(st.interface), - phy_rate_matching_to_str(st.rate_matching), - __ETHTOOL_LINK_MODE_MASK_NBITS, st.advertising, - st.pause); - -- pl->mac_ops->mac_config(pl->config, pl->cur_link_an_mode, &st); -+ pl->mac_ops->mac_config(pl->config, pl->act_link_an_mode, &st); - } - - static void phylink_pcs_an_restart(struct phylink *pl) -@@ -1096,7 +1097,7 @@ static void phylink_pcs_an_restart(struc - if (pl->pcs && linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, - pl->link_config.advertising) && - phy_interface_mode_is_8023z(pl->link_config.interface) && -- phylink_autoneg_inband(pl->cur_link_an_mode)) -+ phylink_autoneg_inband(pl->act_link_an_mode)) - pl->pcs->ops->pcs_an_restart(pl->pcs); - } - -@@ -1126,7 +1127,7 @@ static void phylink_pcs_neg_mode(struct - { - unsigned int neg_mode, mode; - -- mode = pl->cur_link_an_mode; -+ mode = pl->req_link_an_mode; - - switch (interface) { - case PHY_INTERFACE_MODE_SGMII: -@@ -1168,6 +1169,7 @@ static void phylink_pcs_neg_mode(struct - } - - pl->pcs_neg_mode = neg_mode; -+ pl->act_link_an_mode = mode; - } - - static void phylink_major_config(struct phylink *pl, bool restart, -@@ -1198,7 +1200,7 @@ static void phylink_major_config(struct - phylink_pcs_poll_stop(pl); - - if (pl->mac_ops->mac_prepare) { -- err = pl->mac_ops->mac_prepare(pl->config, pl->cur_link_an_mode, -+ err = pl->mac_ops->mac_prepare(pl->config, pl->act_link_an_mode, - state->interface); - if (err < 0) { - phylink_err(pl, "mac_prepare failed: %pe\n", -@@ -1232,7 +1234,7 @@ static void phylink_major_config(struct - if (pl->pcs_state == PCS_STATE_STARTING || pcs_changed) - phylink_pcs_enable(pl->pcs); - -- neg_mode = pl->cur_link_an_mode; -+ neg_mode = pl->act_link_an_mode; - if (pl->pcs && pl->pcs->neg_mode) - neg_mode = pl->pcs_neg_mode; - -@@ -1248,7 +1250,7 @@ static void phylink_major_config(struct - phylink_pcs_an_restart(pl); - - if (pl->mac_ops->mac_finish) { -- err = pl->mac_ops->mac_finish(pl->config, pl->cur_link_an_mode, -+ err = pl->mac_ops->mac_finish(pl->config, pl->act_link_an_mode, - state->interface); - if (err < 0) - phylink_err(pl, "mac_finish failed: %pe\n", -@@ -1279,7 +1281,7 @@ static int phylink_change_inband_advert( - return 0; - - phylink_dbg(pl, "%s: mode=%s/%s adv=%*pb pause=%02x\n", __func__, -- phylink_an_mode_str(pl->cur_link_an_mode), -+ phylink_an_mode_str(pl->req_link_an_mode), - phy_modes(pl->link_config.interface), - __ETHTOOL_LINK_MODE_MASK_NBITS, pl->link_config.advertising, - pl->link_config.pause); -@@ -1288,7 +1290,7 @@ static int phylink_change_inband_advert( - phylink_pcs_neg_mode(pl, pl->pcs, pl->link_config.interface, - pl->link_config.advertising); - -- neg_mode = pl->cur_link_an_mode; -+ neg_mode = pl->act_link_an_mode; - if (pl->pcs->neg_mode) - neg_mode = pl->pcs_neg_mode; - -@@ -1353,7 +1355,7 @@ static void phylink_mac_initial_config(s - { - struct phylink_link_state link_state; - -- switch (pl->cur_link_an_mode) { -+ switch (pl->req_link_an_mode) { - case MLO_AN_PHY: - link_state = pl->phy_state; - break; -@@ -1427,14 +1429,14 @@ static void phylink_link_up(struct phyli - - pl->cur_interface = link_state.interface; - -- neg_mode = pl->cur_link_an_mode; -+ neg_mode = pl->act_link_an_mode; - if (pl->pcs && pl->pcs->neg_mode) - neg_mode = pl->pcs_neg_mode; - - phylink_pcs_link_up(pl->pcs, neg_mode, pl->cur_interface, speed, - duplex); - -- pl->mac_ops->mac_link_up(pl->config, pl->phydev, pl->cur_link_an_mode, -+ pl->mac_ops->mac_link_up(pl->config, pl->phydev, pl->act_link_an_mode, - pl->cur_interface, speed, duplex, - !!(link_state.pause & MLO_PAUSE_TX), rx_pause); - -@@ -1454,7 +1456,7 @@ static void phylink_link_down(struct phy - - if (ndev) - netif_carrier_off(ndev); -- pl->mac_ops->mac_link_down(pl->config, pl->cur_link_an_mode, -+ pl->mac_ops->mac_link_down(pl->config, pl->act_link_an_mode, - pl->cur_interface); - phylink_info(pl, "Link is Down\n"); - } -@@ -1480,10 +1482,10 @@ static void phylink_resolve(struct work_ - } else if (pl->link_failed) { - link_state.link = false; - retrigger = true; -- } else if (pl->cur_link_an_mode == MLO_AN_FIXED) { -+ } else if (pl->act_link_an_mode == MLO_AN_FIXED) { - phylink_get_fixed_state(pl, &link_state); - mac_config = link_state.link; -- } else if (pl->cur_link_an_mode == MLO_AN_PHY) { -+ } else if (pl->act_link_an_mode == MLO_AN_PHY) { - link_state = pl->phy_state; - mac_config = link_state.link; - } else { -@@ -1537,7 +1539,7 @@ static void phylink_resolve(struct work_ - } - } - -- if (pl->cur_link_an_mode != MLO_AN_FIXED) -+ if (pl->act_link_an_mode != MLO_AN_FIXED) - phylink_apply_manual_flow(pl, &link_state); - - if (mac_config) { -@@ -1661,7 +1663,7 @@ int phylink_set_fixed_link(struct phylin - pl->link_config.an_complete = 1; - - pl->cfg_link_an_mode = MLO_AN_FIXED; -- pl->cur_link_an_mode = pl->cfg_link_an_mode; -+ pl->req_link_an_mode = pl->cfg_link_an_mode; - - return 0; - } -@@ -1756,7 +1758,7 @@ struct phylink *phylink_create(struct ph - } - } - -- pl->cur_link_an_mode = pl->cfg_link_an_mode; -+ pl->req_link_an_mode = pl->cfg_link_an_mode; - - ret = phylink_register_sfp(pl, fwnode); - if (ret < 0) { -@@ -2213,7 +2215,7 @@ void phylink_start(struct phylink *pl) - ASSERT_RTNL(); - - phylink_info(pl, "configuring for %s/%s link mode\n", -- phylink_an_mode_str(pl->cur_link_an_mode), -+ phylink_an_mode_str(pl->req_link_an_mode), - phy_modes(pl->link_config.interface)); - - /* Always set the carrier off */ -@@ -2472,7 +2474,7 @@ int phylink_ethtool_ksettings_get(struct - - linkmode_copy(kset->link_modes.supported, pl->supported); - -- switch (pl->cur_link_an_mode) { -+ switch (pl->act_link_an_mode) { - case MLO_AN_FIXED: - /* We are using fixed settings. Report these as the - * current link settings - and note that these also -@@ -2564,7 +2566,7 @@ int phylink_ethtool_ksettings_set(struct - /* If we have a fixed link, refuse to change link parameters. - * If the link parameters match, accept them but do nothing. - */ -- if (pl->cur_link_an_mode == MLO_AN_FIXED) { -+ if (pl->req_link_an_mode == MLO_AN_FIXED) { - if (s->speed != pl->link_config.speed || - s->duplex != pl->link_config.duplex) - return -EINVAL; -@@ -2580,7 +2582,7 @@ int phylink_ethtool_ksettings_set(struct - * is our default case) but do not allow the advertisement to - * be changed. If the advertisement matches, simply return. - */ -- if (pl->cur_link_an_mode == MLO_AN_FIXED) { -+ if (pl->req_link_an_mode == MLO_AN_FIXED) { - if (!linkmode_equal(config.advertising, - pl->link_config.advertising)) - return -EINVAL; -@@ -2620,7 +2622,7 @@ int phylink_ethtool_ksettings_set(struct - linkmode_copy(support, pl->supported); - if (phylink_validate(pl, support, &config)) { - phylink_err(pl, "validation of %s/%s with support %*pb failed\n", -- phylink_an_mode_str(pl->cur_link_an_mode), -+ phylink_an_mode_str(pl->req_link_an_mode), - phy_modes(config.interface), - __ETHTOOL_LINK_MODE_MASK_NBITS, support); - return -EINVAL; -@@ -2720,7 +2722,7 @@ int phylink_ethtool_set_pauseparam(struc - - ASSERT_RTNL(); - -- if (pl->cur_link_an_mode == MLO_AN_FIXED) -+ if (pl->req_link_an_mode == MLO_AN_FIXED) - return -EOPNOTSUPP; - - if (!phylink_test(pl->supported, Pause) && -@@ -2984,7 +2986,7 @@ static int phylink_mii_read(struct phyli - struct phylink_link_state state; - int val = 0xffff; - -- switch (pl->cur_link_an_mode) { -+ switch (pl->act_link_an_mode) { - case MLO_AN_FIXED: - if (phy_id == 0) { - phylink_get_fixed_state(pl, &state); -@@ -3009,7 +3011,7 @@ static int phylink_mii_read(struct phyli - static int phylink_mii_write(struct phylink *pl, unsigned int phy_id, - unsigned int reg, unsigned int val) - { -- switch (pl->cur_link_an_mode) { -+ switch (pl->act_link_an_mode) { - case MLO_AN_FIXED: - break; - -@@ -3199,9 +3201,9 @@ static void phylink_sfp_set_config(struc - changed = true; - } - -- if (pl->cur_link_an_mode != mode || -+ if (pl->req_link_an_mode != mode || - pl->link_config.interface != state->interface) { -- pl->cur_link_an_mode = mode; -+ pl->req_link_an_mode = mode; - pl->link_config.interface = state->interface; - - changed = true; diff --git a/target/linux/generic/backport-6.18/601-03-v6.14-net-phylink-add-debug-for-phylink_major_config.patch b/target/linux/generic/backport-6.18/601-03-v6.14-net-phylink-add-debug-for-phylink_major_config.patch deleted file mode 100644 index ee625c7486..0000000000 --- a/target/linux/generic/backport-6.18/601-03-v6.14-net-phylink-add-debug-for-phylink_major_config.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 4e7d000286fe8e12f2d88032711ffab3ab658b12 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Tue, 3 Dec 2024 15:30:57 +0000 -Subject: [PATCH 03/13] net: phylink: add debug for phylink_major_config() - -Now that we have a more complexity in phylink_major_config(), augment -the debugging so we can see what's going on there. - -Reviewed-by: Andrew Lunn -Signed-off-by: Russell King (Oracle) -Link: https://patch.msgid.link/E1tIUrZ-006ITt-Fa@rmk-PC.armlinux.org.uk -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/phylink.c | 27 ++++++++++++++++++++++++++- - 1 file changed, 26 insertions(+), 1 deletion(-) - ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -176,6 +176,24 @@ static const char *phylink_an_mode_str(u - return mode < ARRAY_SIZE(modestr) ? modestr[mode] : "unknown"; - } - -+static const char *phylink_pcs_mode_str(unsigned int mode) -+{ -+ if (!mode) -+ return "none"; -+ -+ if (mode & PHYLINK_PCS_NEG_OUTBAND) -+ return "outband"; -+ -+ if (mode & PHYLINK_PCS_NEG_INBAND) { -+ if (mode & PHYLINK_PCS_NEG_ENABLED) -+ return "inband,an-enabled"; -+ else -+ return "inband,an-disabled"; -+ } -+ -+ return "unknown"; -+} -+ - static unsigned int phylink_interface_signal_rate(phy_interface_t interface) - { - switch (interface) { -@@ -1181,7 +1199,9 @@ static void phylink_major_config(struct - unsigned int neg_mode; - int err; - -- phylink_dbg(pl, "major config %s\n", phy_modes(state->interface)); -+ phylink_dbg(pl, "major config, requested %s/%s\n", -+ phylink_an_mode_str(pl->req_link_an_mode), -+ phy_modes(state->interface)); - - if (pl->using_mac_select_pcs) { - pcs = pl->mac_ops->mac_select_pcs(pl->config, state->interface); -@@ -1197,6 +1217,11 @@ static void phylink_major_config(struct - - phylink_pcs_neg_mode(pl, pcs, state->interface, state->advertising); - -+ phylink_dbg(pl, "major config, active %s/%s/%s\n", -+ phylink_an_mode_str(pl->act_link_an_mode), -+ phylink_pcs_mode_str(pl->pcs_neg_mode), -+ phy_modes(state->interface)); -+ - phylink_pcs_poll_stop(pl); - - if (pl->mac_ops->mac_prepare) { diff --git a/target/linux/generic/backport-6.18/601-04-v6.14-net-phy-add-phy_inband_caps.patch b/target/linux/generic/backport-6.18/601-04-v6.14-net-phy-add-phy_inband_caps.patch deleted file mode 100644 index 0cd38f086c..0000000000 --- a/target/linux/generic/backport-6.18/601-04-v6.14-net-phy-add-phy_inband_caps.patch +++ /dev/null @@ -1,118 +0,0 @@ -From b4c7698dd95f253c6958d8c6ac219098009bf28a Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Tue, 3 Dec 2024 15:31:02 +0000 -Subject: [PATCH 04/13] net: phy: add phy_inband_caps() - -Add a method to query the PHY's in-band capabilities for a PHY -interface mode. - -Where the interface mode does not have in-band capability, or the PHY -driver has not been updated to return this information, then -phy_inband_caps() should return zero. Otherwise, PHY drivers will -return a value consisting of the following flags: - -LINK_INBAND_DISABLE indicates that the hardware does not support -in-band signalling, or can have in-band signalling configured via -software to be disabled. - -LINK_INBAND_ENABLE indicates that the hardware will use in-band -signalling, or can have in-band signalling configured via software -to be enabled. - -LINK_INBAND_BYPASS indicates that the hardware has the ability to -bypass in-band signalling when enabled after a timeout if the link -partner does not respond to its in-band signalling. - -This reports the PHY capabilities for the particular interface mode, -not the current configuration. - -Reviewed-by: Andrew Lunn -Signed-off-by: Russell King (Oracle) -Link: https://patch.msgid.link/E1tIUre-006ITz-KF@rmk-PC.armlinux.org.uk -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/phy.c | 21 +++++++++++++++++++++ - include/linux/phy.h | 28 ++++++++++++++++++++++++++++ - 2 files changed, 49 insertions(+) - ---- a/drivers/net/phy/phy.c -+++ b/drivers/net/phy/phy.c -@@ -1049,6 +1049,27 @@ static int phy_check_link_status(struct - } - - /** -+ * phy_inband_caps - query which in-band signalling modes are supported -+ * @phydev: a pointer to a &struct phy_device -+ * @interface: the interface mode for the PHY -+ * -+ * Returns zero if it is unknown what in-band signalling is supported by the -+ * PHY (e.g. because the PHY driver doesn't implement the method.) Otherwise, -+ * returns a bit mask of the LINK_INBAND_* values from -+ * &enum link_inband_signalling to describe which inband modes are supported -+ * by the PHY for this interface mode. -+ */ -+unsigned int phy_inband_caps(struct phy_device *phydev, -+ phy_interface_t interface) -+{ -+ if (phydev->drv && phydev->drv->inband_caps) -+ return phydev->drv->inband_caps(phydev, interface); -+ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(phy_inband_caps); -+ -+/** - * _phy_start_aneg - start auto-negotiation for this PHY device - * @phydev: the phy_device struct - * ---- a/include/linux/phy.h -+++ b/include/linux/phy.h -@@ -826,6 +826,24 @@ struct phy_tdr_config { - #define PHY_PAIR_ALL -1 - - /** -+ * enum link_inband_signalling - in-band signalling modes that are supported -+ * -+ * @LINK_INBAND_DISABLE: in-band signalling can be disabled -+ * @LINK_INBAND_ENABLE: in-band signalling can be enabled without bypass -+ * @LINK_INBAND_BYPASS: in-band signalling can be enabled with bypass -+ * -+ * The possible and required bits can only be used if the valid bit is set. -+ * If possible is clear, that means inband signalling can not be used. -+ * Required is only valid when possible is set, and means that inband -+ * signalling must be used. -+ */ -+enum link_inband_signalling { -+ LINK_INBAND_DISABLE = BIT(0), -+ LINK_INBAND_ENABLE = BIT(1), -+ LINK_INBAND_BYPASS = BIT(2), -+}; -+ -+/** - * struct phy_plca_cfg - Configuration of the PLCA (Physical Layer Collision - * Avoidance) Reconciliation Sublayer. - * -@@ -964,6 +982,14 @@ struct phy_driver { - int (*get_features)(struct phy_device *phydev); - - /** -+ * @inband_caps: query whether in-band is supported for the given PHY -+ * interface mode. Returns a bitmask of bits defined by enum -+ * link_inband_signalling. -+ */ -+ unsigned int (*inband_caps)(struct phy_device *phydev, -+ phy_interface_t interface); -+ -+ /** - * @get_rate_matching: Get the supported type of rate matching for a - * particular phy interface. This is used by phy consumers to determine - * whether to advertise lower-speed modes for that interface. It is -@@ -1842,6 +1868,8 @@ int phy_config_aneg(struct phy_device *p - int _phy_start_aneg(struct phy_device *phydev); - int phy_start_aneg(struct phy_device *phydev); - int phy_aneg_done(struct phy_device *phydev); -+unsigned int phy_inband_caps(struct phy_device *phydev, -+ phy_interface_t interface); - int phy_speed_down(struct phy_device *phydev, bool sync); - int phy_speed_up(struct phy_device *phydev); - bool phy_check_valid(int speed, int duplex, unsigned long *features); diff --git a/target/linux/generic/backport-6.18/601-05-v6.14-net-phy-bcm84881-implement-phy_inband_caps-method.patch b/target/linux/generic/backport-6.18/601-05-v6.14-net-phy-bcm84881-implement-phy_inband_caps-method.patch deleted file mode 100644 index 0ba3cd2802..0000000000 --- a/target/linux/generic/backport-6.18/601-05-v6.14-net-phy-bcm84881-implement-phy_inband_caps-method.patch +++ /dev/null @@ -1,41 +0,0 @@ -From c64c7fa0a774d9da72071a8517e359992baac982 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Tue, 3 Dec 2024 15:31:07 +0000 -Subject: [PATCH 05/13] net: phy: bcm84881: implement phy_inband_caps() method - -BCM84881 has no support for inband signalling, so this is a trivial -implementation that returns no support for inband. - -Reviewed-by: Andrew Lunn -Signed-off-by: Russell King (Oracle) -Acked-by: Florian Fainelli -Link: https://patch.msgid.link/E1tIUrj-006IU6-ON@rmk-PC.armlinux.org.uk -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/bcm84881.c | 10 ++++++++++ - 1 file changed, 10 insertions(+) - ---- a/drivers/net/phy/bcm84881.c -+++ b/drivers/net/phy/bcm84881.c -@@ -235,11 +235,21 @@ static int bcm84881_read_status(struct p - return genphy_c45_read_mdix(phydev); - } - -+/* The Broadcom BCM84881 in the Methode DM7052 is unable to provide a SGMII -+ * or 802.3z control word, so inband will not work. -+ */ -+static unsigned int bcm84881_inband_caps(struct phy_device *phydev, -+ phy_interface_t interface) -+{ -+ return LINK_INBAND_DISABLE; -+} -+ - static struct phy_driver bcm84881_drivers[] = { - { - .phy_id = 0xae025150, - .phy_id_mask = 0xfffffff0, - .name = "Broadcom BCM84881", -+ .inband_caps = bcm84881_inband_caps, - .config_init = bcm84881_config_init, - .probe = bcm84881_probe, - .get_features = bcm84881_get_features, diff --git a/target/linux/generic/backport-6.18/601-06-v6.14-net-phy-marvell-implement-phy_inband_caps-method.patch b/target/linux/generic/backport-6.18/601-06-v6.14-net-phy-marvell-implement-phy_inband_caps-method.patch deleted file mode 100644 index e2dfeba1d5..0000000000 --- a/target/linux/generic/backport-6.18/601-06-v6.14-net-phy-marvell-implement-phy_inband_caps-method.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 1c86828dff88e28b8ade6bddeee0163a023faf91 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Tue, 3 Dec 2024 15:31:12 +0000 -Subject: [PATCH 06/13] net: phy: marvell: implement phy_inband_caps() method - -Provide an implementation for phy_inband_caps() for Marvell PHYs used -on SFP modules, so that phylink knows the PHYs capabilities. - -Reviewed-by: Andrew Lunn -Signed-off-by: Russell King (Oracle) -Link: https://patch.msgid.link/E1tIUro-006IUC-Rq@rmk-PC.armlinux.org.uk -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/marvell.c | 17 +++++++++++++++++ - 1 file changed, 17 insertions(+) - ---- a/drivers/net/phy/marvell.c -+++ b/drivers/net/phy/marvell.c -@@ -716,6 +716,20 @@ static int marvell_config_aneg_fiber(str - return genphy_check_and_restart_aneg(phydev, changed); - } - -+static unsigned int m88e1111_inband_caps(struct phy_device *phydev, -+ phy_interface_t interface) -+{ -+ /* In 1000base-X and SGMII modes, the inband mode can be changed -+ * through the Fibre page BMCR ANENABLE bit. -+ */ -+ if (interface == PHY_INTERFACE_MODE_1000BASEX || -+ interface == PHY_INTERFACE_MODE_SGMII) -+ return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE | -+ LINK_INBAND_BYPASS; -+ -+ return 0; -+} -+ - static int m88e1111_config_aneg(struct phy_device *phydev) - { - int extsr = phy_read(phydev, MII_M1111_PHY_EXT_SR); -@@ -3704,6 +3718,7 @@ static struct phy_driver marvell_drivers - .name = "Marvell 88E1112", - /* PHY_GBIT_FEATURES */ - .probe = marvell_probe, -+ .inband_caps = m88e1111_inband_caps, - .config_init = m88e1112_config_init, - .config_aneg = marvell_config_aneg, - .config_intr = marvell_config_intr, -@@ -3725,6 +3740,7 @@ static struct phy_driver marvell_drivers - /* PHY_GBIT_FEATURES */ - .flags = PHY_POLL_CABLE_TEST, - .probe = marvell_probe, -+ .inband_caps = m88e1111_inband_caps, - .config_init = m88e1111gbe_config_init, - .config_aneg = m88e1111_config_aneg, - .read_status = marvell_read_status, -@@ -3748,6 +3764,7 @@ static struct phy_driver marvell_drivers - .name = "Marvell 88E1111 (Finisar)", - /* PHY_GBIT_FEATURES */ - .probe = marvell_probe, -+ .inband_caps = m88e1111_inband_caps, - .config_init = m88e1111gbe_config_init, - .config_aneg = m88e1111_config_aneg, - .read_status = marvell_read_status, diff --git a/target/linux/generic/backport-6.18/601-07-v6.14-net-phy-add-phy_config_inband.patch b/target/linux/generic/backport-6.18/601-07-v6.14-net-phy-add-phy_config_inband.patch deleted file mode 100644 index d667bcbec0..0000000000 --- a/target/linux/generic/backport-6.18/601-07-v6.14-net-phy-add-phy_config_inband.patch +++ /dev/null @@ -1,79 +0,0 @@ -From 5d58a890c02770ba8d790b1f3c6e8c0e20514dc2 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Tue, 3 Dec 2024 15:31:18 +0000 -Subject: [PATCH 07/13] net: phy: add phy_config_inband() - -Add a method to configure the PHY's in-band mode. - -Reviewed-by: Andrew Lunn -Signed-off-by: Russell King (Oracle) -Link: https://patch.msgid.link/E1tIUru-006IUI-08@rmk-PC.armlinux.org.uk -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/phy.c | 32 ++++++++++++++++++++++++++++++++ - include/linux/phy.h | 6 ++++++ - 2 files changed, 38 insertions(+) - ---- a/drivers/net/phy/phy.c -+++ b/drivers/net/phy/phy.c -@@ -1070,6 +1070,38 @@ unsigned int phy_inband_caps(struct phy_ - EXPORT_SYMBOL_GPL(phy_inband_caps); - - /** -+ * phy_config_inband - configure the desired PHY in-band mode -+ * @phydev: the phy_device struct -+ * @modes: in-band modes to configure -+ * -+ * Description: disables, enables or enables-with-bypass in-band signalling -+ * between the PHY and host system. -+ * -+ * Returns: zero on success, or negative errno value. -+ */ -+int phy_config_inband(struct phy_device *phydev, unsigned int modes) -+{ -+ int err; -+ -+ if (!!(modes & LINK_INBAND_DISABLE) + -+ !!(modes & LINK_INBAND_ENABLE) + -+ !!(modes & LINK_INBAND_BYPASS) != 1) -+ return -EINVAL; -+ -+ mutex_lock(&phydev->lock); -+ if (!phydev->drv) -+ err = -EIO; -+ else if (!phydev->drv->config_inband) -+ err = -EOPNOTSUPP; -+ else -+ err = phydev->drv->config_inband(phydev, modes); -+ mutex_unlock(&phydev->lock); -+ -+ return err; -+} -+EXPORT_SYMBOL(phy_config_inband); -+ -+/** - * _phy_start_aneg - start auto-negotiation for this PHY device - * @phydev: the phy_device struct - * ---- a/include/linux/phy.h -+++ b/include/linux/phy.h -@@ -990,6 +990,11 @@ struct phy_driver { - phy_interface_t interface); - - /** -+ * @config_inband: configure in-band mode for the PHY -+ */ -+ int (*config_inband)(struct phy_device *phydev, unsigned int modes); -+ -+ /** - * @get_rate_matching: Get the supported type of rate matching for a - * particular phy interface. This is used by phy consumers to determine - * whether to advertise lower-speed modes for that interface. It is -@@ -1870,6 +1875,7 @@ int phy_start_aneg(struct phy_device *ph - int phy_aneg_done(struct phy_device *phydev); - unsigned int phy_inband_caps(struct phy_device *phydev, - phy_interface_t interface); -+int phy_config_inband(struct phy_device *phydev, unsigned int modes); - int phy_speed_down(struct phy_device *phydev, bool sync); - int phy_speed_up(struct phy_device *phydev); - bool phy_check_valid(int speed, int duplex, unsigned long *features); diff --git a/target/linux/generic/backport-6.18/601-08-v6.14-net-phy-marvell-implement-config_inband-method.patch b/target/linux/generic/backport-6.18/601-08-v6.14-net-phy-marvell-implement-config_inband-method.patch deleted file mode 100644 index 4531c507e2..0000000000 --- a/target/linux/generic/backport-6.18/601-08-v6.14-net-phy-marvell-implement-config_inband-method.patch +++ /dev/null @@ -1,77 +0,0 @@ -From a219912e0fec73c346e64ef47013cb2e152f88fc Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Tue, 3 Dec 2024 15:31:23 +0000 -Subject: [PATCH 08/13] net: phy: marvell: implement config_inband() method - -Implement the config_inband() method for Marvell 88E1112, 88E1111, -and Finisar's 88E1111 variant. - -Reviewed-by: Andrew Lunn -Signed-off-by: Russell King (Oracle) -Link: https://patch.msgid.link/E1tIUrz-006IUO-3r@rmk-PC.armlinux.org.uk -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/marvell.c | 31 +++++++++++++++++++++++++++++++ - 1 file changed, 31 insertions(+) - ---- a/drivers/net/phy/marvell.c -+++ b/drivers/net/phy/marvell.c -@@ -730,6 +730,34 @@ static unsigned int m88e1111_inband_caps - return 0; - } - -+static int m88e1111_config_inband(struct phy_device *phydev, unsigned int modes) -+{ -+ u16 extsr, bmcr; -+ int err; -+ -+ if (phydev->interface != PHY_INTERFACE_MODE_1000BASEX && -+ phydev->interface != PHY_INTERFACE_MODE_SGMII) -+ return -EINVAL; -+ -+ if (modes == LINK_INBAND_BYPASS) -+ extsr = MII_M1111_HWCFG_SERIAL_AN_BYPASS; -+ else -+ extsr = 0; -+ -+ if (modes == LINK_INBAND_DISABLE) -+ bmcr = 0; -+ else -+ bmcr = BMCR_ANENABLE; -+ -+ err = phy_modify(phydev, MII_M1111_PHY_EXT_SR, -+ MII_M1111_HWCFG_SERIAL_AN_BYPASS, extsr); -+ if (err < 0) -+ return extsr; -+ -+ return phy_modify_paged(phydev, MII_MARVELL_FIBER_PAGE, MII_BMCR, -+ BMCR_ANENABLE, bmcr); -+} -+ - static int m88e1111_config_aneg(struct phy_device *phydev) - { - int extsr = phy_read(phydev, MII_M1111_PHY_EXT_SR); -@@ -3719,6 +3747,7 @@ static struct phy_driver marvell_drivers - /* PHY_GBIT_FEATURES */ - .probe = marvell_probe, - .inband_caps = m88e1111_inband_caps, -+ .config_inband = m88e1111_config_inband, - .config_init = m88e1112_config_init, - .config_aneg = marvell_config_aneg, - .config_intr = marvell_config_intr, -@@ -3741,6 +3770,7 @@ static struct phy_driver marvell_drivers - .flags = PHY_POLL_CABLE_TEST, - .probe = marvell_probe, - .inband_caps = m88e1111_inband_caps, -+ .config_inband = m88e1111_config_inband, - .config_init = m88e1111gbe_config_init, - .config_aneg = m88e1111_config_aneg, - .read_status = marvell_read_status, -@@ -3765,6 +3795,7 @@ static struct phy_driver marvell_drivers - /* PHY_GBIT_FEATURES */ - .probe = marvell_probe, - .inband_caps = m88e1111_inband_caps, -+ .config_inband = m88e1111_config_inband, - .config_init = m88e1111gbe_config_init, - .config_aneg = m88e1111_config_aneg, - .read_status = marvell_read_status, diff --git a/target/linux/generic/backport-6.18/601-09-v6.14-net-phylink-add-pcs_inband_caps-method.patch b/target/linux/generic/backport-6.18/601-09-v6.14-net-phylink-add-pcs_inband_caps-method.patch deleted file mode 100644 index 422802457e..0000000000 --- a/target/linux/generic/backport-6.18/601-09-v6.14-net-phylink-add-pcs_inband_caps-method.patch +++ /dev/null @@ -1,159 +0,0 @@ -From df874f9e52c340cc6f0a0014a97b778f67d46849 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Tue, 3 Dec 2024 15:31:28 +0000 -Subject: [PATCH 09/13] net: phylink: add pcs_inband_caps() method - -Add a pcs_inband_caps() method to query the PCS for its inband link -capabilities, and use this to determine whether link modes used with -optical SFPs can be supported. - -When a PCS does not provide a method, we allow inband negotiation to -be either on or off, making this a no-op until the pcs_inband_caps() -method is implemented by a PCS driver. - -Reviewed-by: Andrew Lunn -Signed-off-by: Russell King (Oracle) -Link: https://patch.msgid.link/E1tIUs4-006IUU-7K@rmk-PC.armlinux.org.uk -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/phylink.c | 60 +++++++++++++++++++++++++++++++++++++++ - include/linux/phylink.h | 17 +++++++++++ - 2 files changed, 77 insertions(+) - ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -1007,6 +1007,15 @@ static void phylink_resolve_an_pause(str - } - } - -+static unsigned int phylink_pcs_inband_caps(struct phylink_pcs *pcs, -+ phy_interface_t interface) -+{ -+ if (pcs && pcs->ops->pcs_inband_caps) -+ return pcs->ops->pcs_inband_caps(pcs, interface); -+ -+ return 0; -+} -+ - static void phylink_pcs_pre_config(struct phylink_pcs *pcs, - phy_interface_t interface) - { -@@ -1060,6 +1069,24 @@ static void phylink_pcs_link_up(struct p - pcs->ops->pcs_link_up(pcs, neg_mode, interface, speed, duplex); - } - -+/* Query inband for a specific interface mode, asking the MAC for the -+ * PCS which will be used to handle the interface mode. -+ */ -+static unsigned int phylink_inband_caps(struct phylink *pl, -+ phy_interface_t interface) -+{ -+ struct phylink_pcs *pcs; -+ -+ if (!pl->mac_ops->mac_select_pcs) -+ return 0; -+ -+ pcs = pl->mac_ops->mac_select_pcs(pl->config, interface); -+ if (!pcs) -+ return 0; -+ -+ return phylink_pcs_inband_caps(pcs, interface); -+} -+ - static void phylink_pcs_poll_stop(struct phylink *pl) - { - if (pl->cfg_link_an_mode == MLO_AN_INBAND) -@@ -2530,6 +2557,26 @@ int phylink_ethtool_ksettings_get(struct - } - EXPORT_SYMBOL_GPL(phylink_ethtool_ksettings_get); - -+static bool phylink_validate_pcs_inband_autoneg(struct phylink *pl, -+ phy_interface_t interface, -+ unsigned long *adv) -+{ -+ unsigned int inband = phylink_inband_caps(pl, interface); -+ unsigned int mask; -+ -+ /* If the PCS doesn't implement inband support, be permissive. */ -+ if (!inband) -+ return true; -+ -+ if (linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, adv)) -+ mask = LINK_INBAND_ENABLE; -+ else -+ mask = LINK_INBAND_DISABLE; -+ -+ /* Check whether the PCS implements the required mode */ -+ return !!(inband & mask); -+} -+ - /** - * phylink_ethtool_ksettings_set() - set the link settings - * @pl: a pointer to a &struct phylink returned from phylink_create() -@@ -2665,6 +2712,13 @@ int phylink_ethtool_ksettings_set(struct - phylink_is_empty_linkmode(config.advertising)) - return -EINVAL; - -+ /* Validate the autonegotiation state. We don't have a PHY in this -+ * situation, so the PCS is the media-facing entity. -+ */ -+ if (!phylink_validate_pcs_inband_autoneg(pl, config.interface, -+ config.advertising)) -+ return -EINVAL; -+ - mutex_lock(&pl->state_mutex); - pl->link_config.speed = config.speed; - pl->link_config.duplex = config.duplex; -@@ -3349,6 +3403,12 @@ static int phylink_sfp_config_optical(st - phylink_dbg(pl, "optical SFP: chosen %s interface\n", - phy_modes(interface)); - -+ if (!phylink_validate_pcs_inband_autoneg(pl, interface, -+ config.advertising)) { -+ phylink_err(pl, "autoneg setting not compatible with PCS"); -+ return -EINVAL; -+ } -+ - config.interface = interface; - - /* Ignore errors if we're expecting a PHY to attach later */ ---- a/include/linux/phylink.h -+++ b/include/linux/phylink.h -@@ -419,6 +419,7 @@ struct phylink_pcs { - /** - * struct phylink_pcs_ops - MAC PCS operations structure. - * @pcs_validate: validate the link configuration. -+ * @pcs_inband_caps: query inband support for interface mode. - * @pcs_enable: enable the PCS. - * @pcs_disable: disable the PCS. - * @pcs_pre_config: pre-mac_config method (for errata) -@@ -434,6 +435,8 @@ struct phylink_pcs { - struct phylink_pcs_ops { - int (*pcs_validate)(struct phylink_pcs *pcs, unsigned long *supported, - const struct phylink_link_state *state); -+ unsigned int (*pcs_inband_caps)(struct phylink_pcs *pcs, -+ phy_interface_t interface); - int (*pcs_enable)(struct phylink_pcs *pcs); - void (*pcs_disable)(struct phylink_pcs *pcs); - void (*pcs_pre_config)(struct phylink_pcs *pcs, -@@ -471,6 +474,20 @@ int pcs_validate(struct phylink_pcs *pcs - const struct phylink_link_state *state); - - /** -+ * pcs_inband_caps - query PCS in-band capabilities for interface mode. -+ * @pcs: a pointer to a &struct phylink_pcs. -+ * @interface: interface mode to be queried -+ * -+ * Returns zero if it is unknown what in-band signalling is supported by the -+ * PHY (e.g. because the PHY driver doesn't implement the method.) Otherwise, -+ * returns a bit mask of the LINK_INBAND_* values from -+ * &enum link_inband_signalling to describe which inband modes are supported -+ * for this interface mode. -+ */ -+unsigned int pcs_inband_caps(struct phylink_pcs *pcs, -+ phy_interface_t interface); -+ -+/** - * pcs_enable() - enable the PCS. - * @pcs: a pointer to a &struct phylink_pcs. - */ diff --git a/target/linux/generic/backport-6.18/601-10-v6.14-net-mvneta-implement-pcs_inband_caps-method.patch b/target/linux/generic/backport-6.18/601-10-v6.14-net-mvneta-implement-pcs_inband_caps-method.patch deleted file mode 100644 index 0937ad1388..0000000000 --- a/target/linux/generic/backport-6.18/601-10-v6.14-net-mvneta-implement-pcs_inband_caps-method.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 513e8fb8fa32035b3325e2e14fb9598f8cb545e9 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Tue, 3 Dec 2024 15:31:33 +0000 -Subject: [PATCH 10/13] net: mvneta: implement pcs_inband_caps() method - -Report the PCS in-band capabilities to phylink for Marvell NETA -interfaces. - -Reviewed-by: Andrew Lunn -Signed-off-by: Russell King (Oracle) -Link: https://patch.msgid.link/E1tIUs9-006IUb-Au@rmk-PC.armlinux.org.uk -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/marvell/mvneta.c | 27 +++++++++++++++++---------- - 1 file changed, 17 insertions(+), 10 deletions(-) - ---- a/drivers/net/ethernet/marvell/mvneta.c -+++ b/drivers/net/ethernet/marvell/mvneta.c -@@ -3960,20 +3960,27 @@ static struct mvneta_port *mvneta_pcs_to - return container_of(pcs, struct mvneta_port, phylink_pcs); - } - --static int mvneta_pcs_validate(struct phylink_pcs *pcs, -- unsigned long *supported, -- const struct phylink_link_state *state) -+static unsigned int mvneta_pcs_inband_caps(struct phylink_pcs *pcs, -+ phy_interface_t interface) - { -- /* We only support QSGMII, SGMII, 802.3z and RGMII modes. -- * When in 802.3z mode, we must have AN enabled: -+ /* When operating in an 802.3z mode, we must have AN enabled: - * "Bit 2 Field InBandAnEn In-band Auto-Negotiation enable. ... - * When = 1 (1000BASE-X) this field must be set to 1." -+ * Therefore, inband is "required". - */ -- if (phy_interface_mode_is_8023z(state->interface) && -- !phylink_test(state->advertising, Autoneg)) -- return -EINVAL; -+ if (phy_interface_mode_is_8023z(interface)) -+ return LINK_INBAND_ENABLE; - -- return 0; -+ /* QSGMII, SGMII and RGMII can be configured to use inband -+ * signalling of the AN result. Indicate these as "possible". -+ */ -+ if (interface == PHY_INTERFACE_MODE_SGMII || -+ interface == PHY_INTERFACE_MODE_QSGMII || -+ phy_interface_mode_is_rgmii(interface)) -+ return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE; -+ -+ /* For any other modes, indicate that inband is not supported. */ -+ return LINK_INBAND_DISABLE; - } - - static void mvneta_pcs_get_state(struct phylink_pcs *pcs, -@@ -4071,7 +4078,7 @@ static void mvneta_pcs_an_restart(struct - } - - static const struct phylink_pcs_ops mvneta_phylink_pcs_ops = { -- .pcs_validate = mvneta_pcs_validate, -+ .pcs_inband_caps = mvneta_pcs_inband_caps, - .pcs_get_state = mvneta_pcs_get_state, - .pcs_config = mvneta_pcs_config, - .pcs_an_restart = mvneta_pcs_an_restart, diff --git a/target/linux/generic/backport-6.18/601-11-v6.14-net-mvpp2-implement-pcs_inband_caps-method.patch b/target/linux/generic/backport-6.18/601-11-v6.14-net-mvpp2-implement-pcs_inband_caps-method.patch deleted file mode 100644 index 846d9df36d..0000000000 --- a/target/linux/generic/backport-6.18/601-11-v6.14-net-mvpp2-implement-pcs_inband_caps-method.patch +++ /dev/null @@ -1,62 +0,0 @@ -From d4169f0c7665afb8d8adb5e1b1df3db88517d0ad Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Tue, 3 Dec 2024 15:31:38 +0000 -Subject: [PATCH 11/13] net: mvpp2: implement pcs_inband_caps() method - -Report the PCS in-band capabilities to phylink for Marvell PP2 -interfaces. - -Reviewed-by: Andrew Lunn -Signed-off-by: Russell King (Oracle) -Link: https://patch.msgid.link/E1tIUsE-006IUh-E7@rmk-PC.armlinux.org.uk -Signed-off-by: Jakub Kicinski ---- - .../net/ethernet/marvell/mvpp2/mvpp2_main.c | 25 ++++++++++++------- - 1 file changed, 16 insertions(+), 9 deletions(-) - ---- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c -+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c -@@ -6237,19 +6237,26 @@ static const struct phylink_pcs_ops mvpp - .pcs_config = mvpp2_xlg_pcs_config, - }; - --static int mvpp2_gmac_pcs_validate(struct phylink_pcs *pcs, -- unsigned long *supported, -- const struct phylink_link_state *state) -+static unsigned int mvpp2_gmac_pcs_inband_caps(struct phylink_pcs *pcs, -+ phy_interface_t interface) - { -- /* When in 802.3z mode, we must have AN enabled: -+ /* When operating in an 802.3z mode, we must have AN enabled: - * Bit 2 Field InBandAnEn In-band Auto-Negotiation enable. ... - * When = 1 (1000BASE-X) this field must be set to 1. -+ * Therefore, inband is "required". - */ -- if (phy_interface_mode_is_8023z(state->interface) && -- !phylink_test(state->advertising, Autoneg)) -- return -EINVAL; -+ if (phy_interface_mode_is_8023z(interface)) -+ return LINK_INBAND_ENABLE; - -- return 0; -+ /* SGMII and RGMII can be configured to use inband signalling of the -+ * AN result. Indicate these as "possible". -+ */ -+ if (interface == PHY_INTERFACE_MODE_SGMII || -+ phy_interface_mode_is_rgmii(interface)) -+ return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE; -+ -+ /* For any other modes, indicate that inband is not supported. */ -+ return LINK_INBAND_DISABLE; - } - - static void mvpp2_gmac_pcs_get_state(struct phylink_pcs *pcs, -@@ -6356,7 +6363,7 @@ static void mvpp2_gmac_pcs_an_restart(st - } - - static const struct phylink_pcs_ops mvpp2_phylink_gmac_pcs_ops = { -- .pcs_validate = mvpp2_gmac_pcs_validate, -+ .pcs_inband_caps = mvpp2_gmac_pcs_inband_caps, - .pcs_get_state = mvpp2_gmac_pcs_get_state, - .pcs_config = mvpp2_gmac_pcs_config, - .pcs_an_restart = mvpp2_gmac_pcs_an_restart, diff --git a/target/linux/generic/backport-6.18/601-12-v6.14-net-phylink-add-negotiation-of-in-band-capabilities.patch b/target/linux/generic/backport-6.18/601-12-v6.14-net-phylink-add-negotiation-of-in-band-capabilities.patch deleted file mode 100644 index f629133013..0000000000 --- a/target/linux/generic/backport-6.18/601-12-v6.14-net-phylink-add-negotiation-of-in-band-capabilities.patch +++ /dev/null @@ -1,228 +0,0 @@ -From 5fd0f1a02e750e2db4038dee60edea669ce5aab1 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Tue, 3 Dec 2024 15:31:43 +0000 -Subject: [PATCH 12/13] net: phylink: add negotiation of in-band capabilities - -Support for in-band signalling with Serdes links is uncertain. Some -PHYs do not support in-band for e.g. SGMII. Some PCS do not support -in-band for 2500Base-X. Some PCS require in-band for Base-X protocols. - -Simply using what is in DT is insufficient when we have hot-pluggable -PHYs e.g. in the form of SFP modules, which may not provide the -in-band signalling. - -In order to address this, we have introduced phy_inband_caps() and -pcs_inband_caps() functions to allow phylink to retrieve the -capabilities from each end of the PCS/PHY link. This commit adds code -to resolve whether in-band will be used in the various scenarios that -we have: In-band not being used, PHY present using SGMII or Base-X, -PHY not present. We also deal with no capabilties provided. - -Signed-off-by: Russell King (Oracle) -Link: https://patch.msgid.link/E1tIUsJ-006IUn-H3@rmk-PC.armlinux.org.uk -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/phylink.c | 154 +++++++++++++++++++++++++++++++++++--- - 1 file changed, 144 insertions(+), 10 deletions(-) - ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -75,6 +75,7 @@ struct phylink { - - struct mutex state_mutex; - struct phylink_link_state phy_state; -+ unsigned int phy_ib_mode; - struct work_struct resolve; - unsigned int pcs_neg_mode; - unsigned int pcs_state; -@@ -1170,10 +1171,18 @@ static void phylink_pcs_neg_mode(struct - phy_interface_t interface, - const unsigned long *advertising) - { -+ unsigned int pcs_ib_caps = 0; -+ unsigned int phy_ib_caps = 0; - unsigned int neg_mode, mode; -+ enum { -+ INBAND_CISCO_SGMII, -+ INBAND_BASEX, -+ } type; - - mode = pl->req_link_an_mode; - -+ pl->phy_ib_mode = 0; -+ - switch (interface) { - case PHY_INTERFACE_MODE_SGMII: - case PHY_INTERFACE_MODE_QSGMII: -@@ -1185,10 +1194,7 @@ static void phylink_pcs_neg_mode(struct - * inband communication. Note: there exist PHYs that run - * with SGMII but do not send the inband data. - */ -- if (!phylink_autoneg_inband(mode)) -- neg_mode = PHYLINK_PCS_NEG_OUTBAND; -- else -- neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED; -+ type = INBAND_CISCO_SGMII; - break; - - case PHY_INTERFACE_MODE_1000BASEX: -@@ -1199,18 +1205,139 @@ static void phylink_pcs_neg_mode(struct - * as well, but drivers may not support this, so may - * need to override this. - */ -- if (!phylink_autoneg_inband(mode)) -+ type = INBAND_BASEX; -+ break; -+ -+ default: -+ pl->pcs_neg_mode = PHYLINK_PCS_NEG_NONE; -+ pl->act_link_an_mode = mode; -+ return; -+ } -+ -+ if (pcs) -+ pcs_ib_caps = phylink_pcs_inband_caps(pcs, interface); -+ -+ if (pl->phydev) -+ phy_ib_caps = phy_inband_caps(pl->phydev, interface); -+ -+ phylink_dbg(pl, "interface %s inband modes: pcs=%02x phy=%02x\n", -+ phy_modes(interface), pcs_ib_caps, phy_ib_caps); -+ -+ if (!phylink_autoneg_inband(mode)) { -+ bool pcs_ib_only = false; -+ bool phy_ib_only = false; -+ -+ if (pcs_ib_caps && pcs_ib_caps != LINK_INBAND_DISABLE) { -+ /* PCS supports reporting in-band capabilities, and -+ * supports more than disable mode. -+ */ -+ if (pcs_ib_caps & LINK_INBAND_DISABLE) -+ neg_mode = PHYLINK_PCS_NEG_OUTBAND; -+ else if (pcs_ib_caps & LINK_INBAND_ENABLE) -+ pcs_ib_only = true; -+ } -+ -+ if (phy_ib_caps && phy_ib_caps != LINK_INBAND_DISABLE) { -+ /* PHY supports in-band capabilities, and supports -+ * more than disable mode. -+ */ -+ if (phy_ib_caps & LINK_INBAND_DISABLE) -+ pl->phy_ib_mode = LINK_INBAND_DISABLE; -+ else if (phy_ib_caps & LINK_INBAND_BYPASS) -+ pl->phy_ib_mode = LINK_INBAND_BYPASS; -+ else if (phy_ib_caps & LINK_INBAND_ENABLE) -+ phy_ib_only = true; -+ } -+ -+ /* If either the PCS or PHY requires inband to be enabled, -+ * this is an invalid configuration. Provide a diagnostic -+ * message for this case, but don't try to force the issue. -+ */ -+ if (pcs_ib_only || phy_ib_only) -+ phylink_warn(pl, -+ "firmware wants %s mode, but %s%s%s requires inband\n", -+ phylink_an_mode_str(mode), -+ pcs_ib_only ? "PCS" : "", -+ pcs_ib_only && phy_ib_only ? " and " : "", -+ phy_ib_only ? "PHY" : ""); -+ -+ neg_mode = PHYLINK_PCS_NEG_OUTBAND; -+ } else if (type == INBAND_CISCO_SGMII || pl->phydev) { -+ /* For SGMII modes which are designed to be used with PHYs, or -+ * Base-X with a PHY, we try to use in-band mode where-ever -+ * possible. However, there are some PHYs e.g. BCM84881 which -+ * do not support in-band. -+ */ -+ const unsigned int inband_ok = LINK_INBAND_ENABLE | -+ LINK_INBAND_BYPASS; -+ const unsigned int outband_ok = LINK_INBAND_DISABLE | -+ LINK_INBAND_BYPASS; -+ /* PCS PHY -+ * D E D E -+ * 0 0 0 0 no information inband enabled -+ * 1 0 0 0 pcs doesn't support outband -+ * 0 1 0 0 pcs required inband enabled -+ * 1 1 0 0 pcs optional inband enabled -+ * 0 0 1 0 phy doesn't support outband -+ * 1 0 1 0 pcs+phy doesn't support outband -+ * 0 1 1 0 pcs required, phy doesn't support, invalid -+ * 1 1 1 0 pcs optional, phy doesn't support, outband -+ * 0 0 0 1 phy required inband enabled -+ * 1 0 0 1 pcs doesn't support, phy required, invalid -+ * 0 1 0 1 pcs+phy required inband enabled -+ * 1 1 0 1 pcs optional, phy required inband enabled -+ * 0 0 1 1 phy optional inband enabled -+ * 1 0 1 1 pcs doesn't support, phy optional, outband -+ * 0 1 1 1 pcs required, phy optional inband enabled -+ * 1 1 1 1 pcs+phy optional inband enabled -+ */ -+ if ((!pcs_ib_caps || pcs_ib_caps & inband_ok) && -+ (!phy_ib_caps || phy_ib_caps & inband_ok)) { -+ /* In-band supported or unknown at both ends. Enable -+ * in-band mode with or without bypass at the PHY. -+ */ -+ if (phy_ib_caps & LINK_INBAND_ENABLE) -+ pl->phy_ib_mode = LINK_INBAND_ENABLE; -+ else if (phy_ib_caps & LINK_INBAND_BYPASS) -+ pl->phy_ib_mode = LINK_INBAND_BYPASS; -+ -+ neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED; -+ } else if ((!pcs_ib_caps || pcs_ib_caps & outband_ok) && -+ (!phy_ib_caps || phy_ib_caps & outband_ok)) { -+ /* Either in-band not supported at at least one end. -+ * In-band bypass at the other end is possible. -+ */ -+ if (phy_ib_caps & LINK_INBAND_DISABLE) -+ pl->phy_ib_mode = LINK_INBAND_DISABLE; -+ else if (phy_ib_caps & LINK_INBAND_BYPASS) -+ pl->phy_ib_mode = LINK_INBAND_BYPASS; -+ - neg_mode = PHYLINK_PCS_NEG_OUTBAND; -+ if (pl->phydev) -+ mode = MLO_AN_PHY; -+ } else { -+ /* invalid */ -+ phylink_warn(pl, "%s: incompatible in-band capabilities, trying in-band", -+ phy_modes(interface)); -+ neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED; -+ } -+ } else { -+ /* For Base-X without a PHY */ -+ if (pcs_ib_caps == LINK_INBAND_DISABLE) -+ /* If the PCS doesn't support inband, then inband must -+ * be disabled. -+ */ -+ neg_mode = PHYLINK_PCS_NEG_INBAND_DISABLED; -+ else if (pcs_ib_caps == LINK_INBAND_ENABLE) -+ /* If the PCS requires inband, then inband must always -+ * be enabled. -+ */ -+ neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED; - else if (linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, - advertising)) - neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED; - else - neg_mode = PHYLINK_PCS_NEG_INBAND_DISABLED; -- break; -- -- default: -- neg_mode = PHYLINK_PCS_NEG_NONE; -- break; - } - - pl->pcs_neg_mode = neg_mode; -@@ -1309,6 +1436,13 @@ static void phylink_major_config(struct - ERR_PTR(err)); - } - -+ if (pl->phydev && pl->phy_ib_mode) { -+ err = phy_config_inband(pl->phydev, pl->phy_ib_mode); -+ if (err < 0) -+ phylink_err(pl, "phy_config_inband: %pe\n", -+ ERR_PTR(err)); -+ } -+ - if (pl->sfp_bus) { - rate_kbd = phylink_interface_signal_rate(state->interface); - if (rate_kbd) diff --git a/target/linux/generic/backport-6.18/601-13-v6.14-net-phylink-remove-phylink_phy_no_inband.patch b/target/linux/generic/backport-6.18/601-13-v6.14-net-phylink-remove-phylink_phy_no_inband.patch deleted file mode 100644 index 8be74a2ad6..0000000000 --- a/target/linux/generic/backport-6.18/601-13-v6.14-net-phylink-remove-phylink_phy_no_inband.patch +++ /dev/null @@ -1,110 +0,0 @@ -From 77ac9a8b2536e0eaca6c6f21070068458bf55981 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Tue, 3 Dec 2024 15:31:48 +0000 -Subject: [PATCH 13/13] net: phylink: remove phylink_phy_no_inband() - -Remove phylink_phy_no_inband() now that we are handling the lack of -inband negotiation by querying the capabilities of the PHY and PCS, -and the BCM84881 PHY driver provides us the information necessary to -make the decision. - -Reviewed-by: Andrew Lunn -Signed-off-by: Russell King (Oracle) -Link: https://patch.msgid.link/E1tIUsO-006IUt-KN@rmk-PC.armlinux.org.uk -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/phylink.c | 27 ++++++--------------------- - 1 file changed, 6 insertions(+), 21 deletions(-) - ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -3394,10 +3394,11 @@ static phy_interface_t phylink_choose_sf - return interface; - } - --static void phylink_sfp_set_config(struct phylink *pl, u8 mode, -+static void phylink_sfp_set_config(struct phylink *pl, - unsigned long *supported, - struct phylink_link_state *state) - { -+ u8 mode = MLO_AN_INBAND; - bool changed = false; - - phylink_dbg(pl, "requesting link mode %s/%s with support %*pb\n", -@@ -3431,8 +3432,7 @@ static void phylink_sfp_set_config(struc - phylink_mac_initial_config(pl, false); - } - --static int phylink_sfp_config_phy(struct phylink *pl, u8 mode, -- struct phy_device *phy) -+static int phylink_sfp_config_phy(struct phylink *pl, struct phy_device *phy) - { - __ETHTOOL_DECLARE_LINK_MODE_MASK(support1); - __ETHTOOL_DECLARE_LINK_MODE_MASK(support); -@@ -3472,7 +3472,7 @@ static int phylink_sfp_config_phy(struct - if (ret) { - phylink_err(pl, - "validation of %s/%s with support %*pb failed: %pe\n", -- phylink_an_mode_str(mode), -+ phylink_an_mode_str(pl->req_link_an_mode), - phy_modes(config.interface), - __ETHTOOL_LINK_MODE_MASK_NBITS, support, - ERR_PTR(ret)); -@@ -3481,7 +3481,7 @@ static int phylink_sfp_config_phy(struct - - pl->link_port = pl->sfp_port; - -- phylink_sfp_set_config(pl, mode, support, &config); -+ phylink_sfp_set_config(pl, support, &config); - - return 0; - } -@@ -3556,7 +3556,7 @@ static int phylink_sfp_config_optical(st - - pl->link_port = pl->sfp_port; - -- phylink_sfp_set_config(pl, MLO_AN_INBAND, pl->sfp_support, &config); -+ phylink_sfp_set_config(pl, pl->sfp_support, &config); - - return 0; - } -@@ -3627,20 +3627,10 @@ static void phylink_sfp_link_up(void *up - phylink_enable_and_run_resolve(pl, PHYLINK_DISABLE_LINK); - } - --/* The Broadcom BCM84881 in the Methode DM7052 is unable to provide a SGMII -- * or 802.3z control word, so inband will not work. -- */ --static bool phylink_phy_no_inband(struct phy_device *phy) --{ -- return phy->is_c45 && phy_id_compare(phy->c45_ids.device_ids[1], -- 0xae025150, 0xfffffff0); --} -- - static int phylink_sfp_connect_phy(void *upstream, struct phy_device *phy) - { - struct phylink *pl = upstream; - phy_interface_t interface; -- u8 mode; - int ret; - - /* -@@ -3652,17 +3642,12 @@ static int phylink_sfp_connect_phy(void - */ - phy_support_asym_pause(phy); - -- if (phylink_phy_no_inband(phy)) -- mode = MLO_AN_PHY; -- else -- mode = MLO_AN_INBAND; -- - /* Set the PHY's host supported interfaces */ - phy_interface_and(phy->host_interfaces, phylink_sfp_interfaces, - pl->config->supported_interfaces); - - /* Do the initial configuration */ -- ret = phylink_sfp_config_phy(pl, mode, phy); -+ ret = phylink_sfp_config_phy(pl, phy); - if (ret < 0) - return ret; - diff --git a/target/linux/generic/backport-6.18/602-01-v6.14-net-pcs-pcs-lynx-implement-pcs_inband_caps-method.patch b/target/linux/generic/backport-6.18/602-01-v6.14-net-pcs-pcs-lynx-implement-pcs_inband_caps-method.patch deleted file mode 100644 index 32ba605b1c..0000000000 --- a/target/linux/generic/backport-6.18/602-01-v6.14-net-pcs-pcs-lynx-implement-pcs_inband_caps-method.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 6561f0e547be221f411fda5eddfcc5bd8bb058a5 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Thu, 5 Dec 2024 09:42:24 +0000 -Subject: [PATCH 1/3] net: pcs: pcs-lynx: implement pcs_inband_caps() method - -Report the PCS in-band capabilities to phylink for the Lynx PCS. - -Reviewed-by: Maxime Chevallier -Signed-off-by: Russell King (Oracle) -Link: https://patch.msgid.link/E1tJ8NM-006L5J-AH@rmk-PC.armlinux.org.uk -Signed-off-by: Jakub Kicinski ---- - drivers/net/pcs/pcs-lynx.c | 22 ++++++++++++++++++++++ - 1 file changed, 22 insertions(+) - ---- a/drivers/net/pcs/pcs-lynx.c -+++ b/drivers/net/pcs/pcs-lynx.c -@@ -35,6 +35,27 @@ enum sgmii_speed { - #define phylink_pcs_to_lynx(pl_pcs) container_of((pl_pcs), struct lynx_pcs, pcs) - #define lynx_to_phylink_pcs(lynx) (&(lynx)->pcs) - -+static unsigned int lynx_pcs_inband_caps(struct phylink_pcs *pcs, -+ phy_interface_t interface) -+{ -+ switch (interface) { -+ case PHY_INTERFACE_MODE_1000BASEX: -+ case PHY_INTERFACE_MODE_SGMII: -+ case PHY_INTERFACE_MODE_QSGMII: -+ return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE; -+ -+ case PHY_INTERFACE_MODE_10GBASER: -+ case PHY_INTERFACE_MODE_2500BASEX: -+ return LINK_INBAND_DISABLE; -+ -+ case PHY_INTERFACE_MODE_USXGMII: -+ return LINK_INBAND_ENABLE; -+ -+ default: -+ return 0; -+ } -+} -+ - static void lynx_pcs_get_state_usxgmii(struct mdio_device *pcs, - struct phylink_link_state *state) - { -@@ -306,6 +327,7 @@ static void lynx_pcs_link_up(struct phyl - } - - static const struct phylink_pcs_ops lynx_pcs_phylink_ops = { -+ .pcs_inband_caps = lynx_pcs_inband_caps, - .pcs_get_state = lynx_pcs_get_state, - .pcs_config = lynx_pcs_config, - .pcs_an_restart = lynx_pcs_an_restart, diff --git a/target/linux/generic/backport-6.18/602-02-v6.14-net-pcs-pcs-mtk-lynxi-implement-pcs_inband_caps-meth.patch b/target/linux/generic/backport-6.18/602-02-v6.14-net-pcs-pcs-mtk-lynxi-implement-pcs_inband_caps-meth.patch deleted file mode 100644 index 1cfd3bab9b..0000000000 --- a/target/linux/generic/backport-6.18/602-02-v6.14-net-pcs-pcs-mtk-lynxi-implement-pcs_inband_caps-meth.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 520d29bdda86915b3caf8c72825a574bff212553 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Thu, 5 Dec 2024 09:42:29 +0000 -Subject: [PATCH 2/3] net: pcs: pcs-mtk-lynxi: implement pcs_inband_caps() - method - -Report the PCS in-band capabilities to phylink for the LynxI PCS. - -Signed-off-by: Russell King (Oracle) -Link: https://patch.msgid.link/E1tJ8NR-006L5P-E3@rmk-PC.armlinux.org.uk -Signed-off-by: Jakub Kicinski ---- - drivers/net/pcs/pcs-mtk-lynxi.c | 16 ++++++++++++++++ - 1 file changed, 16 insertions(+) - ---- a/drivers/net/pcs/pcs-mtk-lynxi.c -+++ b/drivers/net/pcs/pcs-mtk-lynxi.c -@@ -88,6 +88,21 @@ static struct mtk_pcs_lynxi *pcs_to_mtk_ - return container_of(pcs, struct mtk_pcs_lynxi, pcs); - } - -+static unsigned int mtk_pcs_lynxi_inband_caps(struct phylink_pcs *pcs, -+ phy_interface_t interface) -+{ -+ switch (interface) { -+ case PHY_INTERFACE_MODE_1000BASEX: -+ case PHY_INTERFACE_MODE_2500BASEX: -+ case PHY_INTERFACE_MODE_SGMII: -+ case PHY_INTERFACE_MODE_QSGMII: -+ return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE; -+ -+ default: -+ return 0; -+ } -+} -+ - static void mtk_pcs_lynxi_get_state(struct phylink_pcs *pcs, - struct phylink_link_state *state) - { -@@ -241,6 +256,7 @@ static void mtk_pcs_lynxi_disable(struct - } - - static const struct phylink_pcs_ops mtk_pcs_lynxi_ops = { -+ .pcs_inband_caps = mtk_pcs_lynxi_inband_caps, - .pcs_get_state = mtk_pcs_lynxi_get_state, - .pcs_config = mtk_pcs_lynxi_config, - .pcs_an_restart = mtk_pcs_lynxi_restart_an, diff --git a/target/linux/generic/backport-6.18/602-03-v6.14-net-pcs-xpcs-implement-pcs_inband_caps-method.patch b/target/linux/generic/backport-6.18/602-03-v6.14-net-pcs-xpcs-implement-pcs_inband_caps-method.patch deleted file mode 100644 index 8dc495bd0c..0000000000 --- a/target/linux/generic/backport-6.18/602-03-v6.14-net-pcs-xpcs-implement-pcs_inband_caps-method.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 484d0170d6c6bbb5213d037664e9a551f793bacd Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Thu, 5 Dec 2024 09:42:34 +0000 -Subject: [PATCH 3/3] net: pcs: xpcs: implement pcs_inband_caps() method - -Report the PCS inband capabilities to phylink for XPCS. - -Signed-off-by: Russell King (Oracle) -Link: https://patch.msgid.link/E1tJ8NW-006L5V-I9@rmk-PC.armlinux.org.uk -Signed-off-by: Jakub Kicinski ---- - drivers/net/pcs/pcs-xpcs.c | 28 ++++++++++++++++++++++++++++ - 1 file changed, 28 insertions(+) - ---- a/drivers/net/pcs/pcs-xpcs.c -+++ b/drivers/net/pcs/pcs-xpcs.c -@@ -608,6 +608,33 @@ static int xpcs_validate(struct phylink_ - return 0; - } - -+static unsigned int xpcs_inband_caps(struct phylink_pcs *pcs, -+ phy_interface_t interface) -+{ -+ struct dw_xpcs *xpcs = phylink_pcs_to_xpcs(pcs); -+ const struct dw_xpcs_compat *compat; -+ -+ compat = xpcs_find_compat(xpcs->desc, interface); -+ if (!compat) -+ return 0; -+ -+ switch (compat->an_mode) { -+ case DW_AN_C73: -+ return LINK_INBAND_ENABLE; -+ -+ case DW_AN_C37_SGMII: -+ case DW_AN_C37_1000BASEX: -+ return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE; -+ -+ case DW_10GBASER: -+ case DW_2500BASEX: -+ return LINK_INBAND_DISABLE; -+ -+ default: -+ return 0; -+ } -+} -+ - void xpcs_get_interfaces(struct dw_xpcs *xpcs, unsigned long *interfaces) - { - int i, j; -@@ -1365,6 +1392,7 @@ static const struct dw_xpcs_desc xpcs_de - - static const struct phylink_pcs_ops xpcs_phylink_ops = { - .pcs_validate = xpcs_validate, -+ .pcs_inband_caps = xpcs_inband_caps, - .pcs_config = xpcs_config, - .pcs_get_state = xpcs_get_state, - .pcs_an_restart = xpcs_an_restart, diff --git a/target/linux/generic/backport-6.18/605-02-v6.17-net-phylink-provide-phylink_get_inband_type.patch b/target/linux/generic/backport-6.18/605-02-v6.17-net-phylink-provide-phylink_get_inband_type.patch deleted file mode 100644 index e944f573e0..0000000000 --- a/target/linux/generic/backport-6.18/605-02-v6.17-net-phylink-provide-phylink_get_inband_type.patch +++ /dev/null @@ -1,117 +0,0 @@ -From 1bd905dfea9897eafef532000702e63a66849f54 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Sun, 31 Aug 2025 18:34:38 +0100 -Subject: net: phylink: provide phylink_get_inband_type() - -Provide a function to get the type of the inband signalling used for -a PHY interface type. This will be used in the subsequent patch to -address problems with 10G optical modules. - -Signed-off-by: Russell King (Oracle) -Reviewed-by: Andrew Lunn -Link: https://patch.msgid.link/E1uslws-00000001SP5-1R2R@rmk-PC.armlinux.org.uk -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/phylink.c | 79 ++++++++++++++++++++++----------------- - 1 file changed, 44 insertions(+), 35 deletions(-) - ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -1147,6 +1147,42 @@ static void phylink_pcs_an_restart(struc - pl->pcs->ops->pcs_an_restart(pl->pcs); - } - -+enum inband_type { -+ INBAND_NONE, -+ INBAND_CISCO_SGMII, -+ INBAND_BASEX, -+}; -+ -+static enum inband_type phylink_get_inband_type(phy_interface_t interface) -+{ -+ switch (interface) { -+ case PHY_INTERFACE_MODE_SGMII: -+ case PHY_INTERFACE_MODE_QSGMII: -+ case PHY_INTERFACE_MODE_QUSGMII: -+ case PHY_INTERFACE_MODE_USXGMII: -+ case PHY_INTERFACE_MODE_10G_QXGMII: -+ /* These protocols are designed for use with a PHY which -+ * communicates its negotiation result back to the MAC via -+ * inband communication. Note: there exist PHYs that run -+ * with SGMII but do not send the inband data. -+ */ -+ return INBAND_CISCO_SGMII; -+ -+ case PHY_INTERFACE_MODE_1000BASEX: -+ case PHY_INTERFACE_MODE_2500BASEX: -+ /* 1000base-X is designed for use media-side for Fibre -+ * connections, and thus the Autoneg bit needs to be -+ * taken into account. We also do this for 2500base-X -+ * as well, but drivers may not support this, so may -+ * need to override this. -+ */ -+ return INBAND_BASEX; -+ -+ default: -+ return INBAND_NONE; -+ } -+} -+ - /** - * phylink_pcs_neg_mode() - helper to determine PCS inband mode - * @pl: a pointer to a &struct phylink returned from phylink_create() -@@ -1174,46 +1210,19 @@ static void phylink_pcs_neg_mode(struct - unsigned int pcs_ib_caps = 0; - unsigned int phy_ib_caps = 0; - unsigned int neg_mode, mode; -- enum { -- INBAND_CISCO_SGMII, -- INBAND_BASEX, -- } type; -- -- mode = pl->req_link_an_mode; -+ enum inband_type type; - -- pl->phy_ib_mode = 0; -- -- switch (interface) { -- case PHY_INTERFACE_MODE_SGMII: -- case PHY_INTERFACE_MODE_QSGMII: -- case PHY_INTERFACE_MODE_QUSGMII: -- case PHY_INTERFACE_MODE_USXGMII: -- case PHY_INTERFACE_MODE_10G_QXGMII: -- /* These protocols are designed for use with a PHY which -- * communicates its negotiation result back to the MAC via -- * inband communication. Note: there exist PHYs that run -- * with SGMII but do not send the inband data. -- */ -- type = INBAND_CISCO_SGMII; -- break; -- -- case PHY_INTERFACE_MODE_1000BASEX: -- case PHY_INTERFACE_MODE_2500BASEX: -- /* 1000base-X is designed for use media-side for Fibre -- * connections, and thus the Autoneg bit needs to be -- * taken into account. We also do this for 2500base-X -- * as well, but drivers may not support this, so may -- * need to override this. -- */ -- type = INBAND_BASEX; -- break; -- -- default: -+ type = phylink_get_inband_type(interface); -+ if (type == INBAND_NONE) { - pl->pcs_neg_mode = PHYLINK_PCS_NEG_NONE; -- pl->act_link_an_mode = mode; -+ pl->act_link_an_mode = pl->req_link_an_mode; - return; - } - -+ mode = pl->req_link_an_mode; -+ -+ pl->phy_ib_mode = 0; -+ - if (pcs) - pcs_ib_caps = phylink_pcs_inband_caps(pcs, interface); - diff --git a/target/linux/generic/backport-6.18/605-03-v6.17-net-phylink-disable-autoneg-for-interfaces-that-have.patch b/target/linux/generic/backport-6.18/605-03-v6.17-net-phylink-disable-autoneg-for-interfaces-that-have.patch deleted file mode 100644 index 0861bb820d..0000000000 --- a/target/linux/generic/backport-6.18/605-03-v6.17-net-phylink-disable-autoneg-for-interfaces-that-have.patch +++ /dev/null @@ -1,68 +0,0 @@ -From a21202743f9ce4063e86b99cccaef48ef9813379 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Sun, 31 Aug 2025 18:34:43 +0100 -Subject: net: phylink: disable autoneg for interfaces that have no inband - -Mathew reports that as a result of commit 6561f0e547be ("net: pcs: -pcs-lynx: implement pcs_inband_caps() method"), 10G SFP modules no -longer work with the Lynx PCS. - -This problem is not specific to the Lynx PCS, but is caused by commit -df874f9e52c3 ("net: phylink: add pcs_inband_caps() method") which added -validation of the autoneg state to the optical SFP configuration path. - -Fix this by handling interface modes that fundamentally have no -inband negotiation more correctly - if we only have a single interface -mode, clear the Autoneg support bit and the advertising mask. If the -module can operate with several different interface modes, autoneg may -be supported for other modes, so leave the support mask alone and just -clear the Autoneg bit in the advertising mask. - -This restores 10G optical module functionality with PCS that supply -their inband support, and makes ethtool output look sane. - -Reported-by: Mathew McBride -Closes: https://lore.kernel.org/r/025c0ebe-5537-4fa3-b05a-8b835e5ad317@app.fastmail.com -Fixes: df874f9e52c3 ("net: phylink: add pcs_inband_caps() method") -Signed-off-by: Russell King (Oracle) -Tested-by: Vladimir Oltean -Link: https://patch.msgid.link/E1uslwx-00000001SPB-2kiM@rmk-PC.armlinux.org.uk -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/phylink.c | 18 ++++++++++++++++++ - 1 file changed, 18 insertions(+) - ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -3500,6 +3500,7 @@ static int phylink_sfp_config_optical(st - __ETHTOOL_DECLARE_LINK_MODE_MASK(support); - DECLARE_PHY_INTERFACE_MASK(interfaces); - struct phylink_link_state config; -+ enum inband_type inband_type; - phy_interface_t interface; - int ret; - -@@ -3546,6 +3547,23 @@ static int phylink_sfp_config_optical(st - phylink_dbg(pl, "optical SFP: chosen %s interface\n", - phy_modes(interface)); - -+ inband_type = phylink_get_inband_type(interface); -+ if (inband_type == INBAND_NONE) { -+ /* If this is the sole interface, and there is no inband -+ * support, clear the advertising mask and Autoneg bit in -+ * the support mask. Otherwise, just clear the Autoneg bit -+ * in the advertising mask. -+ */ -+ if (phy_interface_weight(pl->sfp_interfaces) == 1) { -+ linkmode_clear_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, -+ pl->sfp_support); -+ linkmode_zero(config.advertising); -+ } else { -+ linkmode_clear_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, -+ config.advertising); -+ } -+ } -+ - if (!phylink_validate_pcs_inband_autoneg(pl, interface, - config.advertising)) { - phylink_err(pl, "autoneg setting not compatible with PCS"); diff --git a/target/linux/generic/backport-6.18/610-01-v6.13-net-dsa-use-ethtool-string-helpers.patch b/target/linux/generic/backport-6.18/610-01-v6.13-net-dsa-use-ethtool-string-helpers.patch deleted file mode 100644 index a435e29144..0000000000 --- a/target/linux/generic/backport-6.18/610-01-v6.13-net-dsa-use-ethtool-string-helpers.patch +++ /dev/null @@ -1,30 +0,0 @@ -From f12b363887c706c40611fba645265527a8415832 Mon Sep 17 00:00:00 2001 -From: Rosen Penev -Date: Sun, 27 Oct 2024 21:48:28 -0700 -Subject: [PATCH] net: dsa: use ethtool string helpers - -These are the preferred way to copy ethtool strings. - -Avoids incrementing pointers all over the place. - -Signed-off-by: Rosen Penev -(for hellcreek driver) -Reviewed-by: Kurt Kanzenbach -Link: https://patch.msgid.link/20241028044828.1639668-1-rosenp@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/dsa/b53/b53_common.c | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - ---- a/drivers/net/dsa/b53/b53_common.c -+++ b/drivers/net/dsa/b53/b53_common.c -@@ -1086,8 +1086,7 @@ void b53_get_strings(struct dsa_switch * - - if (stringset == ETH_SS_STATS) { - for (i = 0; i < mib_size; i++) -- strscpy(data + i * ETH_GSTRING_LEN, -- mibs[i].name, ETH_GSTRING_LEN); -+ ethtool_puts(&data, mibs[i].name); - } else if (stringset == ETH_SS_PHY_STATS) { - phydev = b53_get_phy_device(ds, port); - if (!phydev) diff --git a/target/linux/generic/backport-6.18/610-02-v6.15-net-dsa-b53-mdio-add-support-for-BCM53101.patch b/target/linux/generic/backport-6.18/610-02-v6.15-net-dsa-b53-mdio-add-support-for-BCM53101.patch deleted file mode 100644 index 6cbe547423..0000000000 --- a/target/linux/generic/backport-6.18/610-02-v6.15-net-dsa-b53-mdio-add-support-for-BCM53101.patch +++ /dev/null @@ -1,76 +0,0 @@ -From c4f873c2b65c839ff5e7c996bd9ef5a1e7eae11a Mon Sep 17 00:00:00 2001 -From: Torben Nielsen -Date: Mon, 17 Feb 2025 09:05:01 +0100 -Subject: [PATCH] net: dsa: b53: mdio: add support for BCM53101 - -BCM53101 is a ethernet switch, very similar to the BCM53115. -Enable support for it, in the existing b53 dsa driver. - -Signed-off-by: Torben Nielsen -Signed-off-by: Claus Stovgaard -Link: https://patch.msgid.link/20250217080503.1390282-1-claus.stovgaard@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/dsa/b53/b53_common.c | 14 ++++++++++++++ - drivers/net/dsa/b53/b53_mdio.c | 1 + - drivers/net/dsa/b53/b53_priv.h | 2 ++ - 3 files changed, 17 insertions(+) - ---- a/drivers/net/dsa/b53/b53_common.c -+++ b/drivers/net/dsa/b53/b53_common.c -@@ -2606,6 +2606,19 @@ static const struct b53_chip_data b53_sw - .jumbo_size_reg = B53_JUMBO_MAX_SIZE, - }, - { -+ .chip_id = BCM53101_DEVICE_ID, -+ .dev_name = "BCM53101", -+ .vlans = 4096, -+ .enabled_ports = 0x11f, -+ .arl_bins = 4, -+ .arl_buckets = 512, -+ .vta_regs = B53_VTA_REGS, -+ .imp_port = 8, -+ .duplex_reg = B53_DUPLEX_STAT_GE, -+ .jumbo_pm_reg = B53_JUMBO_PORT_MASK, -+ .jumbo_size_reg = B53_JUMBO_MAX_SIZE, -+ }, -+ { - .chip_id = BCM53115_DEVICE_ID, - .dev_name = "BCM53115", - .vlans = 4096, -@@ -2986,6 +2999,7 @@ int b53_switch_detect(struct b53_device - return ret; - - switch (id32) { -+ case BCM53101_DEVICE_ID: - case BCM53115_DEVICE_ID: - case BCM53125_DEVICE_ID: - case BCM53128_DEVICE_ID: ---- a/drivers/net/dsa/b53/b53_mdio.c -+++ b/drivers/net/dsa/b53/b53_mdio.c -@@ -374,6 +374,7 @@ static void b53_mdio_shutdown(struct mdi - - static const struct of_device_id b53_of_match[] = { - { .compatible = "brcm,bcm5325" }, -+ { .compatible = "brcm,bcm53101" }, - { .compatible = "brcm,bcm53115" }, - { .compatible = "brcm,bcm53125" }, - { .compatible = "brcm,bcm53128" }, ---- a/drivers/net/dsa/b53/b53_priv.h -+++ b/drivers/net/dsa/b53/b53_priv.h -@@ -66,6 +66,7 @@ enum { - BCM5395_DEVICE_ID = 0x95, - BCM5397_DEVICE_ID = 0x97, - BCM5398_DEVICE_ID = 0x98, -+ BCM53101_DEVICE_ID = 0x53101, - BCM53115_DEVICE_ID = 0x53115, - BCM53125_DEVICE_ID = 0x53125, - BCM53128_DEVICE_ID = 0x53128, -@@ -190,6 +191,7 @@ static inline int is531x5(struct b53_dev - { - return dev->chip_id == BCM53115_DEVICE_ID || - dev->chip_id == BCM53125_DEVICE_ID || -+ dev->chip_id == BCM53101_DEVICE_ID || - dev->chip_id == BCM53128_DEVICE_ID || - dev->chip_id == BCM53134_DEVICE_ID; - } diff --git a/target/linux/generic/backport-6.18/610-03-v6.16-net-dsa-b53-implement-setting-ageing-time.patch b/target/linux/generic/backport-6.18/610-03-v6.16-net-dsa-b53-implement-setting-ageing-time.patch deleted file mode 100644 index 196e70c42c..0000000000 --- a/target/linux/generic/backport-6.18/610-03-v6.16-net-dsa-b53-implement-setting-ageing-time.patch +++ /dev/null @@ -1,105 +0,0 @@ -From e39d14a760c039af0653e3df967e7525413924a0 Mon Sep 17 00:00:00 2001 -From: Jonas Gorski -Date: Sat, 10 May 2025 11:22:11 +0200 -Subject: [PATCH] net: dsa: b53: implement setting ageing time - -b53 supported switches support configuring ageing time between 1 and -1,048,575 seconds, so add an appropriate setter. - -This allows b53 to pass the FDB learning test for both vlan aware and -vlan unaware bridges. - -Signed-off-by: Jonas Gorski -Reviewed-by: Florian Fainelli -Link: https://patch.msgid.link/20250510092211.276541-1-jonas.gorski@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/dsa/b53/b53_common.c | 28 ++++++++++++++++++++++++++++ - drivers/net/dsa/b53/b53_priv.h | 1 + - drivers/net/dsa/b53/b53_regs.h | 7 +++++++ - 3 files changed, 36 insertions(+) - ---- a/drivers/net/dsa/b53/b53_common.c -+++ b/drivers/net/dsa/b53/b53_common.c -@@ -21,6 +21,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -1227,6 +1228,10 @@ static int b53_setup(struct dsa_switch * - */ - ds->untag_vlan_aware_bridge_pvid = true; - -+ /* Ageing time is set in seconds */ -+ ds->ageing_time_min = 1 * 1000; -+ ds->ageing_time_max = AGE_TIME_MAX * 1000; -+ - ret = b53_reset_switch(dev); - if (ret) { - dev_err(ds->dev, "failed to reset switch\n"); -@@ -2466,6 +2471,28 @@ static int b53_get_max_mtu(struct dsa_sw - return B53_MAX_MTU; - } - -+int b53_set_ageing_time(struct dsa_switch *ds, unsigned int msecs) -+{ -+ struct b53_device *dev = ds->priv; -+ u32 atc; -+ int reg; -+ -+ if (is63xx(dev)) -+ reg = B53_AGING_TIME_CONTROL_63XX; -+ else -+ reg = B53_AGING_TIME_CONTROL; -+ -+ atc = DIV_ROUND_CLOSEST(msecs, 1000); -+ -+ if (!is5325(dev) && !is5365(dev)) -+ atc |= AGE_CHANGE; -+ -+ b53_write32(dev, B53_MGMT_PAGE, reg, atc); -+ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(b53_set_ageing_time); -+ - static const struct phylink_mac_ops b53_phylink_mac_ops = { - .mac_select_pcs = b53_phylink_mac_select_pcs, - .mac_config = b53_phylink_mac_config, -@@ -2490,6 +2517,7 @@ static const struct dsa_switch_ops b53_s - .support_eee = b53_support_eee, - .get_mac_eee = b53_get_mac_eee, - .set_mac_eee = b53_set_mac_eee, -+ .set_ageing_time = b53_set_ageing_time, - .port_bridge_join = b53_br_join, - .port_bridge_leave = b53_br_leave, - .port_pre_bridge_flags = b53_br_flags_pre, ---- a/drivers/net/dsa/b53/b53_priv.h -+++ b/drivers/net/dsa/b53/b53_priv.h -@@ -343,6 +343,7 @@ void b53_get_strings(struct dsa_switch * - void b53_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *data); - int b53_get_sset_count(struct dsa_switch *ds, int port, int sset); - void b53_get_ethtool_phy_stats(struct dsa_switch *ds, int port, uint64_t *data); -+int b53_set_ageing_time(struct dsa_switch *ds, unsigned int msecs); - int b53_br_join(struct dsa_switch *ds, int port, struct dsa_bridge bridge, - bool *tx_fwd_offload, struct netlink_ext_ack *extack); - void b53_br_leave(struct dsa_switch *ds, int port, struct dsa_bridge bridge); ---- a/drivers/net/dsa/b53/b53_regs.h -+++ b/drivers/net/dsa/b53/b53_regs.h -@@ -224,6 +224,13 @@ - #define BRCM_HDR_P5_EN BIT(1) /* Enable tagging on port 5 */ - #define BRCM_HDR_P7_EN BIT(2) /* Enable tagging on port 7 */ - -+/* Aging Time control register (32 bit) */ -+#define B53_AGING_TIME_CONTROL 0x06 -+#define B53_AGING_TIME_CONTROL_63XX 0x08 -+#define AGE_CHANGE BIT(20) -+#define AGE_TIME_MASK 0x7ffff -+#define AGE_TIME_MAX 1048575 -+ - /* Mirror capture control register (16 bit) */ - #define B53_MIR_CAP_CTL 0x10 - #define CAP_PORT_MASK 0xf diff --git a/target/linux/generic/backport-6.18/610-04-v6.16-net-dsa-b53-do-not-configure-bcm63xx-s-IMP-port-inte.patch b/target/linux/generic/backport-6.18/610-04-v6.16-net-dsa-b53-do-not-configure-bcm63xx-s-IMP-port-inte.patch deleted file mode 100644 index e70f09e050..0000000000 --- a/target/linux/generic/backport-6.18/610-04-v6.16-net-dsa-b53-do-not-configure-bcm63xx-s-IMP-port-inte.patch +++ /dev/null @@ -1,70 +0,0 @@ -From 75f4f7b2b13008803f84768ff90396f9d7553221 Mon Sep 17 00:00:00 2001 -From: Jonas Gorski -Date: Mon, 2 Jun 2025 21:39:51 +0200 -Subject: [PATCH] net: dsa: b53: do not configure bcm63xx's IMP port interface - -The IMP port is not a valid RGMII interface, but hard wired to internal, -so we shouldn't touch the undefined register B53_RGMII_CTRL_IMP. - -While this does not seem to have any side effects, let's not touch it at -all, so limit RGMII configuration on bcm63xx to the actual RGMII ports. - -Fixes: ce3bf94871f7 ("net: dsa: b53: add support for BCM63xx RGMIIs") -Signed-off-by: Jonas Gorski -Reviewed-by: Florian Fainelli -Link: https://patch.msgid.link/20250602193953.1010487-4-jonas.gorski@gmail.com -Signed-off-by: Paolo Abeni ---- - drivers/net/dsa/b53/b53_common.c | 22 ++++++++-------------- - 1 file changed, 8 insertions(+), 14 deletions(-) - ---- a/drivers/net/dsa/b53/b53_common.c -+++ b/drivers/net/dsa/b53/b53_common.c -@@ -22,6 +22,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -1369,24 +1370,17 @@ static void b53_adjust_63xx_rgmii(struct - phy_interface_t interface) - { - struct b53_device *dev = ds->priv; -- u8 rgmii_ctrl = 0, off; -- -- if (port == dev->imp_port) -- off = B53_RGMII_CTRL_IMP; -- else -- off = B53_RGMII_CTRL_P(port); -+ u8 rgmii_ctrl = 0; - -- b53_read8(dev, B53_CTRL_PAGE, off, &rgmii_ctrl); -+ b53_read8(dev, B53_CTRL_PAGE, B53_RGMII_CTRL_P(port), &rgmii_ctrl); - rgmii_ctrl &= ~(RGMII_CTRL_DLL_RXC | RGMII_CTRL_DLL_TXC); - -- if (port != dev->imp_port) { -- if (is63268(dev)) -- rgmii_ctrl |= RGMII_CTRL_MII_OVERRIDE; -+ if (is63268(dev)) -+ rgmii_ctrl |= RGMII_CTRL_MII_OVERRIDE; - -- rgmii_ctrl |= RGMII_CTRL_ENABLE_GMII; -- } -+ rgmii_ctrl |= RGMII_CTRL_ENABLE_GMII; - -- b53_write8(dev, B53_CTRL_PAGE, off, rgmii_ctrl); -+ b53_write8(dev, B53_CTRL_PAGE, B53_RGMII_CTRL_P(port), rgmii_ctrl); - - dev_dbg(ds->dev, "Configured port %d for %s\n", port, - phy_modes(interface)); -@@ -1537,7 +1531,7 @@ static void b53_phylink_mac_config(struc - struct b53_device *dev = ds->priv; - int port = dp->index; - -- if (is63xx(dev) && port >= B53_63XX_RGMII0) -+ if (is63xx(dev) && in_range(port, B53_63XX_RGMII0, 4)) - b53_adjust_63xx_rgmii(ds, port, interface); - - if (mode == MLO_AN_FIXED) { diff --git a/target/linux/generic/backport-6.18/611-01-v6.17-net-dsa-tag_brcm-add-support-for-legacy-FCS-tags.patch b/target/linux/generic/backport-6.18/611-01-v6.17-net-dsa-tag_brcm-add-support-for-legacy-FCS-tags.patch deleted file mode 100644 index 88f10be377..0000000000 --- a/target/linux/generic/backport-6.18/611-01-v6.17-net-dsa-tag_brcm-add-support-for-legacy-FCS-tags.patch +++ /dev/null @@ -1,188 +0,0 @@ -From ef07df397a621707903ef0d294a7df11f80cf206 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= -Date: Sat, 14 Jun 2025 09:59:48 +0200 -Subject: [PATCH] net: dsa: tag_brcm: add support for legacy FCS tags -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Add support for legacy Broadcom FCS tags, which are similar to -DSA_TAG_PROTO_BRCM_LEGACY. -BCM5325 and BCM5365 switches require including the original FCS value and -length, as opposed to BCM63xx switches. -Adding the original FCS value and length to DSA_TAG_PROTO_BRCM_LEGACY would -impact performance of BCM63xx switches, so it's better to create a new tag. - -Signed-off-by: Álvaro Fernández Rojas -Reviewed-by: Florian Fainelli -Link: https://patch.msgid.link/20250614080000.1884236-3-noltari@gmail.com -Signed-off-by: Jakub Kicinski ---- - include/net/dsa.h | 2 ++ - net/dsa/Kconfig | 16 ++++++++-- - net/dsa/tag_brcm.c | 73 +++++++++++++++++++++++++++++++++++++++++++++- - 3 files changed, 88 insertions(+), 3 deletions(-) - ---- a/include/net/dsa.h -+++ b/include/net/dsa.h -@@ -54,11 +54,13 @@ struct tc_action; - #define DSA_TAG_PROTO_RZN1_A5PSW_VALUE 26 - #define DSA_TAG_PROTO_LAN937X_VALUE 27 - #define DSA_TAG_PROTO_VSC73XX_8021Q_VALUE 28 -+#define DSA_TAG_PROTO_BRCM_LEGACY_FCS_VALUE 29 - - enum dsa_tag_protocol { - DSA_TAG_PROTO_NONE = DSA_TAG_PROTO_NONE_VALUE, - DSA_TAG_PROTO_BRCM = DSA_TAG_PROTO_BRCM_VALUE, - DSA_TAG_PROTO_BRCM_LEGACY = DSA_TAG_PROTO_BRCM_LEGACY_VALUE, -+ DSA_TAG_PROTO_BRCM_LEGACY_FCS = DSA_TAG_PROTO_BRCM_LEGACY_FCS_VALUE, - DSA_TAG_PROTO_BRCM_PREPEND = DSA_TAG_PROTO_BRCM_PREPEND_VALUE, - DSA_TAG_PROTO_DSA = DSA_TAG_PROTO_DSA_VALUE, - DSA_TAG_PROTO_EDSA = DSA_TAG_PROTO_EDSA_VALUE, ---- a/net/dsa/Kconfig -+++ b/net/dsa/Kconfig -@@ -42,12 +42,24 @@ config NET_DSA_TAG_BRCM - Broadcom switches which place the tag after the MAC source address. - - config NET_DSA_TAG_BRCM_LEGACY -- tristate "Tag driver for Broadcom legacy switches using in-frame headers" -+ tristate "Tag driver for BCM63xx legacy switches using in-frame headers" - select NET_DSA_TAG_BRCM_COMMON - help - Say Y if you want to enable support for tagging frames for the -- Broadcom legacy switches which place the tag after the MAC source -+ BCM63xx legacy switches which place the tag after the MAC source - address. -+ This tag is used in BCM63xx legacy switches which work without the -+ original FCS and length before the tag insertion. -+ -+config NET_DSA_TAG_BRCM_LEGACY_FCS -+ tristate "Tag driver for BCM53xx legacy switches using in-frame headers" -+ select NET_DSA_TAG_BRCM_COMMON -+ help -+ Say Y if you want to enable support for tagging frames for the -+ BCM53xx legacy switches which place the tag after the MAC source -+ address. -+ This tag is used in BCM53xx legacy switches which expect original -+ FCS and length before the tag insertion to be present. - - config NET_DSA_TAG_BRCM_PREPEND - tristate "Tag driver for Broadcom switches using prepended headers" ---- a/net/dsa/tag_brcm.c -+++ b/net/dsa/tag_brcm.c -@@ -15,6 +15,7 @@ - - #define BRCM_NAME "brcm" - #define BRCM_LEGACY_NAME "brcm-legacy" -+#define BRCM_LEGACY_FCS_NAME "brcm-legacy-fcs" - #define BRCM_PREPEND_NAME "brcm-prepend" - - /* Legacy Broadcom tag (6 bytes) */ -@@ -32,6 +33,10 @@ - #define BRCM_LEG_MULTICAST (1 << 5) - #define BRCM_LEG_EGRESS (2 << 5) - #define BRCM_LEG_INGRESS (3 << 5) -+#define BRCM_LEG_LEN_HI(x) (((x) >> 8) & 0x7) -+ -+/* 4th byte in the tag */ -+#define BRCM_LEG_LEN_LO(x) ((x) & 0xff) - - /* 6th byte in the tag */ - #define BRCM_LEG_PORT_ID (0xf) -@@ -212,7 +217,8 @@ DSA_TAG_DRIVER(brcm_netdev_ops); - MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_BRCM, BRCM_NAME); - #endif - --#if IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM_LEGACY) -+#if IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM_LEGACY) || \ -+ IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM_LEGACY_FCS) - static struct sk_buff *brcm_leg_tag_rcv(struct sk_buff *skb, - struct net_device *dev) - { -@@ -250,7 +256,9 @@ static struct sk_buff *brcm_leg_tag_rcv( - - return skb; - } -+#endif /* CONFIG_NET_DSA_TAG_BRCM_LEGACY || CONFIG_NET_DSA_TAG_BRCM_LEGACY_FCS */ - -+#if IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM_LEGACY) - static struct sk_buff *brcm_leg_tag_xmit(struct sk_buff *skb, - struct net_device *dev) - { -@@ -300,6 +308,66 @@ DSA_TAG_DRIVER(brcm_legacy_netdev_ops); - MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_BRCM_LEGACY, BRCM_LEGACY_NAME); - #endif /* CONFIG_NET_DSA_TAG_BRCM_LEGACY */ - -+#if IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM_LEGACY_FCS) -+static struct sk_buff *brcm_leg_fcs_tag_xmit(struct sk_buff *skb, -+ struct net_device *dev) -+{ -+ struct dsa_port *dp = dsa_user_to_port(dev); -+ unsigned int fcs_len; -+ __le32 fcs_val; -+ u8 *brcm_tag; -+ -+ /* The Ethernet switch we are interfaced with needs packets to be at -+ * least 64 bytes (including FCS) otherwise they will be discarded when -+ * they enter the switch port logic. When Broadcom tags are enabled, we -+ * need to make sure that packets are at least 70 bytes (including FCS -+ * and tag) because the length verification is done after the Broadcom -+ * tag is stripped off the ingress packet. -+ * -+ * Let dsa_user_xmit() free the SKB. -+ */ -+ if (__skb_put_padto(skb, ETH_ZLEN + BRCM_LEG_TAG_LEN, false)) -+ return NULL; -+ -+ fcs_len = skb->len; -+ fcs_val = cpu_to_le32(crc32_le(~0, skb->data, fcs_len) ^ ~0); -+ -+ skb_push(skb, BRCM_LEG_TAG_LEN); -+ -+ dsa_alloc_etype_header(skb, BRCM_LEG_TAG_LEN); -+ -+ brcm_tag = skb->data + 2 * ETH_ALEN; -+ -+ /* Broadcom tag type */ -+ brcm_tag[0] = BRCM_LEG_TYPE_HI; -+ brcm_tag[1] = BRCM_LEG_TYPE_LO; -+ -+ /* Broadcom tag value */ -+ brcm_tag[2] = BRCM_LEG_EGRESS | BRCM_LEG_LEN_HI(fcs_len); -+ brcm_tag[3] = BRCM_LEG_LEN_LO(fcs_len); -+ brcm_tag[4] = 0; -+ brcm_tag[5] = dp->index & BRCM_LEG_PORT_ID; -+ -+ /* Original FCS value */ -+ if (__skb_pad(skb, ETH_FCS_LEN, false)) -+ return NULL; -+ skb_put_data(skb, &fcs_val, ETH_FCS_LEN); -+ -+ return skb; -+} -+ -+static const struct dsa_device_ops brcm_legacy_fcs_netdev_ops = { -+ .name = BRCM_LEGACY_FCS_NAME, -+ .proto = DSA_TAG_PROTO_BRCM_LEGACY_FCS, -+ .xmit = brcm_leg_fcs_tag_xmit, -+ .rcv = brcm_leg_tag_rcv, -+ .needed_headroom = BRCM_LEG_TAG_LEN, -+}; -+ -+DSA_TAG_DRIVER(brcm_legacy_fcs_netdev_ops); -+MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_BRCM_LEGACY_FCS, BRCM_LEGACY_FCS_NAME); -+#endif /* CONFIG_NET_DSA_TAG_BRCM_LEGACY_FCS */ -+ - #if IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM_PREPEND) - static struct sk_buff *brcm_tag_xmit_prepend(struct sk_buff *skb, - struct net_device *dev) -@@ -334,6 +402,9 @@ static struct dsa_tag_driver *dsa_tag_dr - #if IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM_LEGACY) - &DSA_TAG_DRIVER_NAME(brcm_legacy_netdev_ops), - #endif -+#if IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM_LEGACY_FCS) -+ &DSA_TAG_DRIVER_NAME(brcm_legacy_fcs_netdev_ops), -+#endif - #if IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM_PREPEND) - &DSA_TAG_DRIVER_NAME(brcm_prepend_netdev_ops), - #endif diff --git a/target/linux/generic/backport-6.18/611-02-v6.17-net-dsa-b53-support-legacy-FCS-tags.patch b/target/linux/generic/backport-6.18/611-02-v6.17-net-dsa-b53-support-legacy-FCS-tags.patch deleted file mode 100644 index b04c8ea27e..0000000000 --- a/target/linux/generic/backport-6.18/611-02-v6.17-net-dsa-b53-support-legacy-FCS-tags.patch +++ /dev/null @@ -1,48 +0,0 @@ -From c3cf059a4d419b9c888ce7e9952fa13ba7569b61 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= -Date: Sat, 14 Jun 2025 09:59:49 +0200 -Subject: [PATCH] net: dsa: b53: support legacy FCS tags -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Commit 46c5176c586c ("net: dsa: b53: support legacy tags") introduced -support for legacy tags, but it turns out that BCM5325 and BCM5365 -switches require the original FCS value and length, so they have to be -treated differently. - -Reviewed-by: Florian Fainelli -Signed-off-by: Álvaro Fernández Rojas -Link: https://patch.msgid.link/20250614080000.1884236-4-noltari@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/dsa/b53/Kconfig | 1 + - drivers/net/dsa/b53/b53_common.c | 7 +++++-- - 2 files changed, 6 insertions(+), 2 deletions(-) - ---- a/drivers/net/dsa/b53/Kconfig -+++ b/drivers/net/dsa/b53/Kconfig -@@ -5,6 +5,7 @@ menuconfig B53 - select NET_DSA_TAG_NONE - select NET_DSA_TAG_BRCM - select NET_DSA_TAG_BRCM_LEGACY -+ select NET_DSA_TAG_BRCM_LEGACY_FCS - select NET_DSA_TAG_BRCM_PREPEND - help - This driver adds support for Broadcom managed switch chips. It supports ---- a/drivers/net/dsa/b53/b53_common.c -+++ b/drivers/net/dsa/b53/b53_common.c -@@ -2307,8 +2307,11 @@ enum dsa_tag_protocol b53_get_tag_protoc - goto out; - } - -- /* Older models require a different 6 byte tag */ -- if (is5325(dev) || is5365(dev) || is63xx(dev)) { -+ /* Older models require different 6 byte tags */ -+ if (is5325(dev) || is5365(dev)) { -+ dev->tag_protocol = DSA_TAG_PROTO_BRCM_LEGACY_FCS; -+ goto out; -+ } else if (is63xx(dev)) { - dev->tag_protocol = DSA_TAG_PROTO_BRCM_LEGACY; - goto out; - } diff --git a/target/linux/generic/backport-6.18/611-03-v6.17-net-dsa-b53-detect-BCM5325-variants.patch b/target/linux/generic/backport-6.18/611-03-v6.17-net-dsa-b53-detect-BCM5325-variants.patch deleted file mode 100644 index 3c2fa2d8c4..0000000000 --- a/target/linux/generic/backport-6.18/611-03-v6.17-net-dsa-b53-detect-BCM5325-variants.patch +++ /dev/null @@ -1,112 +0,0 @@ -From 0cbec9aef5a86194117a956546dc1aec95031f37 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= -Date: Sat, 14 Jun 2025 09:59:50 +0200 -Subject: [PATCH] net: dsa: b53: detect BCM5325 variants -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -We need to be able to differentiate the BCM5325 variants because: -- BCM5325M switches lack the ARLIO_PAGE->VLAN_ID_IDX register. -- BCM5325E have less 512 ARL buckets instead of 1024. - -Signed-off-by: Álvaro Fernández Rojas -Reviewed-by: Florian Fainelli -Link: https://patch.msgid.link/20250614080000.1884236-5-noltari@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/dsa/b53/b53_common.c | 24 +++++++++++++++++++++--- - drivers/net/dsa/b53/b53_priv.h | 19 +++++++++++++++++++ - 2 files changed, 40 insertions(+), 3 deletions(-) - ---- a/drivers/net/dsa/b53/b53_common.c -+++ b/drivers/net/dsa/b53/b53_common.c -@@ -1835,7 +1835,8 @@ static int b53_arl_op(struct b53_device - - /* Perform a read for the given MAC and VID */ - b53_write48(dev, B53_ARLIO_PAGE, B53_MAC_ADDR_IDX, mac); -- b53_write16(dev, B53_ARLIO_PAGE, B53_VLAN_ID_IDX, vid); -+ if (!is5325m(dev)) -+ b53_write16(dev, B53_ARLIO_PAGE, B53_VLAN_ID_IDX, vid); - - /* Issue a read operation for this MAC */ - ret = b53_arl_rw_op(dev, 1); -@@ -2906,6 +2907,9 @@ static int b53_switch_init(struct b53_de - } - } - -+ if (is5325e(dev)) -+ dev->num_arl_buckets = 512; -+ - dev->num_ports = fls(dev->enabled_ports); - - dev->ds->num_ports = min_t(unsigned int, dev->num_ports, DSA_MAX_PORTS); -@@ -3007,10 +3011,24 @@ int b53_switch_detect(struct b53_device - b53_write16(dev, B53_VLAN_PAGE, B53_VLAN_TABLE_ACCESS_25, 0xf); - b53_read16(dev, B53_VLAN_PAGE, B53_VLAN_TABLE_ACCESS_25, &tmp); - -- if (tmp == 0xf) -+ if (tmp == 0xf) { -+ u32 phy_id; -+ int val; -+ - dev->chip_id = BCM5325_DEVICE_ID; -- else -+ -+ val = b53_phy_read16(dev->ds, 0, MII_PHYSID1); -+ phy_id = (val & 0xffff) << 16; -+ val = b53_phy_read16(dev->ds, 0, MII_PHYSID2); -+ phy_id |= (val & 0xfff0); -+ -+ if (phy_id == 0x00406330) -+ dev->variant_id = B53_VARIANT_5325M; -+ else if (phy_id == 0x0143bc30) -+ dev->variant_id = B53_VARIANT_5325E; -+ } else { - dev->chip_id = BCM5365_DEVICE_ID; -+ } - break; - case BCM5389_DEVICE_ID: - case BCM5395_DEVICE_ID: ---- a/drivers/net/dsa/b53/b53_priv.h -+++ b/drivers/net/dsa/b53/b53_priv.h -@@ -84,6 +84,12 @@ enum { - BCM53134_DEVICE_ID = 0x5075, - }; - -+enum b53_variant_id { -+ B53_VARIANT_NONE = 0, -+ B53_VARIANT_5325E, -+ B53_VARIANT_5325M, -+}; -+ - struct b53_pcs { - struct phylink_pcs pcs; - struct b53_device *dev; -@@ -118,6 +124,7 @@ struct b53_device { - - /* chip specific data */ - u32 chip_id; -+ enum b53_variant_id variant_id; - u8 core_rev; - u8 vta_regs[3]; - u8 duplex_reg; -@@ -165,6 +172,18 @@ static inline int is5325(struct b53_devi - return dev->chip_id == BCM5325_DEVICE_ID; - } - -+static inline int is5325e(struct b53_device *dev) -+{ -+ return is5325(dev) && -+ dev->variant_id == B53_VARIANT_5325E; -+} -+ -+static inline int is5325m(struct b53_device *dev) -+{ -+ return is5325(dev) && -+ dev->variant_id == B53_VARIANT_5325M; -+} -+ - static inline int is5365(struct b53_device *dev) - { - #ifdef CONFIG_BCM47XX diff --git a/target/linux/generic/backport-6.18/611-04-v6.17-net-dsa-b53-add-support-for-FDB-operations-on-5325-5365.patch b/target/linux/generic/backport-6.18/611-04-v6.17-net-dsa-b53-add-support-for-FDB-operations-on-5325-5365.patch deleted file mode 100644 index 9de73815da..0000000000 --- a/target/linux/generic/backport-6.18/611-04-v6.17-net-dsa-b53-add-support-for-FDB-operations-on-5325-5365.patch +++ /dev/null @@ -1,250 +0,0 @@ -From c45655386e532c85ff1d679fc2aa40b3aaff9916 Mon Sep 17 00:00:00 2001 -From: Florian Fainelli -Date: Sat, 14 Jun 2025 09:59:51 +0200 -Subject: [PATCH] net: dsa: b53: add support for FDB operations on 5325/5365 -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -BCM5325 and BCM5365 are part of a much older generation of switches which, -due to their limited number of ports and VLAN entries (up to 256) allowed -a single 64-bit register to hold a full ARL entry. -This requires a little bit of massaging when reading, writing and -converting ARL entries in both directions. - -Signed-off-by: Florian Fainelli -Signed-off-by: Álvaro Fernández Rojas -Link: https://patch.msgid.link/20250614080000.1884236-6-noltari@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/dsa/b53/b53_common.c | 101 +++++++++++++++++++++++++------ - drivers/net/dsa/b53/b53_priv.h | 29 +++++++++ - drivers/net/dsa/b53/b53_regs.h | 7 ++- - 3 files changed, 115 insertions(+), 22 deletions(-) - ---- a/drivers/net/dsa/b53/b53_common.c -+++ b/drivers/net/dsa/b53/b53_common.c -@@ -1821,6 +1821,45 @@ static int b53_arl_read(struct b53_devic - return *idx >= dev->num_arl_bins ? -ENOSPC : -ENOENT; - } - -+static int b53_arl_read_25(struct b53_device *dev, u64 mac, -+ u16 vid, struct b53_arl_entry *ent, u8 *idx) -+{ -+ DECLARE_BITMAP(free_bins, B53_ARLTBL_MAX_BIN_ENTRIES); -+ unsigned int i; -+ int ret; -+ -+ ret = b53_arl_op_wait(dev); -+ if (ret) -+ return ret; -+ -+ bitmap_zero(free_bins, dev->num_arl_bins); -+ -+ /* Read the bins */ -+ for (i = 0; i < dev->num_arl_bins; i++) { -+ u64 mac_vid; -+ -+ b53_read64(dev, B53_ARLIO_PAGE, -+ B53_ARLTBL_MAC_VID_ENTRY(i), &mac_vid); -+ -+ b53_arl_to_entry_25(ent, mac_vid); -+ -+ if (!(mac_vid & ARLTBL_VALID_25)) { -+ set_bit(i, free_bins); -+ continue; -+ } -+ if ((mac_vid & ARLTBL_MAC_MASK) != mac) -+ continue; -+ if (dev->vlan_enabled && -+ ((mac_vid >> ARLTBL_VID_S_65) & ARLTBL_VID_MASK_25) != vid) -+ continue; -+ *idx = i; -+ return 0; -+ } -+ -+ *idx = find_first_bit(free_bins, dev->num_arl_bins); -+ return *idx >= dev->num_arl_bins ? -ENOSPC : -ENOENT; -+} -+ - static int b53_arl_op(struct b53_device *dev, int op, int port, - const unsigned char *addr, u16 vid, bool is_valid) - { -@@ -1843,7 +1882,10 @@ static int b53_arl_op(struct b53_device - if (ret) - return ret; - -- ret = b53_arl_read(dev, mac, vid, &ent, &idx); -+ if (is5325(dev) || is5365(dev)) -+ ret = b53_arl_read_25(dev, mac, vid, &ent, &idx); -+ else -+ ret = b53_arl_read(dev, mac, vid, &ent, &idx); - - /* If this is a read, just finish now */ - if (op) -@@ -1887,12 +1929,17 @@ static int b53_arl_op(struct b53_device - ent.is_static = true; - ent.is_age = false; - memcpy(ent.mac, addr, ETH_ALEN); -- b53_arl_from_entry(&mac_vid, &fwd_entry, &ent); -+ if (is5325(dev) || is5365(dev)) -+ b53_arl_from_entry_25(&mac_vid, &ent); -+ else -+ b53_arl_from_entry(&mac_vid, &fwd_entry, &ent); - - b53_write64(dev, B53_ARLIO_PAGE, - B53_ARLTBL_MAC_VID_ENTRY(idx), mac_vid); -- b53_write32(dev, B53_ARLIO_PAGE, -- B53_ARLTBL_DATA_ENTRY(idx), fwd_entry); -+ -+ if (!is5325(dev) && !is5365(dev)) -+ b53_write32(dev, B53_ARLIO_PAGE, -+ B53_ARLTBL_DATA_ENTRY(idx), fwd_entry); - - return b53_arl_rw_op(dev, 0); - } -@@ -1904,12 +1951,6 @@ int b53_fdb_add(struct dsa_switch *ds, i - struct b53_device *priv = ds->priv; - int ret; - -- /* 5325 and 5365 require some more massaging, but could -- * be supported eventually -- */ -- if (is5325(priv) || is5365(priv)) -- return -EOPNOTSUPP; -- - mutex_lock(&priv->arl_mutex); - ret = b53_arl_op(priv, 0, port, addr, vid, true); - mutex_unlock(&priv->arl_mutex); -@@ -1936,10 +1977,15 @@ EXPORT_SYMBOL(b53_fdb_del); - static int b53_arl_search_wait(struct b53_device *dev) - { - unsigned int timeout = 1000; -- u8 reg; -+ u8 reg, offset; -+ -+ if (is5325(dev) || is5365(dev)) -+ offset = B53_ARL_SRCH_CTL_25; -+ else -+ offset = B53_ARL_SRCH_CTL; - - do { -- b53_read8(dev, B53_ARLIO_PAGE, B53_ARL_SRCH_CTL, ®); -+ b53_read8(dev, B53_ARLIO_PAGE, offset, ®); - if (!(reg & ARL_SRCH_STDN)) - return -ENOENT; - -@@ -1956,13 +2002,24 @@ static void b53_arl_search_rd(struct b53 - struct b53_arl_entry *ent) - { - u64 mac_vid; -- u32 fwd_entry; - -- b53_read64(dev, B53_ARLIO_PAGE, -- B53_ARL_SRCH_RSTL_MACVID(idx), &mac_vid); -- b53_read32(dev, B53_ARLIO_PAGE, -- B53_ARL_SRCH_RSTL(idx), &fwd_entry); -- b53_arl_to_entry(ent, mac_vid, fwd_entry); -+ if (is5325(dev)) { -+ b53_read64(dev, B53_ARLIO_PAGE, B53_ARL_SRCH_RSTL_0_MACVID_25, -+ &mac_vid); -+ b53_arl_to_entry_25(ent, mac_vid); -+ } else if (is5365(dev)) { -+ b53_read64(dev, B53_ARLIO_PAGE, B53_ARL_SRCH_RSTL_0_MACVID_65, -+ &mac_vid); -+ b53_arl_to_entry_25(ent, mac_vid); -+ } else { -+ u32 fwd_entry; -+ -+ b53_read64(dev, B53_ARLIO_PAGE, B53_ARL_SRCH_RSTL_MACVID(idx), -+ &mac_vid); -+ b53_read32(dev, B53_ARLIO_PAGE, B53_ARL_SRCH_RSTL(idx), -+ &fwd_entry); -+ b53_arl_to_entry(ent, mac_vid, fwd_entry); -+ } - } - - static int b53_fdb_copy(int port, const struct b53_arl_entry *ent, -@@ -1986,14 +2043,20 @@ int b53_fdb_dump(struct dsa_switch *ds, - struct b53_device *priv = ds->priv; - struct b53_arl_entry results[2]; - unsigned int count = 0; -+ u8 offset; - int ret; - u8 reg; - - mutex_lock(&priv->arl_mutex); - -+ if (is5325(priv) || is5365(priv)) -+ offset = B53_ARL_SRCH_CTL_25; -+ else -+ offset = B53_ARL_SRCH_CTL; -+ - /* Start search operation */ - reg = ARL_SRCH_STDN; -- b53_write8(priv, B53_ARLIO_PAGE, B53_ARL_SRCH_CTL, reg); -+ b53_write8(priv, offset, B53_ARL_SRCH_CTL, reg); - - do { - ret = b53_arl_search_wait(priv); ---- a/drivers/net/dsa/b53/b53_priv.h -+++ b/drivers/net/dsa/b53/b53_priv.h -@@ -317,6 +317,19 @@ static inline void b53_arl_to_entry(stru - ent->vid = mac_vid >> ARLTBL_VID_S; - } - -+static inline void b53_arl_to_entry_25(struct b53_arl_entry *ent, -+ u64 mac_vid) -+{ -+ memset(ent, 0, sizeof(*ent)); -+ ent->port = (mac_vid >> ARLTBL_DATA_PORT_ID_S_25) & -+ ARLTBL_DATA_PORT_ID_MASK_25; -+ ent->is_valid = !!(mac_vid & ARLTBL_VALID_25); -+ ent->is_age = !!(mac_vid & ARLTBL_AGE_25); -+ ent->is_static = !!(mac_vid & ARLTBL_STATIC_25); -+ u64_to_ether_addr(mac_vid, ent->mac); -+ ent->vid = mac_vid >> ARLTBL_VID_S_65; -+} -+ - static inline void b53_arl_from_entry(u64 *mac_vid, u32 *fwd_entry, - const struct b53_arl_entry *ent) - { -@@ -331,6 +344,22 @@ static inline void b53_arl_from_entry(u6 - *fwd_entry |= ARLTBL_AGE; - } - -+static inline void b53_arl_from_entry_25(u64 *mac_vid, -+ const struct b53_arl_entry *ent) -+{ -+ *mac_vid = ether_addr_to_u64(ent->mac); -+ *mac_vid |= (u64)(ent->port & ARLTBL_DATA_PORT_ID_MASK_25) << -+ ARLTBL_DATA_PORT_ID_S_25; -+ *mac_vid |= (u64)(ent->vid & ARLTBL_VID_MASK_25) << -+ ARLTBL_VID_S_65; -+ if (ent->is_valid) -+ *mac_vid |= ARLTBL_VALID_25; -+ if (ent->is_static) -+ *mac_vid |= ARLTBL_STATIC_25; -+ if (ent->is_age) -+ *mac_vid |= ARLTBL_AGE_25; -+} -+ - #ifdef CONFIG_BCM47XX - - #include ---- a/drivers/net/dsa/b53/b53_regs.h -+++ b/drivers/net/dsa/b53/b53_regs.h -@@ -328,9 +328,10 @@ - #define ARLTBL_VID_MASK 0xfff - #define ARLTBL_DATA_PORT_ID_S_25 48 - #define ARLTBL_DATA_PORT_ID_MASK_25 0xf --#define ARLTBL_AGE_25 BIT(61) --#define ARLTBL_STATIC_25 BIT(62) --#define ARLTBL_VALID_25 BIT(63) -+#define ARLTBL_VID_S_65 53 -+#define ARLTBL_AGE_25 BIT_ULL(61) -+#define ARLTBL_STATIC_25 BIT_ULL(62) -+#define ARLTBL_VALID_25 BIT_ULL(63) - - /* ARL Table Data Entry N Registers (32 bit) */ - #define B53_ARLTBL_DATA_ENTRY(n) ((0x10 * (n)) + 0x18) diff --git a/target/linux/generic/backport-6.18/611-05-v6.17-net-dsa-b53-prevent-FAST_AGE-access-on-BCM5325.patch b/target/linux/generic/backport-6.18/611-05-v6.17-net-dsa-b53-prevent-FAST_AGE-access-on-BCM5325.patch deleted file mode 100644 index 7397e3323c..0000000000 --- a/target/linux/generic/backport-6.18/611-05-v6.17-net-dsa-b53-prevent-FAST_AGE-access-on-BCM5325.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 9b6c767c312b4709e9aeb2314a6b47863e7fb72d Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= -Date: Sat, 14 Jun 2025 09:59:52 +0200 -Subject: [PATCH] net: dsa: b53: prevent FAST_AGE access on BCM5325 -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -BCM5325 doesn't implement FAST_AGE registers so we should avoid reading or -writing them. - -Signed-off-by: Álvaro Fernández Rojas -Reviewed-by: Florian Fainelli -Link: https://patch.msgid.link/20250614080000.1884236-7-noltari@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/dsa/b53/b53_common.c | 9 +++++++++ - 1 file changed, 9 insertions(+) - ---- a/drivers/net/dsa/b53/b53_common.c -+++ b/drivers/net/dsa/b53/b53_common.c -@@ -492,6 +492,9 @@ static int b53_flush_arl(struct b53_devi - { - unsigned int i; - -+ if (is5325(dev)) -+ return 0; -+ - b53_write8(dev, B53_CTRL_PAGE, B53_FAST_AGE_CTRL, - FAST_AGE_DONE | FAST_AGE_DYNAMIC | mask); - -@@ -516,6 +519,9 @@ out: - - static int b53_fast_age_port(struct b53_device *dev, int port) - { -+ if (is5325(dev)) -+ return 0; -+ - b53_write8(dev, B53_CTRL_PAGE, B53_FAST_AGE_PORT_CTRL, port); - - return b53_flush_arl(dev, FAST_AGE_PORT); -@@ -523,6 +529,9 @@ static int b53_fast_age_port(struct b53_ - - static int b53_fast_age_vlan(struct b53_device *dev, u16 vid) - { -+ if (is5325(dev)) -+ return 0; -+ - b53_write16(dev, B53_CTRL_PAGE, B53_FAST_AGE_VID_CTRL, vid); - - return b53_flush_arl(dev, FAST_AGE_VLAN); diff --git a/target/linux/generic/backport-6.18/611-06-v6.17-net-dsa-b53-prevent-BRCM_HDR-access-on-older-devices.patch b/target/linux/generic/backport-6.18/611-06-v6.17-net-dsa-b53-prevent-BRCM_HDR-access-on-older-devices.patch deleted file mode 100644 index 6ea836734a..0000000000 --- a/target/linux/generic/backport-6.18/611-06-v6.17-net-dsa-b53-prevent-BRCM_HDR-access-on-older-devices.patch +++ /dev/null @@ -1,33 +0,0 @@ -From e17813968b08b1b09bf80699223dea48851cbd07 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= -Date: Sat, 14 Jun 2025 09:59:56 +0200 -Subject: [PATCH] net: dsa: b53: prevent BRCM_HDR access on older devices -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Older switches don't implement BRCM_HDR register so we should avoid -reading or writing it. - -Reviewed-by: Florian Fainelli -Signed-off-by: Álvaro Fernández Rojas -Link: https://patch.msgid.link/20250614080000.1884236-11-noltari@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/dsa/b53/b53_common.c | 5 +++++ - 1 file changed, 5 insertions(+) - ---- a/drivers/net/dsa/b53/b53_common.c -+++ b/drivers/net/dsa/b53/b53_common.c -@@ -747,6 +747,11 @@ void b53_brcm_hdr_setup(struct dsa_switc - hdr_ctl |= GC_FRM_MGMT_PORT_M; - b53_write8(dev, B53_MGMT_PAGE, B53_GLOBAL_CONFIG, hdr_ctl); - -+ /* B53_BRCM_HDR not present on devices with legacy tags */ -+ if (dev->tag_protocol == DSA_TAG_PROTO_BRCM_LEGACY || -+ dev->tag_protocol == DSA_TAG_PROTO_BRCM_LEGACY_FCS) -+ return; -+ - /* Enable Broadcom tags for IMP port */ - b53_read8(dev, B53_MGMT_PAGE, B53_BRCM_HDR, &hdr_ctl); - if (tag_en) diff --git a/target/linux/generic/backport-6.18/611-07-v6.17-net-dsa-b53-fix-unicast-multicast-flooding-on-BCM5325.patch b/target/linux/generic/backport-6.18/611-07-v6.17-net-dsa-b53-fix-unicast-multicast-flooding-on-BCM5325.patch deleted file mode 100644 index 6b9c86ed0c..0000000000 --- a/target/linux/generic/backport-6.18/611-07-v6.17-net-dsa-b53-fix-unicast-multicast-flooding-on-BCM5325.patch +++ /dev/null @@ -1,128 +0,0 @@ -From 651c9e71ffe44e99b5a9b011271c2117f0353b32 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= -Date: Sat, 14 Jun 2025 09:59:58 +0200 -Subject: [PATCH] net: dsa: b53: fix unicast/multicast flooding on BCM5325 -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -BCM5325 doesn't implement UC_FLOOD_MASK, MC_FLOOD_MASK and IPMC_FLOOD_MASK -registers. -This has to be handled differently with other pages and registers. - -Signed-off-by: Álvaro Fernández Rojas -Reviewed-by: Florian Fainelli -Link: https://patch.msgid.link/20250614080000.1884236-13-noltari@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/dsa/b53/b53_common.c | 60 ++++++++++++++++++++++---------- - drivers/net/dsa/b53/b53_regs.h | 13 +++++++ - 2 files changed, 55 insertions(+), 18 deletions(-) - ---- a/drivers/net/dsa/b53/b53_common.c -+++ b/drivers/net/dsa/b53/b53_common.c -@@ -564,12 +564,24 @@ static void b53_port_set_ucast_flood(str - { - u16 uc; - -- b53_read16(dev, B53_CTRL_PAGE, B53_UC_FLOOD_MASK, &uc); -- if (unicast) -- uc |= BIT(port); -- else -- uc &= ~BIT(port); -- b53_write16(dev, B53_CTRL_PAGE, B53_UC_FLOOD_MASK, uc); -+ if (is5325(dev)) { -+ if (port == B53_CPU_PORT_25) -+ port = B53_CPU_PORT; -+ -+ b53_read16(dev, B53_IEEE_PAGE, B53_IEEE_UCAST_DLF, &uc); -+ if (unicast) -+ uc |= BIT(port) | B53_IEEE_UCAST_DROP_EN; -+ else -+ uc &= ~BIT(port); -+ b53_write16(dev, B53_IEEE_PAGE, B53_IEEE_UCAST_DLF, uc); -+ } else { -+ b53_read16(dev, B53_CTRL_PAGE, B53_UC_FLOOD_MASK, &uc); -+ if (unicast) -+ uc |= BIT(port); -+ else -+ uc &= ~BIT(port); -+ b53_write16(dev, B53_CTRL_PAGE, B53_UC_FLOOD_MASK, uc); -+ } - } - - static void b53_port_set_mcast_flood(struct b53_device *dev, int port, -@@ -577,19 +589,31 @@ static void b53_port_set_mcast_flood(str - { - u16 mc; - -- b53_read16(dev, B53_CTRL_PAGE, B53_MC_FLOOD_MASK, &mc); -- if (multicast) -- mc |= BIT(port); -- else -- mc &= ~BIT(port); -- b53_write16(dev, B53_CTRL_PAGE, B53_MC_FLOOD_MASK, mc); -- -- b53_read16(dev, B53_CTRL_PAGE, B53_IPMC_FLOOD_MASK, &mc); -- if (multicast) -- mc |= BIT(port); -- else -- mc &= ~BIT(port); -- b53_write16(dev, B53_CTRL_PAGE, B53_IPMC_FLOOD_MASK, mc); -+ if (is5325(dev)) { -+ if (port == B53_CPU_PORT_25) -+ port = B53_CPU_PORT; -+ -+ b53_read16(dev, B53_IEEE_PAGE, B53_IEEE_MCAST_DLF, &mc); -+ if (multicast) -+ mc |= BIT(port) | B53_IEEE_MCAST_DROP_EN; -+ else -+ mc &= ~BIT(port); -+ b53_write16(dev, B53_IEEE_PAGE, B53_IEEE_MCAST_DLF, mc); -+ } else { -+ b53_read16(dev, B53_CTRL_PAGE, B53_MC_FLOOD_MASK, &mc); -+ if (multicast) -+ mc |= BIT(port); -+ else -+ mc &= ~BIT(port); -+ b53_write16(dev, B53_CTRL_PAGE, B53_MC_FLOOD_MASK, mc); -+ -+ b53_read16(dev, B53_CTRL_PAGE, B53_IPMC_FLOOD_MASK, &mc); -+ if (multicast) -+ mc |= BIT(port); -+ else -+ mc &= ~BIT(port); -+ b53_write16(dev, B53_CTRL_PAGE, B53_IPMC_FLOOD_MASK, mc); -+ } - } - - static void b53_port_set_learning(struct b53_device *dev, int port, ---- a/drivers/net/dsa/b53/b53_regs.h -+++ b/drivers/net/dsa/b53/b53_regs.h -@@ -29,6 +29,7 @@ - #define B53_ARLIO_PAGE 0x05 /* ARL Access */ - #define B53_FRAMEBUF_PAGE 0x06 /* Management frame access */ - #define B53_MEM_ACCESS_PAGE 0x08 /* Memory access */ -+#define B53_IEEE_PAGE 0x0a /* IEEE 802.1X */ - - /* PHY Registers */ - #define B53_PORT_MII_PAGE(i) (0x10 + (i)) /* Port i MII Registers */ -@@ -371,6 +372,18 @@ - #define B53_ARL_SRCH_RSTL(x) (B53_ARL_SRCH_RSTL_0 + ((x) * 0x10)) - - /************************************************************************* -+ * IEEE 802.1X Registers -+ *************************************************************************/ -+ -+/* Multicast DLF Drop Control register (16 bit) */ -+#define B53_IEEE_MCAST_DLF 0x94 -+#define B53_IEEE_MCAST_DROP_EN BIT(11) -+ -+/* Unicast DLF Drop Control register (16 bit) */ -+#define B53_IEEE_UCAST_DLF 0x96 -+#define B53_IEEE_UCAST_DROP_EN BIT(11) -+ -+/************************************************************************* - * Port VLAN Registers - *************************************************************************/ - diff --git a/target/linux/generic/backport-6.18/611-08-v6.18-net-dsa-b53-Add-phy_enable-phy_disable-methods.patch b/target/linux/generic/backport-6.18/611-08-v6.18-net-dsa-b53-Add-phy_enable-phy_disable-methods.patch deleted file mode 100644 index 14106e3dd2..0000000000 --- a/target/linux/generic/backport-6.18/611-08-v6.18-net-dsa-b53-Add-phy_enable-phy_disable-methods.patch +++ /dev/null @@ -1,50 +0,0 @@ -From be7a79145d85af1a9d65a45560b9243b13a67782 Mon Sep 17 00:00:00 2001 -From: Kyle Hendry -Date: Wed, 23 Jul 2025 20:52:40 -0700 -Subject: [PATCH] net: dsa: b53: Add phy_enable(), phy_disable() methods - -Add phy enable/disable to b53 ops to be called when -enabling/disabling ports. - -Signed-off-by: Kyle Hendry -Reviewed-by: Florian Fainelli -Link: https://patch.msgid.link/20250724035300.20497-2-kylehendrydev@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/dsa/b53/b53_common.c | 6 ++++++ - drivers/net/dsa/b53/b53_priv.h | 2 ++ - 2 files changed, 8 insertions(+) - ---- a/drivers/net/dsa/b53/b53_common.c -+++ b/drivers/net/dsa/b53/b53_common.c -@@ -689,6 +689,9 @@ int b53_enable_port(struct dsa_switch *d - - cpu_port = dsa_to_port(ds, port)->cpu_dp->index; - -+ if (dev->ops->phy_enable) -+ dev->ops->phy_enable(dev, port); -+ - if (dev->ops->irq_enable) - ret = dev->ops->irq_enable(dev, port); - if (ret) -@@ -727,6 +730,9 @@ void b53_disable_port(struct dsa_switch - reg |= PORT_CTRL_RX_DISABLE | PORT_CTRL_TX_DISABLE; - b53_write8(dev, B53_CTRL_PAGE, B53_PORT_CTRL(port), reg); - -+ if (dev->ops->phy_disable) -+ dev->ops->phy_disable(dev, port); -+ - if (dev->ops->irq_disable) - dev->ops->irq_disable(dev, port); - } ---- a/drivers/net/dsa/b53/b53_priv.h -+++ b/drivers/net/dsa/b53/b53_priv.h -@@ -45,6 +45,8 @@ struct b53_io_ops { - int (*phy_write16)(struct b53_device *dev, int addr, int reg, u16 value); - int (*irq_enable)(struct b53_device *dev, int port); - void (*irq_disable)(struct b53_device *dev, int port); -+ void (*phy_enable)(struct b53_device *dev, int port); -+ void (*phy_disable)(struct b53_device *dev, int port); - void (*phylink_get_caps)(struct b53_device *dev, int port, - struct phylink_config *config); - struct phylink_pcs *(*phylink_mac_select_pcs)(struct b53_device *dev, diff --git a/target/linux/generic/backport-6.18/611-09-v6.18-net-dsa-b53-Define-chip-IDs-for-more-bcm63xx-SoCs.patch b/target/linux/generic/backport-6.18/611-09-v6.18-net-dsa-b53-Define-chip-IDs-for-more-bcm63xx-SoCs.patch deleted file mode 100644 index 0e039168ad..0000000000 --- a/target/linux/generic/backport-6.18/611-09-v6.18-net-dsa-b53-Define-chip-IDs-for-more-bcm63xx-SoCs.patch +++ /dev/null @@ -1,124 +0,0 @@ -From fcf02a462fab52fbfcb24e617dd940745afd0dff Mon Sep 17 00:00:00 2001 -From: Kyle Hendry -Date: Wed, 23 Jul 2025 20:52:42 -0700 -Subject: [PATCH] net: dsa: b53: Define chip IDs for more bcm63xx SoCs - -Add defines for bcm6318, bcm6328, bcm6362, bcm6368 chip IDs, -update tables and switch init. - -Signed-off-by: Kyle Hendry -Reviewed-by: Florian Fainelli -Link: https://patch.msgid.link/20250724035300.20497-4-kylehendrydev@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/dsa/b53/b53_common.c | 21 ++++++--------------- - drivers/net/dsa/b53/b53_mmap.c | 8 ++++---- - drivers/net/dsa/b53/b53_priv.h | 13 +++++++++++-- - 3 files changed, 21 insertions(+), 21 deletions(-) - ---- a/drivers/net/dsa/b53/b53_common.c -+++ b/drivers/net/dsa/b53/b53_common.c -@@ -1419,7 +1419,7 @@ static void b53_adjust_63xx_rgmii(struct - b53_read8(dev, B53_CTRL_PAGE, B53_RGMII_CTRL_P(port), &rgmii_ctrl); - rgmii_ctrl &= ~(RGMII_CTRL_DLL_RXC | RGMII_CTRL_DLL_TXC); - -- if (is63268(dev)) -+ if (is6318_268(dev)) - rgmii_ctrl |= RGMII_CTRL_MII_OVERRIDE; - - rgmii_ctrl |= RGMII_CTRL_ENABLE_GMII; -@@ -2804,19 +2804,6 @@ static const struct b53_chip_data b53_sw - .jumbo_size_reg = B53_JUMBO_MAX_SIZE_63XX, - }, - { -- .chip_id = BCM63268_DEVICE_ID, -- .dev_name = "BCM63268", -- .vlans = 4096, -- .enabled_ports = 0, /* pdata must provide them */ -- .arl_bins = 4, -- .arl_buckets = 1024, -- .imp_port = 8, -- .vta_regs = B53_VTA_REGS_63XX, -- .duplex_reg = B53_DUPLEX_STAT_63XX, -- .jumbo_pm_reg = B53_JUMBO_PORT_MASK_63XX, -- .jumbo_size_reg = B53_JUMBO_MAX_SIZE_63XX, -- }, -- { - .chip_id = BCM53010_DEVICE_ID, - .dev_name = "BCM53010", - .vlans = 4096, -@@ -2965,13 +2952,17 @@ static const struct b53_chip_data b53_sw - - static int b53_switch_init(struct b53_device *dev) - { -+ u32 chip_id = dev->chip_id; - unsigned int i; - int ret; - -+ if (is63xx(dev)) -+ chip_id = BCM63XX_DEVICE_ID; -+ - for (i = 0; i < ARRAY_SIZE(b53_switch_chips); i++) { - const struct b53_chip_data *chip = &b53_switch_chips[i]; - -- if (chip->chip_id == dev->chip_id) { -+ if (chip->chip_id == chip_id) { - if (!dev->enabled_ports) - dev->enabled_ports = chip->enabled_ports; - dev->name = chip->dev_name; ---- a/drivers/net/dsa/b53/b53_mmap.c -+++ b/drivers/net/dsa/b53/b53_mmap.c -@@ -348,16 +348,16 @@ static const struct of_device_id b53_mma - .data = (void *)BCM63XX_DEVICE_ID, - }, { - .compatible = "brcm,bcm6318-switch", -- .data = (void *)BCM63268_DEVICE_ID, -+ .data = (void *)BCM6318_DEVICE_ID, - }, { - .compatible = "brcm,bcm6328-switch", -- .data = (void *)BCM63XX_DEVICE_ID, -+ .data = (void *)BCM6328_DEVICE_ID, - }, { - .compatible = "brcm,bcm6362-switch", -- .data = (void *)BCM63XX_DEVICE_ID, -+ .data = (void *)BCM6362_DEVICE_ID, - }, { - .compatible = "brcm,bcm6368-switch", -- .data = (void *)BCM63XX_DEVICE_ID, -+ .data = (void *)BCM6368_DEVICE_ID, - }, { - .compatible = "brcm,bcm63268-switch", - .data = (void *)BCM63268_DEVICE_ID, ---- a/drivers/net/dsa/b53/b53_priv.h -+++ b/drivers/net/dsa/b53/b53_priv.h -@@ -73,6 +73,10 @@ enum { - BCM53125_DEVICE_ID = 0x53125, - BCM53128_DEVICE_ID = 0x53128, - BCM63XX_DEVICE_ID = 0x6300, -+ BCM6318_DEVICE_ID = 0x6318, -+ BCM6328_DEVICE_ID = 0x6328, -+ BCM6362_DEVICE_ID = 0x6362, -+ BCM6368_DEVICE_ID = 0x6368, - BCM63268_DEVICE_ID = 0x63268, - BCM53010_DEVICE_ID = 0x53010, - BCM53011_DEVICE_ID = 0x53011, -@@ -220,12 +224,17 @@ static inline int is531x5(struct b53_dev - static inline int is63xx(struct b53_device *dev) - { - return dev->chip_id == BCM63XX_DEVICE_ID || -+ dev->chip_id == BCM6318_DEVICE_ID || -+ dev->chip_id == BCM6328_DEVICE_ID || -+ dev->chip_id == BCM6362_DEVICE_ID || -+ dev->chip_id == BCM6368_DEVICE_ID || - dev->chip_id == BCM63268_DEVICE_ID; - } - --static inline int is63268(struct b53_device *dev) -+static inline int is6318_268(struct b53_device *dev) - { -- return dev->chip_id == BCM63268_DEVICE_ID; -+ return dev->chip_id == BCM6318_DEVICE_ID || -+ dev->chip_id == BCM63268_DEVICE_ID; - } - - static inline int is5301x(struct b53_device *dev) diff --git a/target/linux/generic/backport-6.18/611-10-v6.18-net-dsa-b53-mmap-Add-syscon-reference-and-register-layout-for-bcm63268.patch b/target/linux/generic/backport-6.18/611-10-v6.18-net-dsa-b53-mmap-Add-syscon-reference-and-register-layout-for-bcm63268.patch deleted file mode 100644 index 92e540d384..0000000000 --- a/target/linux/generic/backport-6.18/611-10-v6.18-net-dsa-b53-mmap-Add-syscon-reference-and-register-layout-for-bcm63268.patch +++ /dev/null @@ -1,69 +0,0 @@ -From aed2aaa3c963f8aabbfa061a177022fee826ebfb Mon Sep 17 00:00:00 2001 -From: Kyle Hendry -Date: Wed, 23 Jul 2025 20:52:43 -0700 -Subject: [PATCH] net: dsa: b53: mmap: Add syscon reference and register layout - for bcm63268 - -On bcm63xx SoCs there are registers that control the PHYs in -the GPIO controller. Allow the b53 driver to access them -by passing in the syscon through the device tree. - -Add a structure to describe the ephy control register -and add register info for bcm63268. - -Signed-off-by: Kyle Hendry -Reviewed-by: Florian Fainelli -Link: https://patch.msgid.link/20250724035300.20497-5-kylehendrydev@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/dsa/b53/b53_mmap.c | 25 +++++++++++++++++++++++++ - 1 file changed, 25 insertions(+) - ---- a/drivers/net/dsa/b53/b53_mmap.c -+++ b/drivers/net/dsa/b53/b53_mmap.c -@@ -21,13 +21,32 @@ - #include - #include - #include -+#include - #include - #include - - #include "b53_priv.h" - -+struct b53_phy_info { -+ u32 ephy_enable_mask; -+ u32 ephy_port_mask; -+ u32 ephy_bias_bit; -+ const u32 *ephy_offset; -+}; -+ - struct b53_mmap_priv { - void __iomem *regs; -+ struct regmap *gpio_ctrl; -+ const struct b53_phy_info *phy_info; -+}; -+ -+static const u32 bcm63268_ephy_offsets[] = {4, 9, 14}; -+ -+static const struct b53_phy_info bcm63268_ephy_info = { -+ .ephy_enable_mask = GENMASK(4, 0), -+ .ephy_port_mask = GENMASK((ARRAY_SIZE(bcm63268_ephy_offsets) - 1), 0), -+ .ephy_bias_bit = 24, -+ .ephy_offset = bcm63268_ephy_offsets, - }; - - static int b53_mmap_read8(struct b53_device *dev, u8 page, u8 reg, u8 *val) -@@ -313,6 +332,12 @@ static int b53_mmap_probe(struct platfor - - priv->regs = pdata->regs; - -+ priv->gpio_ctrl = syscon_regmap_lookup_by_phandle(np, "brcm,gpio-ctrl"); -+ if (!IS_ERR(priv->gpio_ctrl)) { -+ if (pdata->chip_id == BCM63268_DEVICE_ID) -+ priv->phy_info = &bcm63268_ephy_info; -+ } -+ - dev = b53_switch_alloc(&pdev->dev, &b53_mmap_ops, priv); - if (!dev) - return -ENOMEM; diff --git a/target/linux/generic/backport-6.18/611-11-v6.18-net-dsa-b53-mmap-Add-register-layout-for-bcm6318.patch b/target/linux/generic/backport-6.18/611-11-v6.18-net-dsa-b53-mmap-Add-register-layout-for-bcm6318.patch deleted file mode 100644 index f6c1cbaf01..0000000000 --- a/target/linux/generic/backport-6.18/611-11-v6.18-net-dsa-b53-mmap-Add-register-layout-for-bcm6318.patch +++ /dev/null @@ -1,47 +0,0 @@ -From c251304ab021ff21c77e83e0babcb9eb76f8787a Mon Sep 17 00:00:00 2001 -From: Kyle Hendry -Date: Wed, 23 Jul 2025 20:52:44 -0700 -Subject: [PATCH] net: dsa: b53: mmap: Add register layout for bcm6318 - -Add ephy register info for bcm6318, which also applies to -bcm6328 and bcm6362. - -Signed-off-by: Kyle Hendry -Reviewed-by: Florian Fainelli -Link: https://patch.msgid.link/20250724035300.20497-6-kylehendrydev@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/dsa/b53/b53_mmap.c | 15 ++++++++++++++- - 1 file changed, 14 insertions(+), 1 deletion(-) - ---- a/drivers/net/dsa/b53/b53_mmap.c -+++ b/drivers/net/dsa/b53/b53_mmap.c -@@ -40,6 +40,15 @@ struct b53_mmap_priv { - const struct b53_phy_info *phy_info; - }; - -+static const u32 bcm6318_ephy_offsets[] = {4, 5, 6, 7}; -+ -+static const struct b53_phy_info bcm6318_ephy_info = { -+ .ephy_enable_mask = BIT(0) | BIT(4) | BIT(8) | BIT(12) | BIT(16), -+ .ephy_port_mask = GENMASK((ARRAY_SIZE(bcm6318_ephy_offsets) - 1), 0), -+ .ephy_bias_bit = 24, -+ .ephy_offset = bcm6318_ephy_offsets, -+}; -+ - static const u32 bcm63268_ephy_offsets[] = {4, 9, 14}; - - static const struct b53_phy_info bcm63268_ephy_info = { -@@ -334,7 +343,11 @@ static int b53_mmap_probe(struct platfor - - priv->gpio_ctrl = syscon_regmap_lookup_by_phandle(np, "brcm,gpio-ctrl"); - if (!IS_ERR(priv->gpio_ctrl)) { -- if (pdata->chip_id == BCM63268_DEVICE_ID) -+ if (pdata->chip_id == BCM6318_DEVICE_ID || -+ pdata->chip_id == BCM6328_DEVICE_ID || -+ pdata->chip_id == BCM6362_DEVICE_ID) -+ priv->phy_info = &bcm6318_ephy_info; -+ else if (pdata->chip_id == BCM63268_DEVICE_ID) - priv->phy_info = &bcm63268_ephy_info; - } - diff --git a/target/linux/generic/backport-6.18/611-12-v6.18-net-dsa-b53-mmap-Add-register-layout-for-bcm6368.patch b/target/linux/generic/backport-6.18/611-12-v6.18-net-dsa-b53-mmap-Add-register-layout-for-bcm6368.patch deleted file mode 100644 index f703804a40..0000000000 --- a/target/linux/generic/backport-6.18/611-12-v6.18-net-dsa-b53-mmap-Add-register-layout-for-bcm6368.patch +++ /dev/null @@ -1,42 +0,0 @@ -From e8e13073dff7052b144d002bae2cfe9ddfa27e2a Mon Sep 17 00:00:00 2001 -From: Kyle Hendry -Date: Wed, 23 Jul 2025 20:52:45 -0700 -Subject: [PATCH] net: dsa: b53: mmap: Add register layout for bcm6368 - -Add ephy register info for bcm6368. - -Signed-off-by: Kyle Hendry -Reviewed-by: Florian Fainelli -Link: https://patch.msgid.link/20250724035300.20497-7-kylehendrydev@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/dsa/b53/b53_mmap.c | 11 +++++++++++ - 1 file changed, 11 insertions(+) - ---- a/drivers/net/dsa/b53/b53_mmap.c -+++ b/drivers/net/dsa/b53/b53_mmap.c -@@ -49,6 +49,15 @@ static const struct b53_phy_info bcm6318 - .ephy_offset = bcm6318_ephy_offsets, - }; - -+static const u32 bcm6368_ephy_offsets[] = {2, 3, 4, 5}; -+ -+static const struct b53_phy_info bcm6368_ephy_info = { -+ .ephy_enable_mask = BIT(0), -+ .ephy_port_mask = GENMASK((ARRAY_SIZE(bcm6368_ephy_offsets) - 1), 0), -+ .ephy_bias_bit = 0, -+ .ephy_offset = bcm6368_ephy_offsets, -+}; -+ - static const u32 bcm63268_ephy_offsets[] = {4, 9, 14}; - - static const struct b53_phy_info bcm63268_ephy_info = { -@@ -347,6 +356,8 @@ static int b53_mmap_probe(struct platfor - pdata->chip_id == BCM6328_DEVICE_ID || - pdata->chip_id == BCM6362_DEVICE_ID) - priv->phy_info = &bcm6318_ephy_info; -+ else if (pdata->chip_id == BCM6368_DEVICE_ID) -+ priv->phy_info = &bcm6368_ephy_info; - else if (pdata->chip_id == BCM63268_DEVICE_ID) - priv->phy_info = &bcm63268_ephy_info; - } diff --git a/target/linux/generic/backport-6.18/611-13-v6.18-net-dsa-b53-mmap-Implement-bcm63xx-ephy-power-control.patch b/target/linux/generic/backport-6.18/611-13-v6.18-net-dsa-b53-mmap-Implement-bcm63xx-ephy-power-control.patch deleted file mode 100644 index bf3aeb7047..0000000000 --- a/target/linux/generic/backport-6.18/611-13-v6.18-net-dsa-b53-mmap-Implement-bcm63xx-ephy-power-control.patch +++ /dev/null @@ -1,100 +0,0 @@ -From 5ac00023852d960528a0c1d10ae6c17893fc4113 Mon Sep 17 00:00:00 2001 -From: Kyle Hendry -Date: Wed, 23 Jul 2025 20:52:46 -0700 -Subject: [PATCH] net: dsa: b53: mmap: Implement bcm63xx ephy power control - -Implement the phy enable/disable calls for b53 mmap, and -set the power down registers in the ephy control register -appropriately. - -Signed-off-by: Kyle Hendry -Reviewed-by: Florian Fainelli -Link: https://patch.msgid.link/20250724035300.20497-8-kylehendrydev@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/dsa/b53/b53_mmap.c | 50 ++++++++++++++++++++++++++++++++++ - 1 file changed, 50 insertions(+) - ---- a/drivers/net/dsa/b53/b53_mmap.c -+++ b/drivers/net/dsa/b53/b53_mmap.c -@@ -24,9 +24,12 @@ - #include - #include - #include -+#include - - #include "b53_priv.h" - -+#define BCM63XX_EPHY_REG 0x3C -+ - struct b53_phy_info { - u32 ephy_enable_mask; - u32 ephy_port_mask; -@@ -38,6 +41,7 @@ struct b53_mmap_priv { - void __iomem *regs; - struct regmap *gpio_ctrl; - const struct b53_phy_info *phy_info; -+ u32 phys_enabled; - }; - - static const u32 bcm6318_ephy_offsets[] = {4, 5, 6, 7}; -@@ -266,6 +270,50 @@ static int b53_mmap_phy_write16(struct b - return -EIO; - } - -+static int bcm63xx_ephy_set(struct b53_device *dev, int port, bool enable) -+{ -+ struct b53_mmap_priv *priv = dev->priv; -+ const struct b53_phy_info *info = priv->phy_info; -+ struct regmap *gpio_ctrl = priv->gpio_ctrl; -+ u32 mask, val; -+ -+ if (enable) { -+ mask = (info->ephy_enable_mask << info->ephy_offset[port]) -+ | BIT(info->ephy_bias_bit); -+ val = 0; -+ } else { -+ mask = (info->ephy_enable_mask << info->ephy_offset[port]); -+ if (!((priv->phys_enabled & ~BIT(port)) & info->ephy_port_mask)) -+ mask |= BIT(info->ephy_bias_bit); -+ val = mask; -+ } -+ return regmap_update_bits(gpio_ctrl, BCM63XX_EPHY_REG, mask, val); -+} -+ -+static void b53_mmap_phy_enable(struct b53_device *dev, int port) -+{ -+ struct b53_mmap_priv *priv = dev->priv; -+ int ret = 0; -+ -+ if (priv->phy_info && (BIT(port) & priv->phy_info->ephy_port_mask)) -+ ret = bcm63xx_ephy_set(dev, port, true); -+ -+ if (!ret) -+ priv->phys_enabled |= BIT(port); -+} -+ -+static void b53_mmap_phy_disable(struct b53_device *dev, int port) -+{ -+ struct b53_mmap_priv *priv = dev->priv; -+ int ret = 0; -+ -+ if (priv->phy_info && (BIT(port) & priv->phy_info->ephy_port_mask)) -+ ret = bcm63xx_ephy_set(dev, port, false); -+ -+ if (!ret) -+ priv->phys_enabled &= ~BIT(port); -+} -+ - static const struct b53_io_ops b53_mmap_ops = { - .read8 = b53_mmap_read8, - .read16 = b53_mmap_read16, -@@ -279,6 +327,8 @@ static const struct b53_io_ops b53_mmap_ - .write64 = b53_mmap_write64, - .phy_read16 = b53_mmap_phy_read16, - .phy_write16 = b53_mmap_phy_write16, -+ .phy_enable = b53_mmap_phy_enable, -+ .phy_disable = b53_mmap_phy_disable, - }; - - static int b53_mmap_probe_of(struct platform_device *pdev, diff --git a/target/linux/generic/backport-6.18/611-14-v6.18-net-dsa-b53-mmap-Add-gphy-port-to-phy-info-for-bcm63268.patch b/target/linux/generic/backport-6.18/611-14-v6.18-net-dsa-b53-mmap-Add-gphy-port-to-phy-info-for-bcm63268.patch deleted file mode 100644 index 9aa99d234e..0000000000 --- a/target/linux/generic/backport-6.18/611-14-v6.18-net-dsa-b53-mmap-Add-gphy-port-to-phy-info-for-bcm63268.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 7f95f04fe1903a31b61085e3ab1b4730f9d72941 Mon Sep 17 00:00:00 2001 -From: Kyle Hendry -Date: Wed, 13 Aug 2025 17:25:27 -0700 -Subject: [PATCH] net: dsa: b53: mmap: Add gphy port to phy info for bcm63268 - -Add gphy mask to bcm63xx phy info struct and add data for bcm63268 - -Signed-off-by: Kyle Hendry -Reviewed-by: Florian Fainelli -Link: https://patch.msgid.link/20250814002530.5866-2-kylehendrydev@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/dsa/b53/b53_mmap.c | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/drivers/net/dsa/b53/b53_mmap.c -+++ b/drivers/net/dsa/b53/b53_mmap.c -@@ -31,6 +31,7 @@ - #define BCM63XX_EPHY_REG 0x3C - - struct b53_phy_info { -+ u32 gphy_port_mask; - u32 ephy_enable_mask; - u32 ephy_port_mask; - u32 ephy_bias_bit; -@@ -65,6 +66,7 @@ static const struct b53_phy_info bcm6368 - static const u32 bcm63268_ephy_offsets[] = {4, 9, 14}; - - static const struct b53_phy_info bcm63268_ephy_info = { -+ .gphy_port_mask = BIT(3), - .ephy_enable_mask = GENMASK(4, 0), - .ephy_port_mask = GENMASK((ARRAY_SIZE(bcm63268_ephy_offsets) - 1), 0), - .ephy_bias_bit = 24, diff --git a/target/linux/generic/backport-6.18/611-15-v6.18-net-dsa-b53-mmap-Implement-bcm63268-gphy-power-control.patch b/target/linux/generic/backport-6.18/611-15-v6.18-net-dsa-b53-mmap-Implement-bcm63268-gphy-power-control.patch deleted file mode 100644 index 8dda51e19e..0000000000 --- a/target/linux/generic/backport-6.18/611-15-v6.18-net-dsa-b53-mmap-Implement-bcm63268-gphy-power-control.patch +++ /dev/null @@ -1,77 +0,0 @@ -From 61730ac10ba90c52563861a0119504f6a9be9868 Mon Sep 17 00:00:00 2001 -From: Kyle Hendry -Date: Wed, 13 Aug 2025 17:25:28 -0700 -Subject: [PATCH] net: dsa: b53: mmap: Implement bcm63268 gphy power control - -Add check for gphy in enable/disable phy calls and set power bits -in gphy control register. - -Signed-off-by: Kyle Hendry -Reviewed-by: Florian Fainelli -Link: https://patch.msgid.link/20250814002530.5866-3-kylehendrydev@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/dsa/b53/b53_mmap.c | 33 +++++++++++++++++++++++++++++---- - 1 file changed, 29 insertions(+), 4 deletions(-) - ---- a/drivers/net/dsa/b53/b53_mmap.c -+++ b/drivers/net/dsa/b53/b53_mmap.c -@@ -29,6 +29,10 @@ - #include "b53_priv.h" - - #define BCM63XX_EPHY_REG 0x3C -+#define BCM63268_GPHY_REG 0x54 -+ -+#define GPHY_CTRL_LOW_PWR BIT(3) -+#define GPHY_CTRL_IDDQ_BIAS BIT(0) - - struct b53_phy_info { - u32 gphy_port_mask; -@@ -292,13 +296,30 @@ static int bcm63xx_ephy_set(struct b53_d - return regmap_update_bits(gpio_ctrl, BCM63XX_EPHY_REG, mask, val); - } - -+static int bcm63268_gphy_set(struct b53_device *dev, bool enable) -+{ -+ struct b53_mmap_priv *priv = dev->priv; -+ struct regmap *gpio_ctrl = priv->gpio_ctrl; -+ u32 mask = GPHY_CTRL_IDDQ_BIAS | GPHY_CTRL_LOW_PWR; -+ u32 val = 0; -+ -+ if (!enable) -+ val = mask; -+ -+ return regmap_update_bits(gpio_ctrl, BCM63268_GPHY_REG, mask, val); -+} -+ - static void b53_mmap_phy_enable(struct b53_device *dev, int port) - { - struct b53_mmap_priv *priv = dev->priv; - int ret = 0; - -- if (priv->phy_info && (BIT(port) & priv->phy_info->ephy_port_mask)) -- ret = bcm63xx_ephy_set(dev, port, true); -+ if (priv->phy_info) { -+ if (BIT(port) & priv->phy_info->ephy_port_mask) -+ ret = bcm63xx_ephy_set(dev, port, true); -+ else if (BIT(port) & priv->phy_info->gphy_port_mask) -+ ret = bcm63268_gphy_set(dev, true); -+ } - - if (!ret) - priv->phys_enabled |= BIT(port); -@@ -309,8 +330,12 @@ static void b53_mmap_phy_disable(struct - struct b53_mmap_priv *priv = dev->priv; - int ret = 0; - -- if (priv->phy_info && (BIT(port) & priv->phy_info->ephy_port_mask)) -- ret = bcm63xx_ephy_set(dev, port, false); -+ if (priv->phy_info) { -+ if (BIT(port) & priv->phy_info->ephy_port_mask) -+ ret = bcm63xx_ephy_set(dev, port, false); -+ else if (BIT(port) & priv->phy_info->gphy_port_mask) -+ ret = bcm63268_gphy_set(dev, false); -+ } - - if (!ret) - priv->phys_enabled &= ~BIT(port); diff --git a/target/linux/generic/backport-6.18/611-16-v6.18-net-dsa-b53-fix-reserved-register-access-in-b53_fdb_dump.patch b/target/linux/generic/backport-6.18/611-16-v6.18-net-dsa-b53-fix-reserved-register-access-in-b53_fdb_dump.patch deleted file mode 100644 index 5190cf908f..0000000000 --- a/target/linux/generic/backport-6.18/611-16-v6.18-net-dsa-b53-fix-reserved-register-access-in-b53_fdb_dump.patch +++ /dev/null @@ -1,72 +0,0 @@ -From 89eb9a62aed77b409663ba1eac152e8f758815b7 Mon Sep 17 00:00:00 2001 -From: Jonas Gorski -Date: Fri, 15 Aug 2025 22:18:09 +0200 -Subject: [PATCH] net: dsa: b53: fix reserved register access in b53_fdb_dump() - -When BCM5325 support was added in c45655386e53 ("net: dsa: b53: add -support for FDB operations on 5325/5365"), the register used for ARL access -was made conditional on the chip. - -But in b53_fdb_dump(), instead of the register argument the page -argument was replaced, causing it to write to a reserved page 0x50 on -!BCM5325*. Writing to this page seems to completely lock the switch up: - -[ 89.680000] b53-switch spi0.1 lan2: Link is Down -[ 89.680000] WARNING: CPU: 1 PID: 26 at drivers/net/phy/phy.c:1350 _phy_state_machine+0x1bc/0x454 -[ 89.720000] phy_check_link_status+0x0/0x114: returned: -5 -[ 89.730000] Modules linked in: nft_fib_inet nf_flow_table_inet nft_reject_ipv6 nft_reject_ipv4 nft_reject_inet nft_reject nft_redir nft_quota nft_numgen nft_nat nft_masq nft_log nft_limit nft_hash nft_flow_offload nft_fib_ipv6 nft_fib_ipv4 nft_fib nft_ct nft_chain_nat nf_tables nf_nat nf_flow_table nf_conntrack nfnetlink nf_reject_ipv6 nf_reject_ipv4 nf_log_syslog nf_defrag_ipv6 nf_defrag_ipv4 cls_flower sch_tbf sch_ingress sch_htb sch_hfsc em_u32 cls_u32 cls_route cls_matchall cls_fw cls_flow cls_basic act_skbedit act_mirred act_gact vrf md5 crc32c_cryptoapi -[ 89.780000] CPU: 1 UID: 0 PID: 26 Comm: kworker/u10:0 Tainted: G W 6.16.0-rc1+ #0 NONE -[ 89.780000] Tainted: [W]=WARN -[ 89.780000] Hardware name: Netgear DGND3700 v1 -[ 89.780000] Workqueue: events_power_efficient phy_state_machine -[ 89.780000] Stack : 809c762c 8006b050 00000001 820a9ce3 0000114c 000affff 805d22d0 8200ba00 -[ 89.780000] 82005000 6576656e 74735f70 6f776572 5f656666 10008b00 820a9cb8 82088700 -[ 89.780000] 00000000 00000000 809c762c 820a9a98 00000000 00000000 ffffefff 80a7a76c -[ 89.780000] 80a70000 820a9af8 80a70000 80a70000 80a70000 00000000 809c762c 820a9dd4 -[ 89.780000] 00000000 805d1494 80a029e4 80a70000 00000003 00000000 00000004 81a60004 -[ 89.780000] ... -[ 89.780000] Call Trace: -[ 89.780000] [<800228b8>] show_stack+0x38/0x118 -[ 89.780000] [<8001afc4>] dump_stack_lvl+0x6c/0xac -[ 89.780000] [<80046b90>] __warn+0x9c/0x114 -[ 89.780000] [<80046da8>] warn_slowpath_fmt+0x1a0/0x1b0 -[ 89.780000] [<805d1494>] _phy_state_machine+0x1bc/0x454 -[ 89.780000] [<805d22fc>] phy_state_machine+0x2c/0x70 -[ 89.780000] [<80066b08>] process_one_work+0x1e8/0x3e0 -[ 89.780000] [<80067a1c>] worker_thread+0x354/0x4e4 -[ 89.780000] [<800706cc>] kthread+0x130/0x274 -[ 89.780000] [<8001d808>] ret_from_kernel_thread+0x14/0x1c - -And any further accesses fail: - -[ 120.790000] b53-switch spi0.1: timeout waiting for ARL to finish: 0x81 -[ 120.800000] b53-switch spi0.1: port 2 failed to add 2c:b0:5d:27:9a:bd vid 3 to fdb: -145 -[ 121.010000] b53-switch spi0.1: timeout waiting for ARL to finish: 0xbf -[ 121.020000] b53-switch spi0.1: port 3 failed to add 2c:b0:5d:27:9a:bd vid 3 to fdb: -145 - -Restore the correct page B53_ARLIO_PAGE again, and move the offset -argument to the correct place. - -*On BCM5325, this became a write to the MIB page of Port 1. Still -a reserved offset, but likely less brokenness from that write. - -Fixes: c45655386e53 ("net: dsa: b53: add support for FDB operations on 5325/5365") -Signed-off-by: Jonas Gorski -Reviewed-by: Florian Fainelli -Link: https://patch.msgid.link/20250815201809.549195-1-jonas.gorski@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/dsa/b53/b53_common.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/net/dsa/b53/b53_common.c -+++ b/drivers/net/dsa/b53/b53_common.c -@@ -2100,7 +2100,7 @@ int b53_fdb_dump(struct dsa_switch *ds, - - /* Start search operation */ - reg = ARL_SRCH_STDN; -- b53_write8(priv, offset, B53_ARL_SRCH_CTL, reg); -+ b53_write8(priv, B53_ARLIO_PAGE, offset, reg); - - do { - ret = b53_arl_search_wait(priv); diff --git a/target/linux/generic/backport-6.18/611-17-v6.18-net-dsa-b53-fix-ageing-time-for-BCM53101.patch b/target/linux/generic/backport-6.18/611-17-v6.18-net-dsa-b53-fix-ageing-time-for-BCM53101.patch deleted file mode 100644 index 0eb0870a4b..0000000000 --- a/target/linux/generic/backport-6.18/611-17-v6.18-net-dsa-b53-fix-ageing-time-for-BCM53101.patch +++ /dev/null @@ -1,77 +0,0 @@ -From 674b34c4c770551e916ae707829c7faea4782d3a Mon Sep 17 00:00:00 2001 -From: Jonas Gorski -Date: Fri, 5 Sep 2025 14:45:07 +0200 -Subject: [PATCH] net: dsa: b53: fix ageing time for BCM53101 - -For some reason Broadcom decided that BCM53101 uses 0.5s increments for -the ageing time register, but kept the field width the same [1]. Due to -this, the actual ageing time was always half of what was configured. - -Fix this by adapting the limits and value calculation for BCM53101. - -So far it looks like this is the only chip with the increased tick -speed: - -$ grep -l -r "Specifies the aging time in 0.5 seconds" cdk/PKG/chip | sort -cdk/PKG/chip/bcm53101/bcm53101_a0_defs.h - -$ grep -l -r "Specifies the aging time in seconds" cdk/PKG/chip | sort -cdk/PKG/chip/bcm53010/bcm53010_a0_defs.h -cdk/PKG/chip/bcm53020/bcm53020_a0_defs.h -cdk/PKG/chip/bcm53084/bcm53084_a0_defs.h -cdk/PKG/chip/bcm53115/bcm53115_a0_defs.h -cdk/PKG/chip/bcm53118/bcm53118_a0_defs.h -cdk/PKG/chip/bcm53125/bcm53125_a0_defs.h -cdk/PKG/chip/bcm53128/bcm53128_a0_defs.h -cdk/PKG/chip/bcm53134/bcm53134_a0_defs.h -cdk/PKG/chip/bcm53242/bcm53242_a0_defs.h -cdk/PKG/chip/bcm53262/bcm53262_a0_defs.h -cdk/PKG/chip/bcm53280/bcm53280_a0_defs.h -cdk/PKG/chip/bcm53280/bcm53280_b0_defs.h -cdk/PKG/chip/bcm53600/bcm53600_a0_defs.h -cdk/PKG/chip/bcm89500/bcm89500_a0_defs.h - -[1] https://github.com/Broadcom/OpenMDK/blob/a5d3fc9b12af3eeb68f2ca0ce7ec4056cd14d6c2/cdk/PKG/chip/bcm53101/bcm53101_a0_defs.h#L28966 - -Fixes: e39d14a760c0 ("net: dsa: b53: implement setting ageing time") -Signed-off-by: Jonas Gorski -Reviewed-by: Florian Fainelli -Link: https://patch.msgid.link/20250905124507.59186-1-jonas.gorski@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/dsa/b53/b53_common.c | 17 +++++++++++++---- - 1 file changed, 13 insertions(+), 4 deletions(-) - ---- a/drivers/net/dsa/b53/b53_common.c -+++ b/drivers/net/dsa/b53/b53_common.c -@@ -1273,9 +1273,15 @@ static int b53_setup(struct dsa_switch * - */ - ds->untag_vlan_aware_bridge_pvid = true; - -- /* Ageing time is set in seconds */ -- ds->ageing_time_min = 1 * 1000; -- ds->ageing_time_max = AGE_TIME_MAX * 1000; -+ if (dev->chip_id == BCM53101_DEVICE_ID) { -+ /* BCM53101 uses 0.5 second increments */ -+ ds->ageing_time_min = 1 * 500; -+ ds->ageing_time_max = AGE_TIME_MAX * 500; -+ } else { -+ /* Everything else uses 1 second increments */ -+ ds->ageing_time_min = 1 * 1000; -+ ds->ageing_time_max = AGE_TIME_MAX * 1000; -+ } - - ret = b53_reset_switch(dev); - if (ret) { -@@ -2587,7 +2593,10 @@ int b53_set_ageing_time(struct dsa_switc - else - reg = B53_AGING_TIME_CONTROL; - -- atc = DIV_ROUND_CLOSEST(msecs, 1000); -+ if (dev->chip_id == BCM53101_DEVICE_ID) -+ atc = DIV_ROUND_CLOSEST(msecs, 500); -+ else -+ atc = DIV_ROUND_CLOSEST(msecs, 1000); - - if (!is5325(dev) && !is5365(dev)) - atc |= AGE_CHANGE; diff --git a/target/linux/generic/backport-6.18/611-18-v6.18-net-dsa-b53-properly-bound-ARL-searches-for-4-ARL-bin-chips.patch b/target/linux/generic/backport-6.18/611-18-v6.18-net-dsa-b53-properly-bound-ARL-searches-for-4-ARL-bin-chips.patch deleted file mode 100644 index 50ddcf93ee..0000000000 --- a/target/linux/generic/backport-6.18/611-18-v6.18-net-dsa-b53-properly-bound-ARL-searches-for-4-ARL-bin-chips.patch +++ /dev/null @@ -1,61 +0,0 @@ -From e57723fe536f040cc2635ec1545dd0a7919a321e Mon Sep 17 00:00:00 2001 -From: Jonas Gorski -Date: Sun, 2 Nov 2025 11:07:58 +0100 -Subject: [PATCH] net: dsa: b53: properly bound ARL searches for < 4 ARL bin - chips - -When iterating over the ARL table we stop at max ARL entries / 2, but -this is only valid if the chip actually returns 2 results at once. For -chips with only one result register we will stop before reaching the end -of the table if it is more than half full. - -Fix this by only dividing the maximum results by two if we have a chip -with more than one result register (i.e. those with 4 ARL bins). - -Fixes: cd169d799bee ("net: dsa: b53: Bound check ARL searches") -Signed-off-by: Jonas Gorski -Reviewed-by: Florian Fainelli -Link: https://patch.msgid.link/20251102100758.28352-4-jonas.gorski@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/dsa/b53/b53_common.c | 9 ++++++--- - 1 file changed, 6 insertions(+), 3 deletions(-) - ---- a/drivers/net/dsa/b53/b53_common.c -+++ b/drivers/net/dsa/b53/b53_common.c -@@ -2090,13 +2090,16 @@ static int b53_fdb_copy(int port, const - int b53_fdb_dump(struct dsa_switch *ds, int port, - dsa_fdb_dump_cb_t *cb, void *data) - { -+ unsigned int count = 0, results_per_hit = 1; - struct b53_device *priv = ds->priv; - struct b53_arl_entry results[2]; -- unsigned int count = 0; - u8 offset; - int ret; - u8 reg; - -+ if (priv->num_arl_bins > 2) -+ results_per_hit = 2; -+ - mutex_lock(&priv->arl_mutex); - - if (is5325(priv) || is5365(priv)) -@@ -2118,7 +2121,7 @@ int b53_fdb_dump(struct dsa_switch *ds, - if (ret) - break; - -- if (priv->num_arl_bins > 2) { -+ if (results_per_hit == 2) { - b53_arl_search_rd(priv, 1, &results[1]); - ret = b53_fdb_copy(port, &results[1], cb, data); - if (ret) -@@ -2128,7 +2131,7 @@ int b53_fdb_dump(struct dsa_switch *ds, - break; - } - -- } while (count++ < b53_max_arl_entries(priv) / 2); -+ } while (count++ < b53_max_arl_entries(priv) / results_per_hit); - - mutex_unlock(&priv->arl_mutex); - diff --git a/target/linux/generic/backport-6.18/611-19-v6.18-net-dsa-tag_brcm-do-not-mark-link-local-traffic-as-offloaded.patch b/target/linux/generic/backport-6.18/611-19-v6.18-net-dsa-tag_brcm-do-not-mark-link-local-traffic-as-offloaded.patch deleted file mode 100644 index 7c3d06269a..0000000000 --- a/target/linux/generic/backport-6.18/611-19-v6.18-net-dsa-tag_brcm-do-not-mark-link-local-traffic-as-offloaded.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 762e7e174da91cf4babfe77e45bc6b67334b1503 Mon Sep 17 00:00:00 2001 -From: Jonas Gorski -Date: Sun, 9 Nov 2025 14:46:35 +0100 -Subject: [PATCH] net: dsa: tag_brcm: do not mark link local traffic as - offloaded - -Broadcom switches locally terminate link local traffic and do not -forward it, so we should not mark it as offloaded. - -In some situations we still want/need to flood this traffic, e.g. if STP -is disabled, or it is explicitly enabled via the group_fwd_mask. But if -the skb is marked as offloaded, the kernel will assume this was already -done in hardware, and the packets never reach other bridge ports. - -So ensure that link local traffic is never marked as offloaded, so that -the kernel can forward/flood these packets in software if needed. - -Since the local termination in not configurable, check the destination -MAC, and never mark packets as offloaded if it is a link local ether -address. - -While modern switches set the tag reason code to BRCM_EG_RC_PROT_TERM -for trapped link local traffic, they also set it for link local traffic -that is flooded (01:80:c2:00:00:10 to 01:80:c2:00:00:2f), so we cannot -use it and need to look at the destination address for them as well. - -Fixes: 964dbf186eaa ("net: dsa: tag_brcm: add support for legacy tags") -Fixes: 0e62f543bed0 ("net: dsa: Fix duplicate frames flooded by learning") -Signed-off-by: Jonas Gorski -Reviewed-by: Vladimir Oltean -Reviewed-by: Florian Fainelli -Link: https://patch.msgid.link/20251109134635.243951-1-jonas.gorski@gmail.com -Signed-off-by: Jakub Kicinski ---- - net/dsa/tag_brcm.c | 6 ++++-- - 1 file changed, 4 insertions(+), 2 deletions(-) - ---- a/net/dsa/tag_brcm.c -+++ b/net/dsa/tag_brcm.c -@@ -176,7 +176,8 @@ static struct sk_buff *brcm_tag_rcv_ll(s - /* Remove Broadcom tag and update checksum */ - skb_pull_rcsum(skb, BRCM_TAG_LEN); - -- dsa_default_offload_fwd_mark(skb); -+ if (likely(!is_link_local_ether_addr(eth_hdr(skb)->h_dest))) -+ dsa_default_offload_fwd_mark(skb); - - return skb; - } -@@ -250,7 +251,8 @@ static struct sk_buff *brcm_leg_tag_rcv( - /* Remove Broadcom tag and update checksum */ - skb_pull_rcsum(skb, len); - -- dsa_default_offload_fwd_mark(skb); -+ if (likely(!is_link_local_ether_addr(eth_hdr(skb)->h_dest))) -+ dsa_default_offload_fwd_mark(skb); - - dsa_strip_etype_header(skb, len); - diff --git a/target/linux/generic/backport-6.18/612-01-v6.19-net-dsa-b53-b53_arl_read-25-use-the-entry-for-comparision.patch b/target/linux/generic/backport-6.18/612-01-v6.19-net-dsa-b53-b53_arl_read-25-use-the-entry-for-comparision.patch deleted file mode 100644 index 2b6cff796f..0000000000 --- a/target/linux/generic/backport-6.18/612-01-v6.19-net-dsa-b53-b53_arl_read-25-use-the-entry-for-comparision.patch +++ /dev/null @@ -1,85 +0,0 @@ -From a6e4fd38bf2f2e2363b61c27f4e6c49b14e4bb07 Mon Sep 17 00:00:00 2001 -From: Jonas Gorski -Date: Fri, 7 Nov 2025 09:07:42 +0100 -Subject: [PATCH] net: dsa: b53: b53_arl_read{,25}(): use the entry for - comparision - -Align the b53_arl_read{,25}() functions by consistently using the -parsed arl entry instead of parsing the raw registers again. - -Signed-off-by: Jonas Gorski -Reviewed-by: Florian Fainelli -Link: https://patch.msgid.link/20251107080749.26936-2-jonas.gorski@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/dsa/b53/b53_common.c | 22 ++++++++++------------ - 1 file changed, 10 insertions(+), 12 deletions(-) - ---- a/drivers/net/dsa/b53/b53_common.c -+++ b/drivers/net/dsa/b53/b53_common.c -@@ -1830,7 +1830,7 @@ static int b53_arl_rw_op(struct b53_devi - return b53_arl_op_wait(dev); - } - --static int b53_arl_read(struct b53_device *dev, u64 mac, -+static int b53_arl_read(struct b53_device *dev, const u8 *mac, - u16 vid, struct b53_arl_entry *ent, u8 *idx) - { - DECLARE_BITMAP(free_bins, B53_ARLTBL_MAX_BIN_ENTRIES); -@@ -1854,14 +1854,13 @@ static int b53_arl_read(struct b53_devic - B53_ARLTBL_DATA_ENTRY(i), &fwd_entry); - b53_arl_to_entry(ent, mac_vid, fwd_entry); - -- if (!(fwd_entry & ARLTBL_VALID)) { -+ if (!ent->is_valid) { - set_bit(i, free_bins); - continue; - } -- if ((mac_vid & ARLTBL_MAC_MASK) != mac) -+ if (!ether_addr_equal(ent->mac, mac)) - continue; -- if (dev->vlan_enabled && -- ((mac_vid >> ARLTBL_VID_S) & ARLTBL_VID_MASK) != vid) -+ if (dev->vlan_enabled && ent->vid != vid) - continue; - *idx = i; - return 0; -@@ -1871,7 +1870,7 @@ static int b53_arl_read(struct b53_devic - return *idx >= dev->num_arl_bins ? -ENOSPC : -ENOENT; - } - --static int b53_arl_read_25(struct b53_device *dev, u64 mac, -+static int b53_arl_read_25(struct b53_device *dev, const u8 *mac, - u16 vid, struct b53_arl_entry *ent, u8 *idx) - { - DECLARE_BITMAP(free_bins, B53_ARLTBL_MAX_BIN_ENTRIES); -@@ -1893,14 +1892,13 @@ static int b53_arl_read_25(struct b53_de - - b53_arl_to_entry_25(ent, mac_vid); - -- if (!(mac_vid & ARLTBL_VALID_25)) { -+ if (!ent->is_valid) { - set_bit(i, free_bins); - continue; - } -- if ((mac_vid & ARLTBL_MAC_MASK) != mac) -+ if (!ether_addr_equal(ent->mac, mac)) - continue; -- if (dev->vlan_enabled && -- ((mac_vid >> ARLTBL_VID_S_65) & ARLTBL_VID_MASK_25) != vid) -+ if (dev->vlan_enabled && ent->vid != vid) - continue; - *idx = i; - return 0; -@@ -1933,9 +1931,9 @@ static int b53_arl_op(struct b53_device - return ret; - - if (is5325(dev) || is5365(dev)) -- ret = b53_arl_read_25(dev, mac, vid, &ent, &idx); -+ ret = b53_arl_read_25(dev, addr, vid, &ent, &idx); - else -- ret = b53_arl_read(dev, mac, vid, &ent, &idx); -+ ret = b53_arl_read(dev, addr, vid, &ent, &idx); - - /* If this is a read, just finish now */ - if (op) diff --git a/target/linux/generic/backport-6.18/612-02-v6.19-net-dsa-b53-move-reading-ARL-entries-into-their-own-function.patch b/target/linux/generic/backport-6.18/612-02-v6.19-net-dsa-b53-move-reading-ARL-entries-into-their-own-function.patch deleted file mode 100644 index 8cf85ce7ad..0000000000 --- a/target/linux/generic/backport-6.18/612-02-v6.19-net-dsa-b53-move-reading-ARL-entries-into-their-own-function.patch +++ /dev/null @@ -1,117 +0,0 @@ -From 4a291fe7226736a465ddb3fa93c21fcef7162ec7 Mon Sep 17 00:00:00 2001 -From: Jonas Gorski -Date: Fri, 7 Nov 2025 09:07:43 +0100 -Subject: [PATCH] net: dsa: b53: move reading ARL entries into their own - function - -Instead of duplicating the whole code iterating over all bins for -BCM5325, factor out reading and parsing the entry into its own -functions, and name it the modern one after the first chip with that ARL -format, (BCM53)95. - -Signed-off-by: Jonas Gorski -Reviewed-by: Florian Fainelli -Link: https://patch.msgid.link/20251107080749.26936-3-jonas.gorski@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/dsa/b53/b53_common.c | 69 +++++++++++--------------------- - 1 file changed, 23 insertions(+), 46 deletions(-) - ---- a/drivers/net/dsa/b53/b53_common.c -+++ b/drivers/net/dsa/b53/b53_common.c -@@ -1830,48 +1830,30 @@ static int b53_arl_rw_op(struct b53_devi - return b53_arl_op_wait(dev); - } - --static int b53_arl_read(struct b53_device *dev, const u8 *mac, -- u16 vid, struct b53_arl_entry *ent, u8 *idx) -+static void b53_arl_read_entry_25(struct b53_device *dev, -+ struct b53_arl_entry *ent, u8 idx) - { -- DECLARE_BITMAP(free_bins, B53_ARLTBL_MAX_BIN_ENTRIES); -- unsigned int i; -- int ret; -- -- ret = b53_arl_op_wait(dev); -- if (ret) -- return ret; -+ u64 mac_vid; - -- bitmap_zero(free_bins, dev->num_arl_bins); -- -- /* Read the bins */ -- for (i = 0; i < dev->num_arl_bins; i++) { -- u64 mac_vid; -- u32 fwd_entry; -- -- b53_read64(dev, B53_ARLIO_PAGE, -- B53_ARLTBL_MAC_VID_ENTRY(i), &mac_vid); -- b53_read32(dev, B53_ARLIO_PAGE, -- B53_ARLTBL_DATA_ENTRY(i), &fwd_entry); -- b53_arl_to_entry(ent, mac_vid, fwd_entry); -+ b53_read64(dev, B53_ARLIO_PAGE, B53_ARLTBL_MAC_VID_ENTRY(idx), -+ &mac_vid); -+ b53_arl_to_entry_25(ent, mac_vid); -+} - -- if (!ent->is_valid) { -- set_bit(i, free_bins); -- continue; -- } -- if (!ether_addr_equal(ent->mac, mac)) -- continue; -- if (dev->vlan_enabled && ent->vid != vid) -- continue; -- *idx = i; -- return 0; -- } -+static void b53_arl_read_entry_95(struct b53_device *dev, -+ struct b53_arl_entry *ent, u8 idx) -+{ -+ u32 fwd_entry; -+ u64 mac_vid; - -- *idx = find_first_bit(free_bins, dev->num_arl_bins); -- return *idx >= dev->num_arl_bins ? -ENOSPC : -ENOENT; -+ b53_read64(dev, B53_ARLIO_PAGE, B53_ARLTBL_MAC_VID_ENTRY(idx), -+ &mac_vid); -+ b53_read32(dev, B53_ARLIO_PAGE, B53_ARLTBL_DATA_ENTRY(idx), &fwd_entry); -+ b53_arl_to_entry(ent, mac_vid, fwd_entry); - } - --static int b53_arl_read_25(struct b53_device *dev, const u8 *mac, -- u16 vid, struct b53_arl_entry *ent, u8 *idx) -+static int b53_arl_read(struct b53_device *dev, const u8 *mac, -+ u16 vid, struct b53_arl_entry *ent, u8 *idx) - { - DECLARE_BITMAP(free_bins, B53_ARLTBL_MAX_BIN_ENTRIES); - unsigned int i; -@@ -1885,12 +1867,10 @@ static int b53_arl_read_25(struct b53_de - - /* Read the bins */ - for (i = 0; i < dev->num_arl_bins; i++) { -- u64 mac_vid; -- -- b53_read64(dev, B53_ARLIO_PAGE, -- B53_ARLTBL_MAC_VID_ENTRY(i), &mac_vid); -- -- b53_arl_to_entry_25(ent, mac_vid); -+ if (is5325(dev) || is5365(dev)) -+ b53_arl_read_entry_25(dev, ent, i); -+ else -+ b53_arl_read_entry_95(dev, ent, i); - - if (!ent->is_valid) { - set_bit(i, free_bins); -@@ -1930,10 +1910,7 @@ static int b53_arl_op(struct b53_device - if (ret) - return ret; - -- if (is5325(dev) || is5365(dev)) -- ret = b53_arl_read_25(dev, addr, vid, &ent, &idx); -- else -- ret = b53_arl_read(dev, addr, vid, &ent, &idx); -+ ret = b53_arl_read(dev, addr, vid, &ent, &idx); - - /* If this is a read, just finish now */ - if (op) diff --git a/target/linux/generic/backport-6.18/612-03-v6.19-net-dsa-b53-move-writing-ARL-entries-into-their-own-functions.patch b/target/linux/generic/backport-6.18/612-03-v6.19-net-dsa-b53-move-writing-ARL-entries-into-their-own-functions.patch deleted file mode 100644 index a171232d49..0000000000 --- a/target/linux/generic/backport-6.18/612-03-v6.19-net-dsa-b53-move-writing-ARL-entries-into-their-own-functions.patch +++ /dev/null @@ -1,93 +0,0 @@ -From bf6e9d2ae1dbafee53ec4ccd126595172e1e5278 Mon Sep 17 00:00:00 2001 -From: Jonas Gorski -Date: Fri, 7 Nov 2025 09:07:44 +0100 -Subject: [PATCH] net: dsa: b53: move writing ARL entries into their own - functions - -Move writing ARL entries into individual functions for each format. - -Signed-off-by: Jonas Gorski -Reviewed-by: Florian Fainelli -Link: https://patch.msgid.link/20251107080749.26936-4-jonas.gorski@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/dsa/b53/b53_common.c | 38 ++++++++++++++++++++++---------- - 1 file changed, 26 insertions(+), 12 deletions(-) - ---- a/drivers/net/dsa/b53/b53_common.c -+++ b/drivers/net/dsa/b53/b53_common.c -@@ -1840,6 +1840,16 @@ static void b53_arl_read_entry_25(struct - b53_arl_to_entry_25(ent, mac_vid); - } - -+static void b53_arl_write_entry_25(struct b53_device *dev, -+ const struct b53_arl_entry *ent, u8 idx) -+{ -+ u64 mac_vid; -+ -+ b53_arl_from_entry_25(&mac_vid, ent); -+ b53_write64(dev, B53_ARLIO_PAGE, B53_ARLTBL_MAC_VID_ENTRY(idx), -+ mac_vid); -+} -+ - static void b53_arl_read_entry_95(struct b53_device *dev, - struct b53_arl_entry *ent, u8 idx) - { -@@ -1852,6 +1862,19 @@ static void b53_arl_read_entry_95(struct - b53_arl_to_entry(ent, mac_vid, fwd_entry); - } - -+static void b53_arl_write_entry_95(struct b53_device *dev, -+ const struct b53_arl_entry *ent, u8 idx) -+{ -+ u32 fwd_entry; -+ u64 mac_vid; -+ -+ b53_arl_from_entry(&mac_vid, &fwd_entry, ent); -+ b53_write64(dev, B53_ARLIO_PAGE, B53_ARLTBL_MAC_VID_ENTRY(idx), -+ mac_vid); -+ b53_write32(dev, B53_ARLIO_PAGE, B53_ARLTBL_DATA_ENTRY(idx), -+ fwd_entry); -+} -+ - static int b53_arl_read(struct b53_device *dev, const u8 *mac, - u16 vid, struct b53_arl_entry *ent, u8 *idx) - { -@@ -1892,9 +1915,8 @@ static int b53_arl_op(struct b53_device - const unsigned char *addr, u16 vid, bool is_valid) - { - struct b53_arl_entry ent; -- u32 fwd_entry; -- u64 mac, mac_vid = 0; - u8 idx = 0; -+ u64 mac; - int ret; - - /* Convert the array into a 64-bit MAC */ -@@ -1927,7 +1949,6 @@ static int b53_arl_op(struct b53_device - /* We could not find a matching MAC, so reset to a new entry */ - dev_dbg(dev->dev, "{%pM,%.4d} not found, using idx: %d\n", - addr, vid, idx); -- fwd_entry = 0; - break; - default: - dev_dbg(dev->dev, "{%pM,%.4d} found, using idx: %d\n", -@@ -1955,16 +1976,9 @@ static int b53_arl_op(struct b53_device - ent.is_age = false; - memcpy(ent.mac, addr, ETH_ALEN); - if (is5325(dev) || is5365(dev)) -- b53_arl_from_entry_25(&mac_vid, &ent); -+ b53_arl_write_entry_25(dev, &ent, idx); - else -- b53_arl_from_entry(&mac_vid, &fwd_entry, &ent); -- -- b53_write64(dev, B53_ARLIO_PAGE, -- B53_ARLTBL_MAC_VID_ENTRY(idx), mac_vid); -- -- if (!is5325(dev) && !is5365(dev)) -- b53_write32(dev, B53_ARLIO_PAGE, -- B53_ARLTBL_DATA_ENTRY(idx), fwd_entry); -+ b53_arl_write_entry_95(dev, &ent, idx); - - return b53_arl_rw_op(dev, 0); - } diff --git a/target/linux/generic/backport-6.18/612-04-v6.19-net-dsa-b53-provide-accessors-for-accessing-ARL_SRCH_CTL.patch b/target/linux/generic/backport-6.18/612-04-v6.19-net-dsa-b53-provide-accessors-for-accessing-ARL_SRCH_CTL.patch deleted file mode 100644 index 2922427c3c..0000000000 --- a/target/linux/generic/backport-6.18/612-04-v6.19-net-dsa-b53-provide-accessors-for-accessing-ARL_SRCH_CTL.patch +++ /dev/null @@ -1,85 +0,0 @@ -From 1716be6db04af53bac9b869f01156a460595cf41 Mon Sep 17 00:00:00 2001 -From: Jonas Gorski -Date: Fri, 7 Nov 2025 09:07:45 +0100 -Subject: [PATCH] net: dsa: b53: provide accessors for accessing ARL_SRCH_CTL - -In order to more easily support more formats, move accessing -ARL_SRCH_CTL into helper functions to contain the differences. - -Signed-off-by: Jonas Gorski -Reviewed-by: Florian Fainelli -Link: https://patch.msgid.link/20251107080749.26936-5-jonas.gorski@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/dsa/b53/b53_common.c | 37 +++++++++++++++++++++----------- - 1 file changed, 24 insertions(+), 13 deletions(-) - ---- a/drivers/net/dsa/b53/b53_common.c -+++ b/drivers/net/dsa/b53/b53_common.c -@@ -2013,18 +2013,37 @@ int b53_fdb_del(struct dsa_switch *ds, i - } - EXPORT_SYMBOL(b53_fdb_del); - --static int b53_arl_search_wait(struct b53_device *dev) -+static void b53_read_arl_srch_ctl(struct b53_device *dev, u8 *val) - { -- unsigned int timeout = 1000; -- u8 reg, offset; -+ u8 offset; -+ -+ if (is5325(dev) || is5365(dev)) -+ offset = B53_ARL_SRCH_CTL_25; -+ else -+ offset = B53_ARL_SRCH_CTL; -+ -+ b53_read8(dev, B53_ARLIO_PAGE, offset, val); -+} -+ -+static void b53_write_arl_srch_ctl(struct b53_device *dev, u8 val) -+{ -+ u8 offset; - - if (is5325(dev) || is5365(dev)) - offset = B53_ARL_SRCH_CTL_25; - else - offset = B53_ARL_SRCH_CTL; - -+ b53_write8(dev, B53_ARLIO_PAGE, offset, val); -+} -+ -+static int b53_arl_search_wait(struct b53_device *dev) -+{ -+ unsigned int timeout = 1000; -+ u8 reg; -+ - do { -- b53_read8(dev, B53_ARLIO_PAGE, offset, ®); -+ b53_read_arl_srch_ctl(dev, ®); - if (!(reg & ARL_SRCH_STDN)) - return -ENOENT; - -@@ -2082,23 +2101,15 @@ int b53_fdb_dump(struct dsa_switch *ds, - unsigned int count = 0, results_per_hit = 1; - struct b53_device *priv = ds->priv; - struct b53_arl_entry results[2]; -- u8 offset; - int ret; -- u8 reg; - - if (priv->num_arl_bins > 2) - results_per_hit = 2; - - mutex_lock(&priv->arl_mutex); - -- if (is5325(priv) || is5365(priv)) -- offset = B53_ARL_SRCH_CTL_25; -- else -- offset = B53_ARL_SRCH_CTL; -- - /* Start search operation */ -- reg = ARL_SRCH_STDN; -- b53_write8(priv, B53_ARLIO_PAGE, offset, reg); -+ b53_write_arl_srch_ctl(priv, ARL_SRCH_STDN); - - do { - ret = b53_arl_search_wait(priv); diff --git a/target/linux/generic/backport-6.18/612-05-v6.19-net-dsa-b53-split-reading-search-entry-into-their-own-functions.patch b/target/linux/generic/backport-6.18/612-05-v6.19-net-dsa-b53-split-reading-search-entry-into-their-own-functions.patch deleted file mode 100644 index 3e263f8cfb..0000000000 --- a/target/linux/generic/backport-6.18/612-05-v6.19-net-dsa-b53-split-reading-search-entry-into-their-own-functions.patch +++ /dev/null @@ -1,86 +0,0 @@ -From e0c476f325a8c9b961a3d446c24d3c8ecae7d186 Mon Sep 17 00:00:00 2001 -From: Jonas Gorski -Date: Fri, 7 Nov 2025 09:07:46 +0100 -Subject: [PATCH] net: dsa: b53: split reading search entry into their own - functions - -Split reading search entries into a function for each format. - -Signed-off-by: Jonas Gorski -Reviewed-by: Florian Fainelli -Link: https://patch.msgid.link/20251107080749.26936-6-jonas.gorski@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/dsa/b53/b53_common.c | 56 ++++++++++++++++++++++---------- - 1 file changed, 38 insertions(+), 18 deletions(-) - ---- a/drivers/net/dsa/b53/b53_common.c -+++ b/drivers/net/dsa/b53/b53_common.c -@@ -2056,28 +2056,48 @@ static int b53_arl_search_wait(struct b5 - return -ETIMEDOUT; - } - --static void b53_arl_search_rd(struct b53_device *dev, u8 idx, -- struct b53_arl_entry *ent) -+static void b53_arl_search_read_25(struct b53_device *dev, u8 idx, -+ struct b53_arl_entry *ent) - { - u64 mac_vid; - -- if (is5325(dev)) { -- b53_read64(dev, B53_ARLIO_PAGE, B53_ARL_SRCH_RSTL_0_MACVID_25, -- &mac_vid); -- b53_arl_to_entry_25(ent, mac_vid); -- } else if (is5365(dev)) { -- b53_read64(dev, B53_ARLIO_PAGE, B53_ARL_SRCH_RSTL_0_MACVID_65, -- &mac_vid); -- b53_arl_to_entry_25(ent, mac_vid); -- } else { -- u32 fwd_entry; -- -- b53_read64(dev, B53_ARLIO_PAGE, B53_ARL_SRCH_RSTL_MACVID(idx), -- &mac_vid); -- b53_read32(dev, B53_ARLIO_PAGE, B53_ARL_SRCH_RSTL(idx), -- &fwd_entry); -- b53_arl_to_entry(ent, mac_vid, fwd_entry); -- } -+ b53_read64(dev, B53_ARLIO_PAGE, B53_ARL_SRCH_RSTL_0_MACVID_25, -+ &mac_vid); -+ b53_arl_to_entry_25(ent, mac_vid); -+} -+ -+static void b53_arl_search_read_65(struct b53_device *dev, u8 idx, -+ struct b53_arl_entry *ent) -+{ -+ u64 mac_vid; -+ -+ b53_read64(dev, B53_ARLIO_PAGE, B53_ARL_SRCH_RSTL_0_MACVID_65, -+ &mac_vid); -+ b53_arl_to_entry_25(ent, mac_vid); -+} -+ -+static void b53_arl_search_read_95(struct b53_device *dev, u8 idx, -+ struct b53_arl_entry *ent) -+{ -+ u32 fwd_entry; -+ u64 mac_vid; -+ -+ b53_read64(dev, B53_ARLIO_PAGE, B53_ARL_SRCH_RSTL_MACVID(idx), -+ &mac_vid); -+ b53_read32(dev, B53_ARLIO_PAGE, B53_ARL_SRCH_RSTL(idx), -+ &fwd_entry); -+ b53_arl_to_entry(ent, mac_vid, fwd_entry); -+} -+ -+static void b53_arl_search_rd(struct b53_device *dev, u8 idx, -+ struct b53_arl_entry *ent) -+{ -+ if (is5325(dev)) -+ b53_arl_search_read_25(dev, idx, ent); -+ else if (is5365(dev)) -+ b53_arl_search_read_65(dev, idx, ent); -+ else -+ b53_arl_search_read_95(dev, idx, ent); - } - - static int b53_fdb_copy(int port, const struct b53_arl_entry *ent, diff --git a/target/linux/generic/backport-6.18/612-06-v6.19-net-dsa-b53-move-ARL-entry-functions-into-ops-struct.patch b/target/linux/generic/backport-6.18/612-06-v6.19-net-dsa-b53-move-ARL-entry-functions-into-ops-struct.patch deleted file mode 100644 index 110e160fed..0000000000 --- a/target/linux/generic/backport-6.18/612-06-v6.19-net-dsa-b53-move-ARL-entry-functions-into-ops-struct.patch +++ /dev/null @@ -1,348 +0,0 @@ -From a7e73339ad46ade76d29fb6cc7d7854222608c26 Mon Sep 17 00:00:00 2001 -From: Jonas Gorski -Date: Fri, 7 Nov 2025 09:07:47 +0100 -Subject: [PATCH] net: dsa: b53: move ARL entry functions into ops struct - -Now that the differences in ARL entry formats are neatly contained into -functions per chip family, wrap them into an ops struct and add wrapper -functions to access them. - -Signed-off-by: Jonas Gorski -Reviewed-by: Florian Fainelli -Link: https://patch.msgid.link/20251107080749.26936-7-jonas.gorski@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/dsa/b53/b53_common.c | 67 ++++++++++++++++++++++---------- - drivers/net/dsa/b53/b53_priv.h | 30 ++++++++++++++ - 2 files changed, 76 insertions(+), 21 deletions(-) - ---- a/drivers/net/dsa/b53/b53_common.c -+++ b/drivers/net/dsa/b53/b53_common.c -@@ -1890,10 +1890,7 @@ static int b53_arl_read(struct b53_devic - - /* Read the bins */ - for (i = 0; i < dev->num_arl_bins; i++) { -- if (is5325(dev) || is5365(dev)) -- b53_arl_read_entry_25(dev, ent, i); -- else -- b53_arl_read_entry_95(dev, ent, i); -+ b53_arl_read_entry(dev, ent, i); - - if (!ent->is_valid) { - set_bit(i, free_bins); -@@ -1975,10 +1972,7 @@ static int b53_arl_op(struct b53_device - ent.is_static = true; - ent.is_age = false; - memcpy(ent.mac, addr, ETH_ALEN); -- if (is5325(dev) || is5365(dev)) -- b53_arl_write_entry_25(dev, &ent, idx); -- else -- b53_arl_write_entry_95(dev, &ent, idx); -+ b53_arl_write_entry(dev, &ent, idx); - - return b53_arl_rw_op(dev, 0); - } -@@ -2089,17 +2083,6 @@ static void b53_arl_search_read_95(struc - b53_arl_to_entry(ent, mac_vid, fwd_entry); - } - --static void b53_arl_search_rd(struct b53_device *dev, u8 idx, -- struct b53_arl_entry *ent) --{ -- if (is5325(dev)) -- b53_arl_search_read_25(dev, idx, ent); -- else if (is5365(dev)) -- b53_arl_search_read_65(dev, idx, ent); -- else -- b53_arl_search_read_95(dev, idx, ent); --} -- - static int b53_fdb_copy(int port, const struct b53_arl_entry *ent, - dsa_fdb_dump_cb_t *cb, void *data) - { -@@ -2136,13 +2119,13 @@ int b53_fdb_dump(struct dsa_switch *ds, - if (ret) - break; - -- b53_arl_search_rd(priv, 0, &results[0]); -+ b53_arl_search_read(priv, 0, &results[0]); - ret = b53_fdb_copy(port, &results[0], cb, data); - if (ret) - break; - - if (results_per_hit == 2) { -- b53_arl_search_rd(priv, 1, &results[1]); -+ b53_arl_search_read(priv, 1, &results[1]); - ret = b53_fdb_copy(port, &results[1], cb, data); - if (ret) - break; -@@ -2675,6 +2658,24 @@ static const struct dsa_switch_ops b53_s - .port_change_mtu = b53_change_mtu, - }; - -+static const struct b53_arl_ops b53_arl_ops_25 = { -+ .arl_read_entry = b53_arl_read_entry_25, -+ .arl_write_entry = b53_arl_write_entry_25, -+ .arl_search_read = b53_arl_search_read_25, -+}; -+ -+static const struct b53_arl_ops b53_arl_ops_65 = { -+ .arl_read_entry = b53_arl_read_entry_25, -+ .arl_write_entry = b53_arl_write_entry_25, -+ .arl_search_read = b53_arl_search_read_65, -+}; -+ -+static const struct b53_arl_ops b53_arl_ops_95 = { -+ .arl_read_entry = b53_arl_read_entry_95, -+ .arl_write_entry = b53_arl_write_entry_95, -+ .arl_search_read = b53_arl_search_read_95, -+}; -+ - struct b53_chip_data { - u32 chip_id; - const char *dev_name; -@@ -2688,6 +2689,7 @@ struct b53_chip_data { - u8 duplex_reg; - u8 jumbo_pm_reg; - u8 jumbo_size_reg; -+ const struct b53_arl_ops *arl_ops; - }; - - #define B53_VTA_REGS \ -@@ -2707,6 +2709,7 @@ static const struct b53_chip_data b53_sw - .arl_buckets = 1024, - .imp_port = 5, - .duplex_reg = B53_DUPLEX_STAT_FE, -+ .arl_ops = &b53_arl_ops_25, - }, - { - .chip_id = BCM5365_DEVICE_ID, -@@ -2717,6 +2720,7 @@ static const struct b53_chip_data b53_sw - .arl_buckets = 1024, - .imp_port = 5, - .duplex_reg = B53_DUPLEX_STAT_FE, -+ .arl_ops = &b53_arl_ops_65, - }, - { - .chip_id = BCM5389_DEVICE_ID, -@@ -2730,6 +2734,7 @@ static const struct b53_chip_data b53_sw - .duplex_reg = B53_DUPLEX_STAT_GE, - .jumbo_pm_reg = B53_JUMBO_PORT_MASK, - .jumbo_size_reg = B53_JUMBO_MAX_SIZE, -+ .arl_ops = &b53_arl_ops_95, - }, - { - .chip_id = BCM5395_DEVICE_ID, -@@ -2743,6 +2748,7 @@ static const struct b53_chip_data b53_sw - .duplex_reg = B53_DUPLEX_STAT_GE, - .jumbo_pm_reg = B53_JUMBO_PORT_MASK, - .jumbo_size_reg = B53_JUMBO_MAX_SIZE, -+ .arl_ops = &b53_arl_ops_95, - }, - { - .chip_id = BCM5397_DEVICE_ID, -@@ -2756,6 +2762,7 @@ static const struct b53_chip_data b53_sw - .duplex_reg = B53_DUPLEX_STAT_GE, - .jumbo_pm_reg = B53_JUMBO_PORT_MASK, - .jumbo_size_reg = B53_JUMBO_MAX_SIZE, -+ .arl_ops = &b53_arl_ops_95, - }, - { - .chip_id = BCM5398_DEVICE_ID, -@@ -2769,6 +2776,7 @@ static const struct b53_chip_data b53_sw - .duplex_reg = B53_DUPLEX_STAT_GE, - .jumbo_pm_reg = B53_JUMBO_PORT_MASK, - .jumbo_size_reg = B53_JUMBO_MAX_SIZE, -+ .arl_ops = &b53_arl_ops_95, - }, - { - .chip_id = BCM53101_DEVICE_ID, -@@ -2782,6 +2790,7 @@ static const struct b53_chip_data b53_sw - .duplex_reg = B53_DUPLEX_STAT_GE, - .jumbo_pm_reg = B53_JUMBO_PORT_MASK, - .jumbo_size_reg = B53_JUMBO_MAX_SIZE, -+ .arl_ops = &b53_arl_ops_95, - }, - { - .chip_id = BCM53115_DEVICE_ID, -@@ -2795,6 +2804,7 @@ static const struct b53_chip_data b53_sw - .duplex_reg = B53_DUPLEX_STAT_GE, - .jumbo_pm_reg = B53_JUMBO_PORT_MASK, - .jumbo_size_reg = B53_JUMBO_MAX_SIZE, -+ .arl_ops = &b53_arl_ops_95, - }, - { - .chip_id = BCM53125_DEVICE_ID, -@@ -2808,6 +2818,7 @@ static const struct b53_chip_data b53_sw - .duplex_reg = B53_DUPLEX_STAT_GE, - .jumbo_pm_reg = B53_JUMBO_PORT_MASK, - .jumbo_size_reg = B53_JUMBO_MAX_SIZE, -+ .arl_ops = &b53_arl_ops_95, - }, - { - .chip_id = BCM53128_DEVICE_ID, -@@ -2821,6 +2832,7 @@ static const struct b53_chip_data b53_sw - .duplex_reg = B53_DUPLEX_STAT_GE, - .jumbo_pm_reg = B53_JUMBO_PORT_MASK, - .jumbo_size_reg = B53_JUMBO_MAX_SIZE, -+ .arl_ops = &b53_arl_ops_95, - }, - { - .chip_id = BCM63XX_DEVICE_ID, -@@ -2834,6 +2846,7 @@ static const struct b53_chip_data b53_sw - .duplex_reg = B53_DUPLEX_STAT_63XX, - .jumbo_pm_reg = B53_JUMBO_PORT_MASK_63XX, - .jumbo_size_reg = B53_JUMBO_MAX_SIZE_63XX, -+ .arl_ops = &b53_arl_ops_95, - }, - { - .chip_id = BCM53010_DEVICE_ID, -@@ -2847,6 +2860,7 @@ static const struct b53_chip_data b53_sw - .duplex_reg = B53_DUPLEX_STAT_GE, - .jumbo_pm_reg = B53_JUMBO_PORT_MASK, - .jumbo_size_reg = B53_JUMBO_MAX_SIZE, -+ .arl_ops = &b53_arl_ops_95, - }, - { - .chip_id = BCM53011_DEVICE_ID, -@@ -2860,6 +2874,7 @@ static const struct b53_chip_data b53_sw - .duplex_reg = B53_DUPLEX_STAT_GE, - .jumbo_pm_reg = B53_JUMBO_PORT_MASK, - .jumbo_size_reg = B53_JUMBO_MAX_SIZE, -+ .arl_ops = &b53_arl_ops_95, - }, - { - .chip_id = BCM53012_DEVICE_ID, -@@ -2873,6 +2888,7 @@ static const struct b53_chip_data b53_sw - .duplex_reg = B53_DUPLEX_STAT_GE, - .jumbo_pm_reg = B53_JUMBO_PORT_MASK, - .jumbo_size_reg = B53_JUMBO_MAX_SIZE, -+ .arl_ops = &b53_arl_ops_95, - }, - { - .chip_id = BCM53018_DEVICE_ID, -@@ -2886,6 +2902,7 @@ static const struct b53_chip_data b53_sw - .duplex_reg = B53_DUPLEX_STAT_GE, - .jumbo_pm_reg = B53_JUMBO_PORT_MASK, - .jumbo_size_reg = B53_JUMBO_MAX_SIZE, -+ .arl_ops = &b53_arl_ops_95, - }, - { - .chip_id = BCM53019_DEVICE_ID, -@@ -2899,6 +2916,7 @@ static const struct b53_chip_data b53_sw - .duplex_reg = B53_DUPLEX_STAT_GE, - .jumbo_pm_reg = B53_JUMBO_PORT_MASK, - .jumbo_size_reg = B53_JUMBO_MAX_SIZE, -+ .arl_ops = &b53_arl_ops_95, - }, - { - .chip_id = BCM58XX_DEVICE_ID, -@@ -2912,6 +2930,7 @@ static const struct b53_chip_data b53_sw - .duplex_reg = B53_DUPLEX_STAT_GE, - .jumbo_pm_reg = B53_JUMBO_PORT_MASK, - .jumbo_size_reg = B53_JUMBO_MAX_SIZE, -+ .arl_ops = &b53_arl_ops_95, - }, - { - .chip_id = BCM583XX_DEVICE_ID, -@@ -2925,6 +2944,7 @@ static const struct b53_chip_data b53_sw - .duplex_reg = B53_DUPLEX_STAT_GE, - .jumbo_pm_reg = B53_JUMBO_PORT_MASK, - .jumbo_size_reg = B53_JUMBO_MAX_SIZE, -+ .arl_ops = &b53_arl_ops_95, - }, - /* Starfighter 2 */ - { -@@ -2939,6 +2959,7 @@ static const struct b53_chip_data b53_sw - .duplex_reg = B53_DUPLEX_STAT_GE, - .jumbo_pm_reg = B53_JUMBO_PORT_MASK, - .jumbo_size_reg = B53_JUMBO_MAX_SIZE, -+ .arl_ops = &b53_arl_ops_95, - }, - { - .chip_id = BCM7445_DEVICE_ID, -@@ -2952,6 +2973,7 @@ static const struct b53_chip_data b53_sw - .duplex_reg = B53_DUPLEX_STAT_GE, - .jumbo_pm_reg = B53_JUMBO_PORT_MASK, - .jumbo_size_reg = B53_JUMBO_MAX_SIZE, -+ .arl_ops = &b53_arl_ops_95, - }, - { - .chip_id = BCM7278_DEVICE_ID, -@@ -2965,6 +2987,7 @@ static const struct b53_chip_data b53_sw - .duplex_reg = B53_DUPLEX_STAT_GE, - .jumbo_pm_reg = B53_JUMBO_PORT_MASK, - .jumbo_size_reg = B53_JUMBO_MAX_SIZE, -+ .arl_ops = &b53_arl_ops_95, - }, - { - .chip_id = BCM53134_DEVICE_ID, -@@ -2979,6 +3002,7 @@ static const struct b53_chip_data b53_sw - .duplex_reg = B53_DUPLEX_STAT_GE, - .jumbo_pm_reg = B53_JUMBO_PORT_MASK, - .jumbo_size_reg = B53_JUMBO_MAX_SIZE, -+ .arl_ops = &b53_arl_ops_95, - }, - }; - -@@ -3007,6 +3031,7 @@ static int b53_switch_init(struct b53_de - dev->num_vlans = chip->vlans; - dev->num_arl_bins = chip->arl_bins; - dev->num_arl_buckets = chip->arl_buckets; -+ dev->arl_ops = chip->arl_ops; - break; - } - } ---- a/drivers/net/dsa/b53/b53_priv.h -+++ b/drivers/net/dsa/b53/b53_priv.h -@@ -58,6 +58,17 @@ struct b53_io_ops { - bool link_up); - }; - -+struct b53_arl_entry; -+ -+struct b53_arl_ops { -+ void (*arl_read_entry)(struct b53_device *dev, -+ struct b53_arl_entry *ent, u8 idx); -+ void (*arl_write_entry)(struct b53_device *dev, -+ const struct b53_arl_entry *ent, u8 idx); -+ void (*arl_search_read)(struct b53_device *dev, u8 idx, -+ struct b53_arl_entry *ent); -+}; -+ - #define B53_INVALID_LANE 0xff - - enum { -@@ -127,6 +138,7 @@ struct b53_device { - struct mutex stats_mutex; - struct mutex arl_mutex; - const struct b53_io_ops *ops; -+ const struct b53_arl_ops *arl_ops; - - /* chip specific data */ - u32 chip_id; -@@ -371,6 +383,24 @@ static inline void b53_arl_from_entry_25 - *mac_vid |= ARLTBL_AGE_25; - } - -+static inline void b53_arl_read_entry(struct b53_device *dev, -+ struct b53_arl_entry *ent, u8 idx) -+{ -+ dev->arl_ops->arl_read_entry(dev, ent, idx); -+} -+ -+static inline void b53_arl_write_entry(struct b53_device *dev, -+ const struct b53_arl_entry *ent, u8 idx) -+{ -+ dev->arl_ops->arl_write_entry(dev, ent, idx); -+} -+ -+static inline void b53_arl_search_read(struct b53_device *dev, u8 idx, -+ struct b53_arl_entry *ent) -+{ -+ dev->arl_ops->arl_search_read(dev, idx, ent); -+} -+ - #ifdef CONFIG_BCM47XX - - #include diff --git a/target/linux/generic/backport-6.18/612-07-v6.19-net-dsa-b53-add-support-for-5389-5397-5398-ARL-entry-format.patch b/target/linux/generic/backport-6.18/612-07-v6.19-net-dsa-b53-add-support-for-5389-5397-5398-ARL-entry-format.patch deleted file mode 100644 index 948b4ab67b..0000000000 --- a/target/linux/generic/backport-6.18/612-07-v6.19-net-dsa-b53-add-support-for-5389-5397-5398-ARL-entry-format.patch +++ /dev/null @@ -1,221 +0,0 @@ -From 300f78e8b6b7be17c2c78afeded75be68acb1aa7 Mon Sep 17 00:00:00 2001 -From: Jonas Gorski -Date: Fri, 7 Nov 2025 09:07:48 +0100 -Subject: [PATCH] net: dsa: b53: add support for 5389/5397/5398 ARL entry - format - -BCM5389, BCM5397 and BCM5398 use a different ARL entry format with just -a 16 bit fwdentry register, as well as different search control and data -offsets. - -So add appropriate ops for them and switch those chips to use them. - -Signed-off-by: Jonas Gorski -Reviewed-by: Florian Fainelli -Link: https://patch.msgid.link/20251107080749.26936-8-jonas.gorski@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/dsa/b53/b53_common.c | 53 ++++++++++++++++++++++++++++++-- - drivers/net/dsa/b53/b53_priv.h | 26 ++++++++++++++++ - drivers/net/dsa/b53/b53_regs.h | 13 ++++++++ - 3 files changed, 89 insertions(+), 3 deletions(-) - ---- a/drivers/net/dsa/b53/b53_common.c -+++ b/drivers/net/dsa/b53/b53_common.c -@@ -1850,6 +1850,31 @@ static void b53_arl_write_entry_25(struc - mac_vid); - } - -+static void b53_arl_read_entry_89(struct b53_device *dev, -+ struct b53_arl_entry *ent, u8 idx) -+{ -+ u64 mac_vid; -+ u16 fwd_entry; -+ -+ b53_read64(dev, B53_ARLIO_PAGE, B53_ARLTBL_MAC_VID_ENTRY(idx), -+ &mac_vid); -+ b53_read16(dev, B53_ARLIO_PAGE, B53_ARLTBL_DATA_ENTRY(idx), &fwd_entry); -+ b53_arl_to_entry_89(ent, mac_vid, fwd_entry); -+} -+ -+static void b53_arl_write_entry_89(struct b53_device *dev, -+ const struct b53_arl_entry *ent, u8 idx) -+{ -+ u32 fwd_entry; -+ u64 mac_vid; -+ -+ b53_arl_from_entry_89(&mac_vid, &fwd_entry, ent); -+ b53_write64(dev, B53_ARLIO_PAGE, -+ B53_ARLTBL_MAC_VID_ENTRY(idx), mac_vid); -+ b53_write16(dev, B53_ARLIO_PAGE, -+ B53_ARLTBL_DATA_ENTRY(idx), fwd_entry); -+} -+ - static void b53_arl_read_entry_95(struct b53_device *dev, - struct b53_arl_entry *ent, u8 idx) - { -@@ -2013,6 +2038,8 @@ static void b53_read_arl_srch_ctl(struct - - if (is5325(dev) || is5365(dev)) - offset = B53_ARL_SRCH_CTL_25; -+ else if (dev->chip_id == BCM5389_DEVICE_ID || is5397_98(dev)) -+ offset = B53_ARL_SRCH_CTL_89; - else - offset = B53_ARL_SRCH_CTL; - -@@ -2025,6 +2052,8 @@ static void b53_write_arl_srch_ctl(struc - - if (is5325(dev) || is5365(dev)) - offset = B53_ARL_SRCH_CTL_25; -+ else if (dev->chip_id == BCM5389_DEVICE_ID || is5397_98(dev)) -+ offset = B53_ARL_SRCH_CTL_89; - else - offset = B53_ARL_SRCH_CTL; - -@@ -2070,6 +2099,18 @@ static void b53_arl_search_read_65(struc - b53_arl_to_entry_25(ent, mac_vid); - } - -+static void b53_arl_search_read_89(struct b53_device *dev, u8 idx, -+ struct b53_arl_entry *ent) -+{ -+ u16 fwd_entry; -+ u64 mac_vid; -+ -+ b53_read64(dev, B53_ARLIO_PAGE, B53_ARL_SRCH_RSLT_MACVID_89, -+ &mac_vid); -+ b53_read16(dev, B53_ARLIO_PAGE, B53_ARL_SRCH_RSLT_89, &fwd_entry); -+ b53_arl_to_entry_89(ent, mac_vid, fwd_entry); -+} -+ - static void b53_arl_search_read_95(struct b53_device *dev, u8 idx, - struct b53_arl_entry *ent) - { -@@ -2670,6 +2711,12 @@ static const struct b53_arl_ops b53_arl_ - .arl_search_read = b53_arl_search_read_65, - }; - -+static const struct b53_arl_ops b53_arl_ops_89 = { -+ .arl_read_entry = b53_arl_read_entry_89, -+ .arl_write_entry = b53_arl_write_entry_89, -+ .arl_search_read = b53_arl_search_read_89, -+}; -+ - static const struct b53_arl_ops b53_arl_ops_95 = { - .arl_read_entry = b53_arl_read_entry_95, - .arl_write_entry = b53_arl_write_entry_95, -@@ -2734,7 +2781,7 @@ static const struct b53_chip_data b53_sw - .duplex_reg = B53_DUPLEX_STAT_GE, - .jumbo_pm_reg = B53_JUMBO_PORT_MASK, - .jumbo_size_reg = B53_JUMBO_MAX_SIZE, -- .arl_ops = &b53_arl_ops_95, -+ .arl_ops = &b53_arl_ops_89, - }, - { - .chip_id = BCM5395_DEVICE_ID, -@@ -2762,7 +2809,7 @@ static const struct b53_chip_data b53_sw - .duplex_reg = B53_DUPLEX_STAT_GE, - .jumbo_pm_reg = B53_JUMBO_PORT_MASK, - .jumbo_size_reg = B53_JUMBO_MAX_SIZE, -- .arl_ops = &b53_arl_ops_95, -+ .arl_ops = &b53_arl_ops_89, - }, - { - .chip_id = BCM5398_DEVICE_ID, -@@ -2776,7 +2823,7 @@ static const struct b53_chip_data b53_sw - .duplex_reg = B53_DUPLEX_STAT_GE, - .jumbo_pm_reg = B53_JUMBO_PORT_MASK, - .jumbo_size_reg = B53_JUMBO_MAX_SIZE, -- .arl_ops = &b53_arl_ops_95, -+ .arl_ops = &b53_arl_ops_89, - }, - { - .chip_id = BCM53101_DEVICE_ID, ---- a/drivers/net/dsa/b53/b53_priv.h -+++ b/drivers/net/dsa/b53/b53_priv.h -@@ -353,6 +353,18 @@ static inline void b53_arl_to_entry_25(s - ent->vid = mac_vid >> ARLTBL_VID_S_65; - } - -+static inline void b53_arl_to_entry_89(struct b53_arl_entry *ent, -+ u64 mac_vid, u16 fwd_entry) -+{ -+ memset(ent, 0, sizeof(*ent)); -+ ent->port = fwd_entry & ARLTBL_DATA_PORT_ID_MASK_89; -+ ent->is_valid = !!(fwd_entry & ARLTBL_VALID_89); -+ ent->is_age = !!(fwd_entry & ARLTBL_AGE_89); -+ ent->is_static = !!(fwd_entry & ARLTBL_STATIC_89); -+ u64_to_ether_addr(mac_vid, ent->mac); -+ ent->vid = mac_vid >> ARLTBL_VID_S; -+} -+ - static inline void b53_arl_from_entry(u64 *mac_vid, u32 *fwd_entry, - const struct b53_arl_entry *ent) - { -@@ -383,6 +395,20 @@ static inline void b53_arl_from_entry_25 - *mac_vid |= ARLTBL_AGE_25; - } - -+static inline void b53_arl_from_entry_89(u64 *mac_vid, u32 *fwd_entry, -+ const struct b53_arl_entry *ent) -+{ -+ *mac_vid = ether_addr_to_u64(ent->mac); -+ *mac_vid |= (u64)(ent->vid & ARLTBL_VID_MASK) << ARLTBL_VID_S; -+ *fwd_entry = ent->port & ARLTBL_DATA_PORT_ID_MASK_89; -+ if (ent->is_valid) -+ *fwd_entry |= ARLTBL_VALID_89; -+ if (ent->is_static) -+ *fwd_entry |= ARLTBL_STATIC_89; -+ if (ent->is_age) -+ *fwd_entry |= ARLTBL_AGE_89; -+} -+ - static inline void b53_arl_read_entry(struct b53_device *dev, - struct b53_arl_entry *ent, u8 idx) - { ---- a/drivers/net/dsa/b53/b53_regs.h -+++ b/drivers/net/dsa/b53/b53_regs.h -@@ -342,12 +342,20 @@ - #define ARLTBL_STATIC BIT(15) - #define ARLTBL_VALID BIT(16) - -+/* BCM5389 ARL Table Data Entry N Register format (16 bit) */ -+#define ARLTBL_DATA_PORT_ID_MASK_89 GENMASK(8, 0) -+#define ARLTBL_TC_MASK_89 GENMASK(12, 10) -+#define ARLTBL_AGE_89 BIT(13) -+#define ARLTBL_STATIC_89 BIT(14) -+#define ARLTBL_VALID_89 BIT(15) -+ - /* Maximum number of bin entries in the ARL for all switches */ - #define B53_ARLTBL_MAX_BIN_ENTRIES 4 - - /* ARL Search Control Register (8 bit) */ - #define B53_ARL_SRCH_CTL 0x50 - #define B53_ARL_SRCH_CTL_25 0x20 -+#define B53_ARL_SRCH_CTL_89 0x30 - #define ARL_SRCH_VLID BIT(0) - #define ARL_SRCH_STDN BIT(7) - -@@ -355,10 +363,12 @@ - #define B53_ARL_SRCH_ADDR 0x51 - #define B53_ARL_SRCH_ADDR_25 0x22 - #define B53_ARL_SRCH_ADDR_65 0x24 -+#define B53_ARL_SRCH_ADDR_89 0x31 - #define ARL_ADDR_MASK GENMASK(14, 0) - - /* ARL Search MAC/VID Result (64 bit) */ - #define B53_ARL_SRCH_RSTL_0_MACVID 0x60 -+#define B53_ARL_SRCH_RSLT_MACVID_89 0x33 - - /* Single register search result on 5325 */ - #define B53_ARL_SRCH_RSTL_0_MACVID_25 0x24 -@@ -368,6 +378,9 @@ - /* ARL Search Data Result (32 bit) */ - #define B53_ARL_SRCH_RSTL_0 0x68 - -+/* BCM5389 ARL Search Data Result (16 bit) */ -+#define B53_ARL_SRCH_RSLT_89 0x3b -+ - #define B53_ARL_SRCH_RSTL_MACVID(x) (B53_ARL_SRCH_RSTL_0_MACVID + ((x) * 0x10)) - #define B53_ARL_SRCH_RSTL(x) (B53_ARL_SRCH_RSTL_0 + ((x) * 0x10)) - diff --git a/target/linux/generic/backport-6.18/612-08-v6.19-net-dsa-b53-add-support-for-bcm63xx-ARL-entry-format.patch b/target/linux/generic/backport-6.18/612-08-v6.19-net-dsa-b53-add-support-for-bcm63xx-ARL-entry-format.patch deleted file mode 100644 index ec0e85e4cf..0000000000 --- a/target/linux/generic/backport-6.18/612-08-v6.19-net-dsa-b53-add-support-for-bcm63xx-ARL-entry-format.patch +++ /dev/null @@ -1,177 +0,0 @@ -From 2b3013ac03028a2364d8779719bb6bfbc0212435 Mon Sep 17 00:00:00 2001 -From: Jonas Gorski -Date: Fri, 7 Nov 2025 09:07:49 +0100 -Subject: [PATCH] net: dsa: b53: add support for bcm63xx ARL entry format - -The ARL registers of BCM63XX embedded switches are somewhat unique. The -normal ARL table access registers have the same format as BCM5389, but -the ARL search registers differ: - -* SRCH_CTL is at the same offset of BCM5389, but 16 bits wide. It does - not have more fields, just needs to be accessed by a 16 bit read. -* SRCH_RSLT_MACVID and SRCH_RSLT are aligned to 32 bit, and have shifted - offsets. -* SRCH_RSLT has a different format than the normal ARL data entry - register. -* There is only one set of ENTRY_N registers, implying a 1 bin layout. - -So add appropriate ops for bcm63xx and let it use it. - -Signed-off-by: Jonas Gorski -Reviewed-by: Florian Fainelli -Link: https://patch.msgid.link/20251107080749.26936-9-jonas.gorski@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/dsa/b53/b53_common.c | 44 +++++++++++++++++++++++++++----- - drivers/net/dsa/b53/b53_priv.h | 15 +++++++++++ - drivers/net/dsa/b53/b53_regs.h | 9 +++++++ - 3 files changed, 61 insertions(+), 7 deletions(-) - ---- a/drivers/net/dsa/b53/b53_common.c -+++ b/drivers/net/dsa/b53/b53_common.c -@@ -2038,12 +2038,20 @@ static void b53_read_arl_srch_ctl(struct - - if (is5325(dev) || is5365(dev)) - offset = B53_ARL_SRCH_CTL_25; -- else if (dev->chip_id == BCM5389_DEVICE_ID || is5397_98(dev)) -+ else if (dev->chip_id == BCM5389_DEVICE_ID || is5397_98(dev) || -+ is63xx(dev)) - offset = B53_ARL_SRCH_CTL_89; - else - offset = B53_ARL_SRCH_CTL; - -- b53_read8(dev, B53_ARLIO_PAGE, offset, val); -+ if (is63xx(dev)) { -+ u16 val16; -+ -+ b53_read16(dev, B53_ARLIO_PAGE, offset, &val16); -+ *val = val16 & 0xff; -+ } else { -+ b53_read8(dev, B53_ARLIO_PAGE, offset, val); -+ } - } - - static void b53_write_arl_srch_ctl(struct b53_device *dev, u8 val) -@@ -2052,12 +2060,16 @@ static void b53_write_arl_srch_ctl(struc - - if (is5325(dev) || is5365(dev)) - offset = B53_ARL_SRCH_CTL_25; -- else if (dev->chip_id == BCM5389_DEVICE_ID || is5397_98(dev)) -+ else if (dev->chip_id == BCM5389_DEVICE_ID || is5397_98(dev) || -+ is63xx(dev)) - offset = B53_ARL_SRCH_CTL_89; - else - offset = B53_ARL_SRCH_CTL; - -- b53_write8(dev, B53_ARLIO_PAGE, offset, val); -+ if (is63xx(dev)) -+ b53_write16(dev, B53_ARLIO_PAGE, offset, val); -+ else -+ b53_write8(dev, B53_ARLIO_PAGE, offset, val); - } - - static int b53_arl_search_wait(struct b53_device *dev) -@@ -2111,6 +2123,18 @@ static void b53_arl_search_read_89(struc - b53_arl_to_entry_89(ent, mac_vid, fwd_entry); - } - -+static void b53_arl_search_read_63xx(struct b53_device *dev, u8 idx, -+ struct b53_arl_entry *ent) -+{ -+ u16 fwd_entry; -+ u64 mac_vid; -+ -+ b53_read64(dev, B53_ARLIO_PAGE, B53_ARL_SRCH_RSLT_MACVID_63XX, -+ &mac_vid); -+ b53_read16(dev, B53_ARLIO_PAGE, B53_ARL_SRCH_RSLT_63XX, &fwd_entry); -+ b53_arl_search_to_entry_63xx(ent, mac_vid, fwd_entry); -+} -+ - static void b53_arl_search_read_95(struct b53_device *dev, u8 idx, - struct b53_arl_entry *ent) - { -@@ -2717,6 +2741,12 @@ static const struct b53_arl_ops b53_arl_ - .arl_search_read = b53_arl_search_read_89, - }; - -+static const struct b53_arl_ops b53_arl_ops_63xx = { -+ .arl_read_entry = b53_arl_read_entry_89, -+ .arl_write_entry = b53_arl_write_entry_89, -+ .arl_search_read = b53_arl_search_read_63xx, -+}; -+ - static const struct b53_arl_ops b53_arl_ops_95 = { - .arl_read_entry = b53_arl_read_entry_95, - .arl_write_entry = b53_arl_write_entry_95, -@@ -2886,14 +2916,14 @@ static const struct b53_chip_data b53_sw - .dev_name = "BCM63xx", - .vlans = 4096, - .enabled_ports = 0, /* pdata must provide them */ -- .arl_bins = 4, -- .arl_buckets = 1024, -+ .arl_bins = 1, -+ .arl_buckets = 4096, - .imp_port = 8, - .vta_regs = B53_VTA_REGS_63XX, - .duplex_reg = B53_DUPLEX_STAT_63XX, - .jumbo_pm_reg = B53_JUMBO_PORT_MASK_63XX, - .jumbo_size_reg = B53_JUMBO_MAX_SIZE_63XX, -- .arl_ops = &b53_arl_ops_95, -+ .arl_ops = &b53_arl_ops_63xx, - }, - { - .chip_id = BCM53010_DEVICE_ID, ---- a/drivers/net/dsa/b53/b53_priv.h -+++ b/drivers/net/dsa/b53/b53_priv.h -@@ -409,6 +409,21 @@ static inline void b53_arl_from_entry_89 - *fwd_entry |= ARLTBL_AGE_89; - } - -+static inline void b53_arl_search_to_entry_63xx(struct b53_arl_entry *ent, -+ u64 mac_vid, u16 fwd_entry) -+{ -+ memset(ent, 0, sizeof(*ent)); -+ u64_to_ether_addr(mac_vid, ent->mac); -+ ent->vid = mac_vid >> ARLTBL_VID_S; -+ -+ ent->port = fwd_entry & ARL_SRST_PORT_ID_MASK_63XX; -+ ent->port >>= 1; -+ -+ ent->is_age = !!(fwd_entry & ARL_SRST_AGE_63XX); -+ ent->is_static = !!(fwd_entry & ARL_SRST_STATIC_63XX); -+ ent->is_valid = 1; -+} -+ - static inline void b53_arl_read_entry(struct b53_device *dev, - struct b53_arl_entry *ent, u8 idx) - { ---- a/drivers/net/dsa/b53/b53_regs.h -+++ b/drivers/net/dsa/b53/b53_regs.h -@@ -364,11 +364,13 @@ - #define B53_ARL_SRCH_ADDR_25 0x22 - #define B53_ARL_SRCH_ADDR_65 0x24 - #define B53_ARL_SRCH_ADDR_89 0x31 -+#define B53_ARL_SRCH_ADDR_63XX 0x32 - #define ARL_ADDR_MASK GENMASK(14, 0) - - /* ARL Search MAC/VID Result (64 bit) */ - #define B53_ARL_SRCH_RSTL_0_MACVID 0x60 - #define B53_ARL_SRCH_RSLT_MACVID_89 0x33 -+#define B53_ARL_SRCH_RSLT_MACVID_63XX 0x34 - - /* Single register search result on 5325 */ - #define B53_ARL_SRCH_RSTL_0_MACVID_25 0x24 -@@ -384,6 +386,13 @@ - #define B53_ARL_SRCH_RSTL_MACVID(x) (B53_ARL_SRCH_RSTL_0_MACVID + ((x) * 0x10)) - #define B53_ARL_SRCH_RSTL(x) (B53_ARL_SRCH_RSTL_0 + ((x) * 0x10)) - -+/* 63XX ARL Search Data Result (16 bit) */ -+#define B53_ARL_SRCH_RSLT_63XX 0x3c -+#define ARL_SRST_PORT_ID_MASK_63XX GENMASK(9, 1) -+#define ARL_SRST_TC_MASK_63XX GENMASK(13, 11) -+#define ARL_SRST_AGE_63XX BIT(14) -+#define ARL_SRST_STATIC_63XX BIT(15) -+ - /************************************************************************* - * IEEE 802.1X Registers - *************************************************************************/ diff --git a/target/linux/generic/backport-6.18/613-01-v6.19-net-dsa-b53-fix-VLAN_ID_IDX-write-size-for-BCM5325-65.patch b/target/linux/generic/backport-6.18/613-01-v6.19-net-dsa-b53-fix-VLAN_ID_IDX-write-size-for-BCM5325-65.patch deleted file mode 100644 index d953ea7545..0000000000 --- a/target/linux/generic/backport-6.18/613-01-v6.19-net-dsa-b53-fix-VLAN_ID_IDX-write-size-for-BCM5325-65.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 6f268e275c74dae0536e0b61982a8db25bcf4f16 Mon Sep 17 00:00:00 2001 -From: Jonas Gorski -Date: Fri, 28 Nov 2025 09:06:19 +0100 -Subject: [PATCH] net: dsa: b53: fix VLAN_ID_IDX write size for BCM5325/65 -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Since BCM5325 and BCM5365 only support up to 256 VLANs, the VLAN_ID_IDX -register is only 8 bit wide, not 16 bit, so use an appropriate accessor. - -Fixes: c45655386e53 ("net: dsa: b53: add support for FDB operations on 5325/5365") -Reviewed-by: Florian Fainelli -Tested-by: Álvaro Fernández Rojas -Signed-off-by: Jonas Gorski -Link: https://patch.msgid.link/20251128080625.27181-2-jonas.gorski@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/dsa/b53/b53_common.c | 8 ++++++-- - 1 file changed, 6 insertions(+), 2 deletions(-) - ---- a/drivers/net/dsa/b53/b53_common.c -+++ b/drivers/net/dsa/b53/b53_common.c -@@ -1946,8 +1946,12 @@ static int b53_arl_op(struct b53_device - - /* Perform a read for the given MAC and VID */ - b53_write48(dev, B53_ARLIO_PAGE, B53_MAC_ADDR_IDX, mac); -- if (!is5325m(dev)) -- b53_write16(dev, B53_ARLIO_PAGE, B53_VLAN_ID_IDX, vid); -+ if (!is5325m(dev)) { -+ if (is5325(dev) || is5365(dev)) -+ b53_write8(dev, B53_ARLIO_PAGE, B53_VLAN_ID_IDX, vid); -+ else -+ b53_write16(dev, B53_ARLIO_PAGE, B53_VLAN_ID_IDX, vid); -+ } - - /* Issue a read operation for this MAC */ - ret = b53_arl_rw_op(dev, 1); diff --git a/target/linux/generic/backport-6.18/613-02-v6.19-net-dsa-b53-fix-extracting-VID-from-entry-for-BCM5325-65.patch b/target/linux/generic/backport-6.18/613-02-v6.19-net-dsa-b53-fix-extracting-VID-from-entry-for-BCM5325-65.patch deleted file mode 100644 index 72f81d020f..0000000000 --- a/target/linux/generic/backport-6.18/613-02-v6.19-net-dsa-b53-fix-extracting-VID-from-entry-for-BCM5325-65.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 9316012dd01952f75e37035360138ccc786ef727 Mon Sep 17 00:00:00 2001 -From: Jonas Gorski -Date: Fri, 28 Nov 2025 09:06:20 +0100 -Subject: [PATCH] net: dsa: b53: fix extracting VID from entry for BCM5325/65 -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -BCM5325/65's Entry register uses the highest three bits for -VALID/STATIC/AGE, so shifting by 53 only will add these to -b53_arl_entry::vid. - -So make sure to mask the vid value as well, to not get invalid VIDs. - -Fixes: c45655386e53 ("net: dsa: b53: add support for FDB operations on 5325/5365") -Reviewed-by: Florian Fainelli -Tested-by: Álvaro Fernández Rojas -Signed-off-by: Jonas Gorski -Link: https://patch.msgid.link/20251128080625.27181-3-jonas.gorski@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/dsa/b53/b53_priv.h | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/net/dsa/b53/b53_priv.h -+++ b/drivers/net/dsa/b53/b53_priv.h -@@ -350,7 +350,7 @@ static inline void b53_arl_to_entry_25(s - ent->is_age = !!(mac_vid & ARLTBL_AGE_25); - ent->is_static = !!(mac_vid & ARLTBL_STATIC_25); - u64_to_ether_addr(mac_vid, ent->mac); -- ent->vid = mac_vid >> ARLTBL_VID_S_65; -+ ent->vid = (mac_vid >> ARLTBL_VID_S_65) & ARLTBL_VID_MASK_25; - } - - static inline void b53_arl_to_entry_89(struct b53_arl_entry *ent, diff --git a/target/linux/generic/backport-6.18/613-03-v6.19-net-dsa-b53-use-same-ARL-search-result-offset-for-BCM5325-65.patch b/target/linux/generic/backport-6.18/613-03-v6.19-net-dsa-b53-use-same-ARL-search-result-offset-for-BCM5325-65.patch deleted file mode 100644 index ddb95dfcdc..0000000000 --- a/target/linux/generic/backport-6.18/613-03-v6.19-net-dsa-b53-use-same-ARL-search-result-offset-for-BCM5325-65.patch +++ /dev/null @@ -1,78 +0,0 @@ -From 8e46aacea4264bcb8d4265fb07577afff58ae78d Mon Sep 17 00:00:00 2001 -From: Jonas Gorski -Date: Fri, 28 Nov 2025 09:06:21 +0100 -Subject: [PATCH] net: dsa: b53: use same ARL search result offset for BCM5325/65 -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -BCM5365's search result is at the same offset as BCM5325's search -result, and they (mostly) share the same format, so switch BCM5365 to -BCM5325's arl ops. - -Fixes: c45655386e53 ("net: dsa: b53: add support for FDB operations on 5325/5365") -Reviewed-by: Florian Fainelli -Tested-by: Álvaro Fernández Rojas -Signed-off-by: Jonas Gorski -Link: https://patch.msgid.link/20251128080625.27181-4-jonas.gorski@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/dsa/b53/b53_common.c | 18 +----------------- - drivers/net/dsa/b53/b53_regs.h | 4 +--- - 2 files changed, 2 insertions(+), 20 deletions(-) - ---- a/drivers/net/dsa/b53/b53_common.c -+++ b/drivers/net/dsa/b53/b53_common.c -@@ -2105,16 +2105,6 @@ static void b53_arl_search_read_25(struc - b53_arl_to_entry_25(ent, mac_vid); - } - --static void b53_arl_search_read_65(struct b53_device *dev, u8 idx, -- struct b53_arl_entry *ent) --{ -- u64 mac_vid; -- -- b53_read64(dev, B53_ARLIO_PAGE, B53_ARL_SRCH_RSTL_0_MACVID_65, -- &mac_vid); -- b53_arl_to_entry_25(ent, mac_vid); --} -- - static void b53_arl_search_read_89(struct b53_device *dev, u8 idx, - struct b53_arl_entry *ent) - { -@@ -2733,12 +2723,6 @@ static const struct b53_arl_ops b53_arl_ - .arl_search_read = b53_arl_search_read_25, - }; - --static const struct b53_arl_ops b53_arl_ops_65 = { -- .arl_read_entry = b53_arl_read_entry_25, -- .arl_write_entry = b53_arl_write_entry_25, -- .arl_search_read = b53_arl_search_read_65, --}; -- - static const struct b53_arl_ops b53_arl_ops_89 = { - .arl_read_entry = b53_arl_read_entry_89, - .arl_write_entry = b53_arl_write_entry_89, -@@ -2801,7 +2785,7 @@ static const struct b53_chip_data b53_sw - .arl_buckets = 1024, - .imp_port = 5, - .duplex_reg = B53_DUPLEX_STAT_FE, -- .arl_ops = &b53_arl_ops_65, -+ .arl_ops = &b53_arl_ops_25, - }, - { - .chip_id = BCM5389_DEVICE_ID, ---- a/drivers/net/dsa/b53/b53_regs.h -+++ b/drivers/net/dsa/b53/b53_regs.h -@@ -372,10 +372,8 @@ - #define B53_ARL_SRCH_RSLT_MACVID_89 0x33 - #define B53_ARL_SRCH_RSLT_MACVID_63XX 0x34 - --/* Single register search result on 5325 */ -+/* Single register search result on 5325/5365 */ - #define B53_ARL_SRCH_RSTL_0_MACVID_25 0x24 --/* Single register search result on 5365 */ --#define B53_ARL_SRCH_RSTL_0_MACVID_65 0x30 - - /* ARL Search Data Result (32 bit) */ - #define B53_ARL_SRCH_RSTL_0 0x68 diff --git a/target/linux/generic/backport-6.18/613-04-v6.19-net-dsa-b53-fix-CPU-port-unicast-ARL-entries-for-BCM5325-65.patch b/target/linux/generic/backport-6.18/613-04-v6.19-net-dsa-b53-fix-CPU-port-unicast-ARL-entries-for-BCM5325-65.patch deleted file mode 100644 index 3748892ca8..0000000000 --- a/target/linux/generic/backport-6.18/613-04-v6.19-net-dsa-b53-fix-CPU-port-unicast-ARL-entries-for-BCM5325-65.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 85132103f700b1340fc17df8a981509d17bf4872 Mon Sep 17 00:00:00 2001 -From: Jonas Gorski -Date: Fri, 28 Nov 2025 09:06:22 +0100 -Subject: [PATCH] net: dsa: b53: fix CPU port unicast ARL entries for BCM5325/65 - -On BCM5325 and BCM5365, unicast ARL entries use 8 as the value for the -CPU port, so we need to translate it to/from 5 as used for the CPU port -at most other places. - -Fixes: c45655386e53 ("net: dsa: b53: add support for FDB operations on 5325/5365") -Signed-off-by: Jonas Gorski -Reviewed-by: Florian Fainelli -Link: https://patch.msgid.link/20251128080625.27181-5-jonas.gorski@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/dsa/b53/b53_priv.h | 13 +++++++++---- - 1 file changed, 9 insertions(+), 4 deletions(-) - ---- a/drivers/net/dsa/b53/b53_priv.h -+++ b/drivers/net/dsa/b53/b53_priv.h -@@ -344,12 +344,14 @@ static inline void b53_arl_to_entry_25(s - u64 mac_vid) - { - memset(ent, 0, sizeof(*ent)); -- ent->port = (mac_vid >> ARLTBL_DATA_PORT_ID_S_25) & -- ARLTBL_DATA_PORT_ID_MASK_25; - ent->is_valid = !!(mac_vid & ARLTBL_VALID_25); - ent->is_age = !!(mac_vid & ARLTBL_AGE_25); - ent->is_static = !!(mac_vid & ARLTBL_STATIC_25); - u64_to_ether_addr(mac_vid, ent->mac); -+ ent->port = (mac_vid >> ARLTBL_DATA_PORT_ID_S_25) & -+ ARLTBL_DATA_PORT_ID_MASK_25; -+ if (is_unicast_ether_addr(ent->mac) && ent->port == B53_CPU_PORT) -+ ent->port = B53_CPU_PORT_25; - ent->vid = (mac_vid >> ARLTBL_VID_S_65) & ARLTBL_VID_MASK_25; - } - -@@ -383,8 +385,11 @@ static inline void b53_arl_from_entry_25 - const struct b53_arl_entry *ent) - { - *mac_vid = ether_addr_to_u64(ent->mac); -- *mac_vid |= (u64)(ent->port & ARLTBL_DATA_PORT_ID_MASK_25) << -- ARLTBL_DATA_PORT_ID_S_25; -+ if (is_unicast_ether_addr(ent->mac) && ent->port == B53_CPU_PORT_25) -+ *mac_vid |= (u64)B53_CPU_PORT << ARLTBL_DATA_PORT_ID_S_25; -+ else -+ *mac_vid |= (u64)(ent->port & ARLTBL_DATA_PORT_ID_MASK_25) << -+ ARLTBL_DATA_PORT_ID_S_25; - *mac_vid |= (u64)(ent->vid & ARLTBL_VID_MASK_25) << - ARLTBL_VID_S_65; - if (ent->is_valid) diff --git a/target/linux/generic/backport-6.18/613-05-v6.19-net-dsa-b53-fix-BCM5325-65-ARL-entry-multicast-port-masks.patch b/target/linux/generic/backport-6.18/613-05-v6.19-net-dsa-b53-fix-BCM5325-65-ARL-entry-multicast-port-masks.patch deleted file mode 100644 index c0f5b5d600..0000000000 --- a/target/linux/generic/backport-6.18/613-05-v6.19-net-dsa-b53-fix-BCM5325-65-ARL-entry-multicast-port-masks.patch +++ /dev/null @@ -1,120 +0,0 @@ -From 3b08863469aa6028ac7c3120966f4e2f6051cf6b Mon Sep 17 00:00:00 2001 -From: Jonas Gorski -Date: Fri, 28 Nov 2025 09:06:23 +0100 -Subject: [PATCH] net: dsa: b53: fix BCM5325/65 ARL entry multicast port masks - -We currently use the mask 0xf for writing and reading b53_entry::port, -but this is only correct for unicast ARL entries. Multicast ARL entries -use a bitmask, and 0xf is not enough space for ports > 3, which includes -the CPU port. - -So extend the mask accordingly to also fit port 4 (bit 4) and MII (bit -5). According to the datasheet the multicast port mask is [60:48], -making it 12 bit wide, but bits 60-55 are reserved anyway, and collide -with the priority field at [60:59], so I am not sure if this is valid. -Therefore leave it at the actual used range, [53:48]. - -The ARL search result register differs a bit, and there the mask is only -[52:48], so only spanning the user ports. The MII port bit is -contained in the Search Result Extension register. So create a separate -search result parse function that properly handles this. - -Fixes: c45655386e53 ("net: dsa: b53: add support for FDB operations on 5325/5365") -Reviewed-by: Florian Fainelli -Signed-off-by: Jonas Gorski -Link: https://patch.msgid.link/20251128080625.27181-6-jonas.gorski@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/dsa/b53/b53_common.c | 4 +++- - drivers/net/dsa/b53/b53_priv.h | 25 +++++++++++++++++++++---- - drivers/net/dsa/b53/b53_regs.h | 8 +++++++- - 3 files changed, 31 insertions(+), 6 deletions(-) - ---- a/drivers/net/dsa/b53/b53_common.c -+++ b/drivers/net/dsa/b53/b53_common.c -@@ -2099,10 +2099,12 @@ static void b53_arl_search_read_25(struc - struct b53_arl_entry *ent) - { - u64 mac_vid; -+ u8 ext; - -+ b53_read8(dev, B53_ARLIO_PAGE, B53_ARL_SRCH_RSLT_EXT_25, &ext); - b53_read64(dev, B53_ARLIO_PAGE, B53_ARL_SRCH_RSTL_0_MACVID_25, - &mac_vid); -- b53_arl_to_entry_25(ent, mac_vid); -+ b53_arl_search_to_entry_25(ent, mac_vid, ext); - } - - static void b53_arl_search_read_89(struct b53_device *dev, u8 idx, ---- a/drivers/net/dsa/b53/b53_priv.h -+++ b/drivers/net/dsa/b53/b53_priv.h -@@ -348,8 +348,8 @@ static inline void b53_arl_to_entry_25(s - ent->is_age = !!(mac_vid & ARLTBL_AGE_25); - ent->is_static = !!(mac_vid & ARLTBL_STATIC_25); - u64_to_ether_addr(mac_vid, ent->mac); -- ent->port = (mac_vid >> ARLTBL_DATA_PORT_ID_S_25) & -- ARLTBL_DATA_PORT_ID_MASK_25; -+ ent->port = (mac_vid & ARLTBL_DATA_PORT_ID_MASK_25) >> -+ ARLTBL_DATA_PORT_ID_S_25; - if (is_unicast_ether_addr(ent->mac) && ent->port == B53_CPU_PORT) - ent->port = B53_CPU_PORT_25; - ent->vid = (mac_vid >> ARLTBL_VID_S_65) & ARLTBL_VID_MASK_25; -@@ -388,8 +388,8 @@ static inline void b53_arl_from_entry_25 - if (is_unicast_ether_addr(ent->mac) && ent->port == B53_CPU_PORT_25) - *mac_vid |= (u64)B53_CPU_PORT << ARLTBL_DATA_PORT_ID_S_25; - else -- *mac_vid |= (u64)(ent->port & ARLTBL_DATA_PORT_ID_MASK_25) << -- ARLTBL_DATA_PORT_ID_S_25; -+ *mac_vid |= ((u64)ent->port << ARLTBL_DATA_PORT_ID_S_25) & -+ ARLTBL_DATA_PORT_ID_MASK_25; - *mac_vid |= (u64)(ent->vid & ARLTBL_VID_MASK_25) << - ARLTBL_VID_S_65; - if (ent->is_valid) -@@ -414,6 +414,23 @@ static inline void b53_arl_from_entry_89 - *fwd_entry |= ARLTBL_AGE_89; - } - -+static inline void b53_arl_search_to_entry_25(struct b53_arl_entry *ent, -+ u64 mac_vid, u8 ext) -+{ -+ memset(ent, 0, sizeof(*ent)); -+ ent->is_valid = !!(mac_vid & ARLTBL_VALID_25); -+ ent->is_age = !!(mac_vid & ARLTBL_AGE_25); -+ ent->is_static = !!(mac_vid & ARLTBL_STATIC_25); -+ u64_to_ether_addr(mac_vid, ent->mac); -+ ent->vid = (mac_vid >> ARLTBL_VID_S_65) & ARLTBL_VID_MASK_25; -+ ent->port = (mac_vid & ARL_SRCH_RSLT_PORT_ID_MASK_25) >> -+ ARL_SRCH_RSLT_PORT_ID_S_25; -+ if (is_multicast_ether_addr(ent->mac) && (ext & ARL_SRCH_RSLT_EXT_MC_MII)) -+ ent->port |= BIT(B53_CPU_PORT_25); -+ else if (!is_multicast_ether_addr(ent->mac) && ent->port == B53_CPU_PORT) -+ ent->port = B53_CPU_PORT_25; -+} -+ - static inline void b53_arl_search_to_entry_63xx(struct b53_arl_entry *ent, - u64 mac_vid, u16 fwd_entry) - { ---- a/drivers/net/dsa/b53/b53_regs.h -+++ b/drivers/net/dsa/b53/b53_regs.h -@@ -328,7 +328,7 @@ - #define ARLTBL_VID_MASK_25 0xff - #define ARLTBL_VID_MASK 0xfff - #define ARLTBL_DATA_PORT_ID_S_25 48 --#define ARLTBL_DATA_PORT_ID_MASK_25 0xf -+#define ARLTBL_DATA_PORT_ID_MASK_25 GENMASK_ULL(53, 48) - #define ARLTBL_VID_S_65 53 - #define ARLTBL_AGE_25 BIT_ULL(61) - #define ARLTBL_STATIC_25 BIT_ULL(62) -@@ -374,6 +374,12 @@ - - /* Single register search result on 5325/5365 */ - #define B53_ARL_SRCH_RSTL_0_MACVID_25 0x24 -+#define ARL_SRCH_RSLT_PORT_ID_S_25 48 -+#define ARL_SRCH_RSLT_PORT_ID_MASK_25 GENMASK_ULL(52, 48) -+ -+/* BCM5325/5365 Search result extend register (8 bit) */ -+#define B53_ARL_SRCH_RSLT_EXT_25 0x2c -+#define ARL_SRCH_RSLT_EXT_MC_MII BIT(2) - - /* ARL Search Data Result (32 bit) */ - #define B53_ARL_SRCH_RSTL_0 0x68 diff --git a/target/linux/generic/backport-6.18/613-06-v6.19-net-dsa-b53-fix-BCM5325-65-ARL-entry-VIDs.patch b/target/linux/generic/backport-6.18/613-06-v6.19-net-dsa-b53-fix-BCM5325-65-ARL-entry-VIDs.patch deleted file mode 100644 index a2025f980c..0000000000 --- a/target/linux/generic/backport-6.18/613-06-v6.19-net-dsa-b53-fix-BCM5325-65-ARL-entry-VIDs.patch +++ /dev/null @@ -1,140 +0,0 @@ -From d39514e6a2d14f57830d649e2bf03b49612c2f73 Mon Sep 17 00:00:00 2001 -From: Jonas Gorski -Date: Fri, 28 Nov 2025 09:06:24 +0100 -Subject: [PATCH] net: dsa: b53: fix BCM5325/65 ARL entry VIDs - -BCM5325/65's ARL entry registers do not contain the VID, only the search -result register does. ARL entries have a separate VID entry register for -the index into the VLAN table. - -So make ARL entry accessors use the VID entry registers instead, and -move the VLAN ID field definition to the search register definition. - -Fixes: c45655386e53 ("net: dsa: b53: add support for FDB operations on 5325/5365") -Signed-off-by: Jonas Gorski -Reviewed-by: Florian Fainelli -Link: https://patch.msgid.link/20251128080625.27181-7-jonas.gorski@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/dsa/b53/b53_common.c | 9 +++++++-- - drivers/net/dsa/b53/b53_priv.h | 12 ++++++------ - drivers/net/dsa/b53/b53_regs.h | 7 +++++-- - 3 files changed, 18 insertions(+), 10 deletions(-) - ---- a/drivers/net/dsa/b53/b53_common.c -+++ b/drivers/net/dsa/b53/b53_common.c -@@ -1833,19 +1833,24 @@ static int b53_arl_rw_op(struct b53_devi - static void b53_arl_read_entry_25(struct b53_device *dev, - struct b53_arl_entry *ent, u8 idx) - { -+ u8 vid_entry; - u64 mac_vid; - -+ b53_read8(dev, B53_ARLIO_PAGE, B53_ARLTBL_VID_ENTRY_25(idx), -+ &vid_entry); - b53_read64(dev, B53_ARLIO_PAGE, B53_ARLTBL_MAC_VID_ENTRY(idx), - &mac_vid); -- b53_arl_to_entry_25(ent, mac_vid); -+ b53_arl_to_entry_25(ent, mac_vid, vid_entry); - } - - static void b53_arl_write_entry_25(struct b53_device *dev, - const struct b53_arl_entry *ent, u8 idx) - { -+ u8 vid_entry; - u64 mac_vid; - -- b53_arl_from_entry_25(&mac_vid, ent); -+ b53_arl_from_entry_25(&mac_vid, &vid_entry, ent); -+ b53_write8(dev, B53_ARLIO_PAGE, B53_ARLTBL_VID_ENTRY_25(idx), vid_entry); - b53_write64(dev, B53_ARLIO_PAGE, B53_ARLTBL_MAC_VID_ENTRY(idx), - mac_vid); - } ---- a/drivers/net/dsa/b53/b53_priv.h -+++ b/drivers/net/dsa/b53/b53_priv.h -@@ -341,7 +341,7 @@ static inline void b53_arl_to_entry(stru - } - - static inline void b53_arl_to_entry_25(struct b53_arl_entry *ent, -- u64 mac_vid) -+ u64 mac_vid, u8 vid_entry) - { - memset(ent, 0, sizeof(*ent)); - ent->is_valid = !!(mac_vid & ARLTBL_VALID_25); -@@ -352,7 +352,7 @@ static inline void b53_arl_to_entry_25(s - ARLTBL_DATA_PORT_ID_S_25; - if (is_unicast_ether_addr(ent->mac) && ent->port == B53_CPU_PORT) - ent->port = B53_CPU_PORT_25; -- ent->vid = (mac_vid >> ARLTBL_VID_S_65) & ARLTBL_VID_MASK_25; -+ ent->vid = vid_entry; - } - - static inline void b53_arl_to_entry_89(struct b53_arl_entry *ent, -@@ -381,7 +381,7 @@ static inline void b53_arl_from_entry(u6 - *fwd_entry |= ARLTBL_AGE; - } - --static inline void b53_arl_from_entry_25(u64 *mac_vid, -+static inline void b53_arl_from_entry_25(u64 *mac_vid, u8 *vid_entry, - const struct b53_arl_entry *ent) - { - *mac_vid = ether_addr_to_u64(ent->mac); -@@ -390,14 +390,13 @@ static inline void b53_arl_from_entry_25 - else - *mac_vid |= ((u64)ent->port << ARLTBL_DATA_PORT_ID_S_25) & - ARLTBL_DATA_PORT_ID_MASK_25; -- *mac_vid |= (u64)(ent->vid & ARLTBL_VID_MASK_25) << -- ARLTBL_VID_S_65; - if (ent->is_valid) - *mac_vid |= ARLTBL_VALID_25; - if (ent->is_static) - *mac_vid |= ARLTBL_STATIC_25; - if (ent->is_age) - *mac_vid |= ARLTBL_AGE_25; -+ *vid_entry = ent->vid; - } - - static inline void b53_arl_from_entry_89(u64 *mac_vid, u32 *fwd_entry, -@@ -422,7 +421,8 @@ static inline void b53_arl_search_to_ent - ent->is_age = !!(mac_vid & ARLTBL_AGE_25); - ent->is_static = !!(mac_vid & ARLTBL_STATIC_25); - u64_to_ether_addr(mac_vid, ent->mac); -- ent->vid = (mac_vid >> ARLTBL_VID_S_65) & ARLTBL_VID_MASK_25; -+ ent->vid = (mac_vid & ARL_SRCH_RSLT_VID_MASK_25) >> -+ ARL_SRCH_RSLT_VID_S_25; - ent->port = (mac_vid & ARL_SRCH_RSLT_PORT_ID_MASK_25) >> - ARL_SRCH_RSLT_PORT_ID_S_25; - if (is_multicast_ether_addr(ent->mac) && (ext & ARL_SRCH_RSLT_EXT_MC_MII)) ---- a/drivers/net/dsa/b53/b53_regs.h -+++ b/drivers/net/dsa/b53/b53_regs.h -@@ -325,11 +325,9 @@ - #define B53_ARLTBL_MAC_VID_ENTRY(n) ((0x10 * (n)) + 0x10) - #define ARLTBL_MAC_MASK 0xffffffffffffULL - #define ARLTBL_VID_S 48 --#define ARLTBL_VID_MASK_25 0xff - #define ARLTBL_VID_MASK 0xfff - #define ARLTBL_DATA_PORT_ID_S_25 48 - #define ARLTBL_DATA_PORT_ID_MASK_25 GENMASK_ULL(53, 48) --#define ARLTBL_VID_S_65 53 - #define ARLTBL_AGE_25 BIT_ULL(61) - #define ARLTBL_STATIC_25 BIT_ULL(62) - #define ARLTBL_VALID_25 BIT_ULL(63) -@@ -349,6 +347,9 @@ - #define ARLTBL_STATIC_89 BIT(14) - #define ARLTBL_VALID_89 BIT(15) - -+/* BCM5325/BCM565 ARL Table VID Entry N Registers (8 bit) */ -+#define B53_ARLTBL_VID_ENTRY_25(n) ((0x2 * (n)) + 0x30) -+ - /* Maximum number of bin entries in the ARL for all switches */ - #define B53_ARLTBL_MAX_BIN_ENTRIES 4 - -@@ -376,6 +377,8 @@ - #define B53_ARL_SRCH_RSTL_0_MACVID_25 0x24 - #define ARL_SRCH_RSLT_PORT_ID_S_25 48 - #define ARL_SRCH_RSLT_PORT_ID_MASK_25 GENMASK_ULL(52, 48) -+#define ARL_SRCH_RSLT_VID_S_25 53 -+#define ARL_SRCH_RSLT_VID_MASK_25 GENMASK_ULL(60, 53) - - /* BCM5325/5365 Search result extend register (8 bit) */ - #define B53_ARL_SRCH_RSLT_EXT_25 0x2c diff --git a/target/linux/generic/backport-6.18/620-v6.15-ppp-use-IFF_NO_QUEUE-in-virtual-interfaces.patch b/target/linux/generic/backport-6.18/620-v6.15-ppp-use-IFF_NO_QUEUE-in-virtual-interfaces.patch deleted file mode 100644 index 333627af1b..0000000000 --- a/target/linux/generic/backport-6.18/620-v6.15-ppp-use-IFF_NO_QUEUE-in-virtual-interfaces.patch +++ /dev/null @@ -1,79 +0,0 @@ -From: Qingfang Deng -Date: Sat, 1 Mar 2025 21:55:16 +0800 -Subject: [PATCH] ppp: use IFF_NO_QUEUE in virtual interfaces -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -For PPPoE, PPTP, and PPPoL2TP, the start_xmit() function directly -forwards packets to the underlying network stack and never returns -anything other than 1. So these interfaces do not require a qdisc, -and the IFF_NO_QUEUE flag should be set. - -Introduces a direct_xmit flag in struct ppp_channel to indicate when -IFF_NO_QUEUE should be applied. The flag is set in ppp_connect_channel() -for relevant protocols. - -While at it, remove the usused latency member from struct ppp_channel. - -Signed-off-by: Qingfang Deng -Reviewed-by: Toke Høiland-Jørgensen -Link: https://patch.msgid.link/20250301135517.695809-1-dqfext@gmail.com -Signed-off-by: Jakub Kicinski ---- - ---- a/drivers/net/ppp/ppp_generic.c -+++ b/drivers/net/ppp/ppp_generic.c -@@ -3504,6 +3504,10 @@ ppp_connect_channel(struct channel *pch, - ret = -ENOTCONN; - goto outl; - } -+ if (pch->chan->direct_xmit) -+ ppp->dev->priv_flags |= IFF_NO_QUEUE; -+ else -+ ppp->dev->priv_flags &= ~IFF_NO_QUEUE; - spin_unlock_bh(&pch->downl); - if (pch->file.hdrlen > ppp->file.hdrlen) - ppp->file.hdrlen = pch->file.hdrlen; ---- a/drivers/net/ppp/pppoe.c -+++ b/drivers/net/ppp/pppoe.c -@@ -693,6 +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.direct_xmit = true; - - error = ppp_register_net_channel(dev_net(dev), &po->chan); - if (error) { ---- a/drivers/net/ppp/pptp.c -+++ b/drivers/net/ppp/pptp.c -@@ -469,6 +469,7 @@ static int pptp_connect(struct socket *s - po->chan.mtu -= PPTP_HEADER_OVERHEAD; - - po->chan.hdrlen = 2 + sizeof(struct pptp_gre_header); -+ po->chan.direct_xmit = true; - error = ppp_register_channel(&po->chan); - if (error) { - pr_err("PPTP: failed to register PPP channel (%d)\n", error); ---- a/include/linux/ppp_channel.h -+++ b/include/linux/ppp_channel.h -@@ -42,8 +42,7 @@ struct ppp_channel { - int hdrlen; /* amount of headroom channel needs */ - void *ppp; /* opaque to channel */ - int speed; /* transfer rate (bytes/second) */ -- /* the following is not used at present */ -- int latency; /* overhead time in milliseconds */ -+ bool direct_xmit; /* no qdisc, xmit directly */ - }; - - #ifdef __KERNEL__ ---- a/net/l2tp/l2tp_ppp.c -+++ b/net/l2tp/l2tp_ppp.c -@@ -796,6 +796,7 @@ static int pppol2tp_connect(struct socke - po->chan.private = sk; - po->chan.ops = &pppol2tp_chan_ops; - po->chan.mtu = pppol2tp_tunnel_mtu(tunnel); -+ po->chan.direct_xmit = true; - - error = ppp_register_net_channel(sock_net(sk), &po->chan); - if (error) { diff --git a/target/linux/generic/backport-6.18/621-v6.17-ppp-convert-to-percpu-netstats.patch b/target/linux/generic/backport-6.18/621-v6.17-ppp-convert-to-percpu-netstats.patch deleted file mode 100644 index 874d2bfd8a..0000000000 --- a/target/linux/generic/backport-6.18/621-v6.17-ppp-convert-to-percpu-netstats.patch +++ /dev/null @@ -1,126 +0,0 @@ -From 1a3e9b7a6b09e8ab3d2af019e4a392622685855e Mon Sep 17 00:00:00 2001 -From: Qingfang Deng -Date: Tue, 10 Jun 2025 16:32:10 +0800 -Subject: [PATCH] ppp: convert to percpu netstats - -Convert to percpu netstats to avoid lock contention when reading them. - -Signed-off-by: Qingfang Deng -Link: https://patch.msgid.link/20250610083211.909015-1-dqfext@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/ppp/ppp_generic.c | 52 +++++++++++++---------------------- - 1 file changed, 19 insertions(+), 33 deletions(-) - ---- a/drivers/net/ppp/ppp_generic.c -+++ b/drivers/net/ppp/ppp_generic.c -@@ -108,18 +108,6 @@ struct ppp_file { - #define PF_TO_CHANNEL(pf) PF_TO_X(pf, struct channel) - - /* -- * Data structure to hold primary network stats for which -- * we want to use 64 bit storage. Other network stats -- * are stored in dev->stats of the ppp strucute. -- */ --struct ppp_link_stats { -- u64 rx_packets; -- u64 tx_packets; -- u64 rx_bytes; -- u64 tx_bytes; --}; -- --/* - * Data structure describing one ppp unit. - * A ppp unit corresponds to a ppp network interface device - * and represents a multilink bundle. -@@ -162,7 +150,6 @@ struct ppp { - struct bpf_prog *active_filter; /* filter for pkts to reset idle */ - #endif /* CONFIG_PPP_FILTER */ - struct net *ppp_net; /* the net we belong to */ -- struct ppp_link_stats stats64; /* 64 bit network stats */ - }; - - /* -@@ -1541,23 +1528,12 @@ ppp_net_siocdevprivate(struct net_device - static void - ppp_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats64) - { -- struct ppp *ppp = netdev_priv(dev); -- -- ppp_recv_lock(ppp); -- stats64->rx_packets = ppp->stats64.rx_packets; -- stats64->rx_bytes = ppp->stats64.rx_bytes; -- ppp_recv_unlock(ppp); -- -- ppp_xmit_lock(ppp); -- stats64->tx_packets = ppp->stats64.tx_packets; -- stats64->tx_bytes = ppp->stats64.tx_bytes; -- ppp_xmit_unlock(ppp); -- - stats64->rx_errors = dev->stats.rx_errors; - stats64->tx_errors = dev->stats.tx_errors; - stats64->rx_dropped = dev->stats.rx_dropped; - stats64->tx_dropped = dev->stats.tx_dropped; - stats64->rx_length_errors = dev->stats.rx_length_errors; -+ dev_fetch_sw_netstats(stats64, dev->tstats); - } - - static int ppp_dev_init(struct net_device *dev) -@@ -1655,6 +1631,7 @@ static void ppp_setup(struct net_device - dev->type = ARPHRD_PPP; - dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST; - dev->priv_destructor = ppp_dev_priv_destructor; -+ dev->pcpu_stat_type = NETDEV_PCPU_STAT_TSTATS; - netif_keep_dst(dev); - } - -@@ -1800,8 +1777,7 @@ ppp_send_frame(struct ppp *ppp, struct s - #endif /* CONFIG_PPP_FILTER */ - } - -- ++ppp->stats64.tx_packets; -- ppp->stats64.tx_bytes += skb->len - PPP_PROTO_LEN; -+ dev_sw_netstats_tx_add(ppp->dev, 1, skb->len - PPP_PROTO_LEN); - - switch (proto) { - case PPP_IP: -@@ -2479,8 +2455,7 @@ ppp_receive_nonmp_frame(struct ppp *ppp, - break; - } - -- ++ppp->stats64.rx_packets; -- ppp->stats64.rx_bytes += skb->len - 2; -+ dev_sw_netstats_rx_add(ppp->dev, skb->len - PPP_PROTO_LEN); - - npi = proto_to_npindex(proto); - if (npi < 0) { -@@ -3308,14 +3283,25 @@ static void - ppp_get_stats(struct ppp *ppp, struct ppp_stats *st) - { - struct slcompress *vj = ppp->vj; -+ int cpu; - - memset(st, 0, sizeof(*st)); -- st->p.ppp_ipackets = ppp->stats64.rx_packets; -+ for_each_possible_cpu(cpu) { -+ struct pcpu_sw_netstats *p = per_cpu_ptr(ppp->dev->tstats, cpu); -+ u64 rx_packets, rx_bytes, tx_packets, tx_bytes; -+ -+ rx_packets = u64_stats_read(&p->rx_packets); -+ rx_bytes = u64_stats_read(&p->rx_bytes); -+ tx_packets = u64_stats_read(&p->tx_packets); -+ tx_bytes = u64_stats_read(&p->tx_bytes); -+ -+ st->p.ppp_ipackets += rx_packets; -+ st->p.ppp_ibytes += rx_bytes; -+ st->p.ppp_opackets += tx_packets; -+ st->p.ppp_obytes += tx_bytes; -+ } - st->p.ppp_ierrors = ppp->dev->stats.rx_errors; -- st->p.ppp_ibytes = ppp->stats64.rx_bytes; -- st->p.ppp_opackets = ppp->stats64.tx_packets; - st->p.ppp_oerrors = ppp->dev->stats.tx_errors; -- st->p.ppp_obytes = ppp->stats64.tx_bytes; - if (!vj) - return; - st->vj.vjs_packets = vj->sls_o_compressed + vj->sls_o_uncompressed; diff --git a/target/linux/generic/backport-6.18/622-v6.18-ppp-remove-rwlock-usage.patch b/target/linux/generic/backport-6.18/622-v6.18-ppp-remove-rwlock-usage.patch deleted file mode 100644 index f66a522224..0000000000 --- a/target/linux/generic/backport-6.18/622-v6.18-ppp-remove-rwlock-usage.patch +++ /dev/null @@ -1,334 +0,0 @@ -From b8844aab519a154808dbce15a132f3e8f1c34af6 Mon Sep 17 00:00:00 2001 -From: Qingfang Deng -Date: Fri, 22 Aug 2025 09:25:47 +0800 -Subject: [PATCH] ppp: remove rwlock usage - -In struct channel, the upl lock is implemented using rwlock_t, -protecting access to pch->ppp and pch->bridge. - -As previously discussed on the list, using rwlock in the network fast -path is not recommended. -This patch replaces the rwlock with a spinlock for writers, and uses RCU -for readers. - -- pch->ppp and pch->bridge are now declared as __rcu pointers. -- Readers use rcu_dereference_bh() under rcu_read_lock_bh(). -- Writers use spin_lock() to update. - -Signed-off-by: Qingfang Deng -Link: https://patch.msgid.link/20250822012548.6232-1-dqfext@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/ppp/ppp_generic.c | 120 ++++++++++++++++++---------------- - 1 file changed, 63 insertions(+), 57 deletions(-) - ---- a/drivers/net/ppp/ppp_generic.c -+++ b/drivers/net/ppp/ppp_generic.c -@@ -173,11 +173,11 @@ struct channel { - struct ppp_channel *chan; /* public channel data structure */ - struct rw_semaphore chan_sem; /* protects `chan' during chan ioctl */ - spinlock_t downl; /* protects `chan', file.xq dequeue */ -- struct ppp *ppp; /* ppp unit we're connected to */ -+ struct ppp __rcu *ppp; /* ppp unit we're connected to */ - struct net *chan_net; /* the net channel belongs to */ - netns_tracker ns_tracker; - struct list_head clist; /* link in list of channels per unit */ -- rwlock_t upl; /* protects `ppp' and 'bridge' */ -+ spinlock_t upl; /* protects `ppp' and 'bridge' */ - struct channel __rcu *bridge; /* "bridged" ppp channel */ - #ifdef CONFIG_PPP_MULTILINK - u8 avail; /* flag used in multilink stuff */ -@@ -639,34 +639,34 @@ static struct bpf_prog *compat_ppp_get_f - */ - static int ppp_bridge_channels(struct channel *pch, struct channel *pchb) - { -- write_lock_bh(&pch->upl); -- if (pch->ppp || -+ spin_lock(&pch->upl); -+ if (rcu_dereference_protected(pch->ppp, lockdep_is_held(&pch->upl)) || - rcu_dereference_protected(pch->bridge, lockdep_is_held(&pch->upl))) { -- write_unlock_bh(&pch->upl); -+ spin_unlock(&pch->upl); - return -EALREADY; - } - refcount_inc(&pchb->file.refcnt); - rcu_assign_pointer(pch->bridge, pchb); -- write_unlock_bh(&pch->upl); -+ spin_unlock(&pch->upl); - -- write_lock_bh(&pchb->upl); -- if (pchb->ppp || -+ spin_lock(&pchb->upl); -+ if (rcu_dereference_protected(pchb->ppp, lockdep_is_held(&pchb->upl)) || - rcu_dereference_protected(pchb->bridge, lockdep_is_held(&pchb->upl))) { -- write_unlock_bh(&pchb->upl); -+ spin_unlock(&pchb->upl); - goto err_unset; - } - refcount_inc(&pch->file.refcnt); - rcu_assign_pointer(pchb->bridge, pch); -- write_unlock_bh(&pchb->upl); -+ spin_unlock(&pchb->upl); - - return 0; - - err_unset: -- write_lock_bh(&pch->upl); -+ spin_lock(&pch->upl); - /* Re-read pch->bridge with upl held in case it was modified concurrently */ - pchb = rcu_dereference_protected(pch->bridge, lockdep_is_held(&pch->upl)); - RCU_INIT_POINTER(pch->bridge, NULL); -- write_unlock_bh(&pch->upl); -+ spin_unlock(&pch->upl); - synchronize_rcu(); - - if (pchb) -@@ -680,25 +680,25 @@ static int ppp_unbridge_channels(struct - { - struct channel *pchb, *pchbb; - -- write_lock_bh(&pch->upl); -+ spin_lock(&pch->upl); - pchb = rcu_dereference_protected(pch->bridge, lockdep_is_held(&pch->upl)); - if (!pchb) { -- write_unlock_bh(&pch->upl); -+ spin_unlock(&pch->upl); - return -EINVAL; - } - RCU_INIT_POINTER(pch->bridge, NULL); -- write_unlock_bh(&pch->upl); -+ spin_unlock(&pch->upl); - - /* Only modify pchb if phcb->bridge points back to pch. - * If not, it implies that there has been a race unbridging (and possibly - * even rebridging) pchb. We should leave pchb alone to avoid either a - * refcount underflow, or breaking another established bridge instance. - */ -- write_lock_bh(&pchb->upl); -+ spin_lock(&pchb->upl); - pchbb = rcu_dereference_protected(pchb->bridge, lockdep_is_held(&pchb->upl)); - if (pchbb == pch) - RCU_INIT_POINTER(pchb->bridge, NULL); -- write_unlock_bh(&pchb->upl); -+ spin_unlock(&pchb->upl); - - synchronize_rcu(); - -@@ -2144,10 +2144,9 @@ static int ppp_mp_explode(struct ppp *pp - #endif /* CONFIG_PPP_MULTILINK */ - - /* Try to send data out on a channel */ --static void __ppp_channel_push(struct channel *pch) -+static void __ppp_channel_push(struct channel *pch, struct ppp *ppp) - { - struct sk_buff *skb; -- struct ppp *ppp; - - spin_lock(&pch->downl); - if (pch->chan) { -@@ -2166,7 +2165,6 @@ static void __ppp_channel_push(struct ch - spin_unlock(&pch->downl); - /* see if there is anything from the attached unit to be sent */ - if (skb_queue_empty(&pch->file.xq)) { -- ppp = pch->ppp; - if (ppp) - __ppp_xmit_process(ppp, NULL); - } -@@ -2174,15 +2172,18 @@ static void __ppp_channel_push(struct ch - - static void ppp_channel_push(struct channel *pch) - { -- read_lock_bh(&pch->upl); -- if (pch->ppp) { -- (*this_cpu_ptr(pch->ppp->xmit_recursion))++; -- __ppp_channel_push(pch); -- (*this_cpu_ptr(pch->ppp->xmit_recursion))--; -+ struct ppp *ppp; -+ -+ rcu_read_lock_bh(); -+ ppp = rcu_dereference_bh(pch->ppp); -+ if (ppp) { -+ (*this_cpu_ptr(ppp->xmit_recursion))++; -+ __ppp_channel_push(pch, ppp); -+ (*this_cpu_ptr(ppp->xmit_recursion))--; - } else { -- __ppp_channel_push(pch); -+ __ppp_channel_push(pch, NULL); - } -- read_unlock_bh(&pch->upl); -+ rcu_read_unlock_bh(); - } - - /* -@@ -2284,6 +2285,7 @@ void - ppp_input(struct ppp_channel *chan, struct sk_buff *skb) - { - struct channel *pch = chan->ppp; -+ struct ppp *ppp; - int proto; - - if (!pch) { -@@ -2295,18 +2297,19 @@ ppp_input(struct ppp_channel *chan, stru - if (ppp_channel_bridge_input(pch, skb)) - return; - -- read_lock_bh(&pch->upl); -+ rcu_read_lock_bh(); -+ ppp = rcu_dereference_bh(pch->ppp); - if (!ppp_decompress_proto(skb)) { - kfree_skb(skb); -- if (pch->ppp) { -- ++pch->ppp->dev->stats.rx_length_errors; -- ppp_receive_error(pch->ppp); -+ if (ppp) { -+ ++ppp->dev->stats.rx_length_errors; -+ ppp_receive_error(ppp); - } - goto done; - } - - proto = PPP_PROTO(skb); -- if (!pch->ppp || proto >= 0xc000 || proto == PPP_CCPFRAG) { -+ if (!ppp || proto >= 0xc000 || proto == PPP_CCPFRAG) { - /* put it on the channel queue */ - skb_queue_tail(&pch->file.rq, skb); - /* drop old frames if queue too long */ -@@ -2315,11 +2318,11 @@ ppp_input(struct ppp_channel *chan, stru - kfree_skb(skb); - wake_up_interruptible(&pch->file.rwait); - } else { -- ppp_do_recv(pch->ppp, skb, pch); -+ ppp_do_recv(ppp, skb, pch); - } - - done: -- read_unlock_bh(&pch->upl); -+ rcu_read_unlock_bh(); - } - - /* Put a 0-length skb in the receive queue as an error indication */ -@@ -2328,20 +2331,22 @@ ppp_input_error(struct ppp_channel *chan - { - struct channel *pch = chan->ppp; - struct sk_buff *skb; -+ struct ppp *ppp; - - if (!pch) - return; - -- read_lock_bh(&pch->upl); -- if (pch->ppp) { -+ rcu_read_lock_bh(); -+ ppp = rcu_dereference_bh(pch->ppp); -+ if (ppp) { - skb = alloc_skb(0, GFP_ATOMIC); - if (skb) { - skb->len = 0; /* probably unnecessary */ - skb->cb[0] = code; -- ppp_do_recv(pch->ppp, skb, pch); -+ ppp_do_recv(ppp, skb, pch); - } - } -- read_unlock_bh(&pch->upl); -+ rcu_read_unlock_bh(); - } - - /* -@@ -2889,7 +2894,6 @@ int ppp_register_net_channel(struct net - - pn = ppp_pernet(net); - -- pch->ppp = NULL; - pch->chan = chan; - pch->chan_net = get_net_track(net, &pch->ns_tracker, GFP_KERNEL); - chan->ppp = pch; -@@ -2900,7 +2904,7 @@ int ppp_register_net_channel(struct net - #endif /* CONFIG_PPP_MULTILINK */ - init_rwsem(&pch->chan_sem); - spin_lock_init(&pch->downl); -- rwlock_init(&pch->upl); -+ spin_lock_init(&pch->upl); - - spin_lock_bh(&pn->all_channels_lock); - pch->file.index = ++pn->last_channel_index; -@@ -2929,13 +2933,15 @@ int ppp_channel_index(struct ppp_channel - int ppp_unit_number(struct ppp_channel *chan) - { - struct channel *pch = chan->ppp; -+ struct ppp *ppp; - int unit = -1; - - if (pch) { -- read_lock_bh(&pch->upl); -- if (pch->ppp) -- unit = pch->ppp->file.index; -- read_unlock_bh(&pch->upl); -+ rcu_read_lock(); -+ ppp = rcu_dereference(pch->ppp); -+ if (ppp) -+ unit = ppp->file.index; -+ rcu_read_unlock(); - } - return unit; - } -@@ -2947,12 +2953,14 @@ char *ppp_dev_name(struct ppp_channel *c - { - struct channel *pch = chan->ppp; - char *name = NULL; -+ struct ppp *ppp; - - if (pch) { -- read_lock_bh(&pch->upl); -- if (pch->ppp && pch->ppp->dev) -- name = pch->ppp->dev->name; -- read_unlock_bh(&pch->upl); -+ rcu_read_lock(); -+ ppp = rcu_dereference(pch->ppp); -+ if (ppp && ppp->dev) -+ name = ppp->dev->name; -+ rcu_read_unlock(); - } - return name; - } -@@ -3475,9 +3483,9 @@ ppp_connect_channel(struct channel *pch, - ppp = ppp_find_unit(pn, unit); - if (!ppp) - goto out; -- write_lock_bh(&pch->upl); -+ spin_lock(&pch->upl); - ret = -EINVAL; -- if (pch->ppp || -+ if (rcu_dereference_protected(pch->ppp, lockdep_is_held(&pch->upl)) || - rcu_dereference_protected(pch->bridge, lockdep_is_held(&pch->upl))) - goto outl; - -@@ -3502,13 +3510,13 @@ ppp_connect_channel(struct channel *pch, - ppp->dev->hard_header_len = hdrlen; - list_add_tail_rcu(&pch->clist, &ppp->channels); - ++ppp->n_channels; -- pch->ppp = ppp; -+ rcu_assign_pointer(pch->ppp, ppp); - refcount_inc(&ppp->file.refcnt); - ppp_unlock(ppp); - ret = 0; - - outl: -- write_unlock_bh(&pch->upl); -+ spin_unlock(&pch->upl); - out: - mutex_unlock(&pn->all_ppp_mutex); - return ret; -@@ -3523,10 +3531,9 @@ ppp_disconnect_channel(struct channel *p - struct ppp *ppp; - int err = -EINVAL; - -- write_lock_bh(&pch->upl); -- ppp = pch->ppp; -- pch->ppp = NULL; -- write_unlock_bh(&pch->upl); -+ spin_lock(&pch->upl); -+ ppp = rcu_replace_pointer(pch->ppp, NULL, lockdep_is_held(&pch->upl)); -+ spin_unlock(&pch->upl); - if (ppp) { - /* remove it from the ppp unit's list */ - ppp_lock(ppp); diff --git a/target/linux/generic/backport-6.18/623-v6.18-pppoe-remove-rwlock-usage.patch b/target/linux/generic/backport-6.18/623-v6.18-pppoe-remove-rwlock-usage.patch deleted file mode 100644 index 619f1cbf77..0000000000 --- a/target/linux/generic/backport-6.18/623-v6.18-pppoe-remove-rwlock-usage.patch +++ /dev/null @@ -1,321 +0,0 @@ -From 72cdc67e7fa74931b055df3a76852bab551f1a04 Mon Sep 17 00:00:00 2001 -From: Qingfang Deng -Date: Thu, 28 Aug 2025 09:20:16 +0800 -Subject: [PATCH] pppoe: remove rwlock usage - -Like ppp_generic.c, convert the PPPoE socket hash table to use RCU for -lookups and a spinlock for updates. This removes rwlock usage and allows -lockless readers on the fast path. - -- Mark hash table and list pointers as __rcu. -- Use spin_lock() to protect writers. -- Readers use rcu_dereference() under rcu_read_lock(). All known callers - of get_item() already hold the RCU read lock, so no additional locking - is needed. -- get_item() now uses refcount_inc_not_zero() instead of sock_hold() to - safely take a reference. This prevents crashes if a socket is already - in the process of being freed (sk_refcnt == 0). -- Set SOCK_RCU_FREE to defer socket freeing until after an RCU grace - period. -- Move skb_queue_purge() into sk_destruct callback to ensure purge - happens after an RCU grace period. - -Signed-off-by: Qingfang Deng -Reviewed-by: Eric Dumazet -Link: https://patch.msgid.link/20250828012018.15922-1-dqfext@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/ppp/pppoe.c | 94 ++++++++++++++++++++++------------------ - include/linux/if_pppox.h | 2 +- - 2 files changed, 54 insertions(+), 42 deletions(-) - ---- a/drivers/net/ppp/pppoe.c -+++ b/drivers/net/ppp/pppoe.c -@@ -100,8 +100,8 @@ struct pppoe_net { - * as well, moreover in case of SMP less locking - * controversy here - */ -- struct pppox_sock *hash_table[PPPOE_HASH_SIZE]; -- rwlock_t hash_lock; -+ struct pppox_sock __rcu *hash_table[PPPOE_HASH_SIZE]; -+ spinlock_t hash_lock; - }; - - /* -@@ -162,13 +162,13 @@ static struct pppox_sock *__get_item(str - int hash = hash_item(sid, addr); - struct pppox_sock *ret; - -- ret = pn->hash_table[hash]; -+ ret = rcu_dereference(pn->hash_table[hash]); - while (ret) { - if (cmp_addr(&ret->pppoe_pa, sid, addr) && - ret->pppoe_ifindex == ifindex) - return ret; - -- ret = ret->next; -+ ret = rcu_dereference(ret->next); - } - - return NULL; -@@ -177,19 +177,20 @@ static struct pppox_sock *__get_item(str - static int __set_item(struct pppoe_net *pn, struct pppox_sock *po) - { - int hash = hash_item(po->pppoe_pa.sid, po->pppoe_pa.remote); -- struct pppox_sock *ret; -+ struct pppox_sock *ret, *first; - -- ret = pn->hash_table[hash]; -+ first = rcu_dereference_protected(pn->hash_table[hash], lockdep_is_held(&pn->hash_lock)); -+ ret = first; - while (ret) { - if (cmp_2_addr(&ret->pppoe_pa, &po->pppoe_pa) && - ret->pppoe_ifindex == po->pppoe_ifindex) - return -EALREADY; - -- ret = ret->next; -+ ret = rcu_dereference_protected(ret->next, lockdep_is_held(&pn->hash_lock)); - } - -- po->next = pn->hash_table[hash]; -- pn->hash_table[hash] = po; -+ RCU_INIT_POINTER(po->next, first); -+ rcu_assign_pointer(pn->hash_table[hash], po); - - return 0; - } -@@ -198,20 +199,24 @@ static void __delete_item(struct pppoe_n - char *addr, int ifindex) - { - int hash = hash_item(sid, addr); -- struct pppox_sock *ret, **src; -+ struct pppox_sock *ret, __rcu **src; - -- ret = pn->hash_table[hash]; -+ ret = rcu_dereference_protected(pn->hash_table[hash], lockdep_is_held(&pn->hash_lock)); - src = &pn->hash_table[hash]; - - while (ret) { - if (cmp_addr(&ret->pppoe_pa, sid, addr) && - ret->pppoe_ifindex == ifindex) { -- *src = ret->next; -+ struct pppox_sock *next; -+ -+ next = rcu_dereference_protected(ret->next, -+ lockdep_is_held(&pn->hash_lock)); -+ rcu_assign_pointer(*src, next); - break; - } - - src = &ret->next; -- ret = ret->next; -+ ret = rcu_dereference_protected(ret->next, lockdep_is_held(&pn->hash_lock)); - } - } - -@@ -225,11 +230,9 @@ static inline struct pppox_sock *get_ite - { - struct pppox_sock *po; - -- read_lock_bh(&pn->hash_lock); - po = __get_item(pn, sid, addr, ifindex); -- if (po) -- sock_hold(sk_pppox(po)); -- read_unlock_bh(&pn->hash_lock); -+ if (po && !refcount_inc_not_zero(&sk_pppox(po)->sk_refcnt)) -+ po = NULL; - - return po; - } -@@ -258,9 +261,9 @@ static inline struct pppox_sock *get_ite - static inline void delete_item(struct pppoe_net *pn, __be16 sid, - char *addr, int ifindex) - { -- write_lock_bh(&pn->hash_lock); -+ spin_lock(&pn->hash_lock); - __delete_item(pn, sid, addr, ifindex); -- write_unlock_bh(&pn->hash_lock); -+ spin_unlock(&pn->hash_lock); - } - - /*************************************************************************** -@@ -276,14 +279,16 @@ static void pppoe_flush_dev(struct net_d - int i; - - pn = pppoe_pernet(dev_net(dev)); -- write_lock_bh(&pn->hash_lock); -+ spin_lock(&pn->hash_lock); - for (i = 0; i < PPPOE_HASH_SIZE; i++) { -- struct pppox_sock *po = pn->hash_table[i]; -+ struct pppox_sock *po = rcu_dereference_protected(pn->hash_table[i], -+ lockdep_is_held(&pn->hash_lock)); - struct sock *sk; - - while (po) { - while (po && po->pppoe_dev != dev) { -- po = po->next; -+ po = rcu_dereference_protected(po->next, -+ lockdep_is_held(&pn->hash_lock)); - } - - if (!po) -@@ -300,7 +305,7 @@ static void pppoe_flush_dev(struct net_d - */ - - sock_hold(sk); -- write_unlock_bh(&pn->hash_lock); -+ spin_unlock(&pn->hash_lock); - lock_sock(sk); - - if (po->pppoe_dev == dev && -@@ -320,11 +325,12 @@ static void pppoe_flush_dev(struct net_d - */ - - BUG_ON(pppoe_pernet(dev_net(dev)) == NULL); -- write_lock_bh(&pn->hash_lock); -- po = pn->hash_table[i]; -+ spin_lock(&pn->hash_lock); -+ po = rcu_dereference_protected(pn->hash_table[i], -+ lockdep_is_held(&pn->hash_lock)); - } - } -- write_unlock_bh(&pn->hash_lock); -+ spin_unlock(&pn->hash_lock); - } - - static int pppoe_device_event(struct notifier_block *this, -@@ -528,6 +534,11 @@ static struct proto pppoe_sk_proto __rea - .obj_size = sizeof(struct pppox_sock), - }; - -+static void pppoe_destruct(struct sock *sk) -+{ -+ skb_queue_purge(&sk->sk_receive_queue); -+} -+ - /*********************************************************************** - * - * Initialize a new struct sock. -@@ -542,11 +553,13 @@ static int pppoe_create(struct net *net, - return -ENOMEM; - - sock_init_data(sock, sk); -+ sock_set_flag(sk, SOCK_RCU_FREE); - - sock->state = SS_UNCONNECTED; - sock->ops = &pppoe_ops; - - sk->sk_backlog_rcv = pppoe_rcv_core; -+ sk->sk_destruct = pppoe_destruct; - sk->sk_state = PPPOX_NONE; - sk->sk_type = SOCK_STREAM; - sk->sk_family = PF_PPPOX; -@@ -599,7 +612,6 @@ static int pppoe_release(struct socket * - sock_orphan(sk); - sock->sk = NULL; - -- skb_queue_purge(&sk->sk_receive_queue); - release_sock(sk); - sock_put(sk); - -@@ -681,9 +693,9 @@ static int pppoe_connect(struct socket * - &sp->sa_addr.pppoe, - sizeof(struct pppoe_addr)); - -- write_lock_bh(&pn->hash_lock); -+ spin_lock(&pn->hash_lock); - error = __set_item(pn, po); -- write_unlock_bh(&pn->hash_lock); -+ spin_unlock(&pn->hash_lock); - if (error < 0) - goto err_put; - -@@ -1052,11 +1064,11 @@ static inline struct pppox_sock *pppoe_g - int i; - - for (i = 0; i < PPPOE_HASH_SIZE; i++) { -- po = pn->hash_table[i]; -+ po = rcu_dereference(pn->hash_table[i]); - while (po) { - if (!pos--) - goto out; -- po = po->next; -+ po = rcu_dereference(po->next); - } - } - -@@ -1065,19 +1077,19 @@ out: - } - - static void *pppoe_seq_start(struct seq_file *seq, loff_t *pos) -- __acquires(pn->hash_lock) -+ __acquires(RCU) - { - struct pppoe_net *pn = pppoe_pernet(seq_file_net(seq)); - loff_t l = *pos; - -- read_lock_bh(&pn->hash_lock); -+ rcu_read_lock(); - return l ? pppoe_get_idx(pn, --l) : SEQ_START_TOKEN; - } - - static void *pppoe_seq_next(struct seq_file *seq, void *v, loff_t *pos) - { - struct pppoe_net *pn = pppoe_pernet(seq_file_net(seq)); -- struct pppox_sock *po; -+ struct pppox_sock *po, *next; - - ++*pos; - if (v == SEQ_START_TOKEN) { -@@ -1085,14 +1097,15 @@ static void *pppoe_seq_next(struct seq_f - goto out; - } - po = v; -- if (po->next) -- po = po->next; -+ next = rcu_dereference(po->next); -+ if (next) -+ po = next; - else { - int hash = hash_item(po->pppoe_pa.sid, po->pppoe_pa.remote); - - po = NULL; - while (++hash < PPPOE_HASH_SIZE) { -- po = pn->hash_table[hash]; -+ po = rcu_dereference(pn->hash_table[hash]); - if (po) - break; - } -@@ -1103,10 +1116,9 @@ out: - } - - static void pppoe_seq_stop(struct seq_file *seq, void *v) -- __releases(pn->hash_lock) -+ __releases(RCU) - { -- struct pppoe_net *pn = pppoe_pernet(seq_file_net(seq)); -- read_unlock_bh(&pn->hash_lock); -+ rcu_read_unlock(); - } - - static const struct seq_operations pppoe_seq_ops = { -@@ -1149,7 +1161,7 @@ static __net_init int pppoe_init_net(str - struct pppoe_net *pn = pppoe_pernet(net); - struct proc_dir_entry *pde; - -- rwlock_init(&pn->hash_lock); -+ spin_lock_init(&pn->hash_lock); - - pde = proc_create_net("pppoe", 0444, net->proc_net, - &pppoe_seq_ops, sizeof(struct seq_net_private)); ---- a/include/linux/if_pppox.h -+++ b/include/linux/if_pppox.h -@@ -43,7 +43,7 @@ struct pppox_sock { - /* struct sock must be the first member of pppox_sock */ - struct sock sk; - struct ppp_channel chan; -- struct pppox_sock *next; /* for hash table */ -+ struct pppox_sock __rcu *next; /* for hash table */ - union { - struct pppoe_opt pppoe; - struct pptp_opt pptp; diff --git a/target/linux/generic/backport-6.18/624-v6.18-pppoe-drop-sock-reference-counting-on-fast-path.patch b/target/linux/generic/backport-6.18/624-v6.18-pppoe-drop-sock-reference-counting-on-fast-path.patch deleted file mode 100644 index 2637621042..0000000000 --- a/target/linux/generic/backport-6.18/624-v6.18-pppoe-drop-sock-reference-counting-on-fast-path.patch +++ /dev/null @@ -1,124 +0,0 @@ -From 4f54dff818d7b5b1d84becd5d90bc46e6233c0d7 Mon Sep 17 00:00:00 2001 -From: Qingfang Deng -Date: Thu, 28 Aug 2025 09:20:17 +0800 -Subject: [PATCH] pppoe: drop sock reference counting on fast path - -Now that PPPoE sockets are freed via RCU (SOCK_RCU_FREE), it is no longer -necessary to take a reference count when looking up sockets on the receive -path. Readers are protected by RCU, so the socket memory remains valid -until after a grace period. - -Convert fast-path lookups to avoid refcounting: - - Replace get_item() and sk_receive_skb() in pppoe_rcv() with - __get_item() and __sk_receive_skb(). - - Rework get_item_by_addr() into __get_item_by_addr() (no refcount and - move RCU lock into pppoe_ioctl) - - Remove unnecessary sock_put() calls. - -This avoids cacheline bouncing from atomic reference counting and improves -performance on the receive fast path. - -Signed-off-by: Qingfang Deng -Reviewed-by: Eric Dumazet -Link: https://patch.msgid.link/20250828012018.15922-2-dqfext@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/ppp/pppoe.c | 35 +++++++++++++---------------------- - 1 file changed, 13 insertions(+), 22 deletions(-) - ---- a/drivers/net/ppp/pppoe.c -+++ b/drivers/net/ppp/pppoe.c -@@ -237,8 +237,8 @@ static inline struct pppox_sock *get_ite - return po; - } - --static inline struct pppox_sock *get_item_by_addr(struct net *net, -- struct sockaddr_pppox *sp) -+static inline struct pppox_sock *__get_item_by_addr(struct net *net, -+ struct sockaddr_pppox *sp) - { - struct net_device *dev; - struct pppoe_net *pn; -@@ -246,15 +246,13 @@ static inline struct pppox_sock *get_ite - - int ifindex; - -- rcu_read_lock(); - dev = dev_get_by_name_rcu(net, sp->sa_addr.pppoe.dev); - if (dev) { - ifindex = dev->ifindex; - pn = pppoe_pernet(net); -- pppox_sock = get_item(pn, sp->sa_addr.pppoe.sid, -- sp->sa_addr.pppoe.remote, ifindex); -+ pppox_sock = __get_item(pn, sp->sa_addr.pppoe.sid, -+ sp->sa_addr.pppoe.remote, ifindex); - } -- rcu_read_unlock(); - return pppox_sock; - } - -@@ -384,18 +382,16 @@ static int pppoe_rcv_core(struct sock *s - if (sk->sk_state & PPPOX_BOUND) { - ppp_input(&po->chan, skb); - } else if (sk->sk_state & PPPOX_RELAY) { -- relay_po = get_item_by_addr(sock_net(sk), -- &po->pppoe_relay); -+ relay_po = __get_item_by_addr(sock_net(sk), -+ &po->pppoe_relay); - if (relay_po == NULL) - goto abort_kfree; - - if ((sk_pppox(relay_po)->sk_state & PPPOX_CONNECTED) == 0) -- goto abort_put; -+ goto abort_kfree; - - if (!__pppoe_xmit(sk_pppox(relay_po), skb)) -- goto abort_put; -- -- sock_put(sk_pppox(relay_po)); -+ goto abort_kfree; - } else { - if (sock_queue_rcv_skb(sk, skb)) - goto abort_kfree; -@@ -403,9 +399,6 @@ static int pppoe_rcv_core(struct sock *s - - return NET_RX_SUCCESS; - --abort_put: -- sock_put(sk_pppox(relay_po)); -- - abort_kfree: - kfree_skb(skb); - return NET_RX_DROP; -@@ -447,14 +440,11 @@ static int pppoe_rcv(struct sk_buff *skb - ph = pppoe_hdr(skb); - pn = pppoe_pernet(dev_net(dev)); - -- /* Note that get_item does a sock_hold(), so sk_pppox(po) -- * is known to be safe. -- */ -- po = get_item(pn, ph->sid, eth_hdr(skb)->h_source, dev->ifindex); -+ po = __get_item(pn, ph->sid, eth_hdr(skb)->h_source, dev->ifindex); - if (!po) - goto drop; - -- return sk_receive_skb(sk_pppox(po), skb, 0); -+ return __sk_receive_skb(sk_pppox(po), skb, 0, 1, false); - - drop: - kfree_skb(skb); -@@ -820,11 +810,12 @@ static int pppoe_ioctl(struct socket *so - - /* Check that the socket referenced by the address - actually exists. */ -- relay_po = get_item_by_addr(sock_net(sk), &po->pppoe_relay); -+ rcu_read_lock(); -+ relay_po = __get_item_by_addr(sock_net(sk), &po->pppoe_relay); -+ rcu_read_unlock(); - if (!relay_po) - break; - -- sock_put(sk_pppox(relay_po)); - sk->sk_state |= PPPOX_RELAY; - err = 0; - break; diff --git a/target/linux/generic/backport-6.18/626-01-v6.13-net-pse-pd-Add-power-limit-check.patch b/target/linux/generic/backport-6.18/626-01-v6.13-net-pse-pd-Add-power-limit-check.patch deleted file mode 100644 index fbcc3ec3e1..0000000000 --- a/target/linux/generic/backport-6.18/626-01-v6.13-net-pse-pd-Add-power-limit-check.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 6e56a6d47a7fad705a1a1d088237b0858c01a770 Mon Sep 17 00:00:00 2001 -From: Kory Maincent -Date: Fri, 10 Jan 2025 10:40:22 +0100 -Subject: [PATCH] net: pse-pd: Add power limit check - -Checking only the current limit is not sufficient. According to the -standard, voltage can reach up to 57V and current up to 1.92A, which -exceeds the power limit described in the standard (99.9W). Add a power -limit check to prevent this. - -Acked-by: Oleksij Rempel -Signed-off-by: Kory Maincent -Signed-off-by: Paolo Abeni -Signed-off-by: Carlo Szelinsky ---- - drivers/net/pse-pd/pse_core.c | 3 +++ - include/linux/pse-pd/pse.h | 2 ++ - 2 files changed, 5 insertions(+) ---- a/drivers/net/pse-pd/pse_core.c -+++ b/drivers/net/pse-pd/pse_core.c -@@ -868,6 +868,9 @@ int pse_ethtool_set_pw_limit(struct pse_ - int uV, uA, ret; - s64 tmp_64; - -+ if (pw_limit > MAX_PI_PW) -+ return -ERANGE; -+ - ret = regulator_get_voltage(psec->ps); - if (!ret) { - NL_SET_ERR_MSG(extack, ---- a/include/linux/pse-pd/pse.h -+++ b/include/linux/pse-pd/pse.h -@@ -11,6 +11,8 @@ - - /* Maximum current in uA according to IEEE 802.3-2022 Table 145-1 */ - #define MAX_PI_CURRENT 1920000 -+/* Maximum power in mW according to IEEE 802.3-2022 Table 145-16 */ -+#define MAX_PI_PW 99900 - - struct phy_device; - struct pse_controller_dev; diff --git a/target/linux/generic/backport-6.18/626-02-v6.13-net-pse-pd-tps23881-Simplify-function-returns.patch b/target/linux/generic/backport-6.18/626-02-v6.13-net-pse-pd-tps23881-Simplify-function-returns.patch deleted file mode 100644 index fc6d532298..0000000000 --- a/target/linux/generic/backport-6.18/626-02-v6.13-net-pse-pd-tps23881-Simplify-function-returns.patch +++ /dev/null @@ -1,112 +0,0 @@ -From 0b567519d1152de52b29b2da2c47aa0f39a46266 Mon Sep 17 00:00:00 2001 -From: Kory Maincent -Date: Fri, 10 Jan 2025 10:40:23 +0100 -Subject: [PATCH] net: pse-pd: tps23881: Simplify function returns by removing - redundant checks - -Cleaned up several functions in tps23881 by removing redundant checks on -return values at the end of functions. These check has been removed, and -the return statement now directly returns the function result, reducing -the code's complexity and making it more concise. - -Reviewed-by: Andrew Lunn -Acked-by: Oleksij Rempel -Reviewed-by: Kyle Swenson -Signed-off-by: Kory Maincent -Signed-off-by: Paolo Abeni -Signed-off-by: Carlo Szelinsky ---- - drivers/net/pse-pd/tps23881.c | 34 ++++++---------------------------- - 1 file changed, 6 insertions(+), 28 deletions(-) ---- a/drivers/net/pse-pd/tps23881.c -+++ b/drivers/net/pse-pd/tps23881.c -@@ -59,7 +59,6 @@ static int tps23881_pi_enable(struct pse - struct i2c_client *client = priv->client; - u8 chan; - u16 val; -- int ret; - - if (id >= TPS23881_MAX_CHANS) - return -ERANGE; -@@ -78,11 +77,7 @@ static int tps23881_pi_enable(struct pse - val |= BIT(chan + 4); - } - -- ret = i2c_smbus_write_word_data(client, TPS23881_REG_PW_EN, val); -- if (ret) -- return ret; -- -- return 0; -+ return i2c_smbus_write_word_data(client, TPS23881_REG_PW_EN, val); - } - - static int tps23881_pi_disable(struct pse_controller_dev *pcdev, int id) -@@ -91,7 +86,6 @@ static int tps23881_pi_disable(struct ps - struct i2c_client *client = priv->client; - u8 chan; - u16 val; -- int ret; - - if (id >= TPS23881_MAX_CHANS) - return -ERANGE; -@@ -110,11 +104,7 @@ static int tps23881_pi_disable(struct ps - val |= BIT(chan + 8); - } - -- ret = i2c_smbus_write_word_data(client, TPS23881_REG_PW_EN, val); -- if (ret) -- return ret; -- -- return 0; -+ return i2c_smbus_write_word_data(client, TPS23881_REG_PW_EN, val); - } - - static int tps23881_pi_is_enabled(struct pse_controller_dev *pcdev, int id) -@@ -480,7 +470,7 @@ tps23881_write_port_matrix(struct tps238 - struct i2c_client *client = priv->client; - u8 pi_id, lgcl_chan, hw_chan; - u16 val = 0; -- int i, ret; -+ int i; - - for (i = 0; i < port_cnt; i++) { - pi_id = port_matrix[i].pi_id; -@@ -511,11 +501,7 @@ tps23881_write_port_matrix(struct tps238 - } - - /* Write hardware ports matrix */ -- ret = i2c_smbus_write_word_data(client, TPS23881_REG_PORT_MAP, val); -- if (ret) -- return ret; -- -- return 0; -+ return i2c_smbus_write_word_data(client, TPS23881_REG_PORT_MAP, val); - } - - static int -@@ -564,11 +550,7 @@ tps23881_set_ports_conf(struct tps23881_ - val |= BIT(port_matrix[i].lgcl_chan[1]) | - BIT(port_matrix[i].lgcl_chan[1] + 4); - } -- ret = i2c_smbus_write_word_data(client, TPS23881_REG_DET_CLA_EN, val); -- if (ret) -- return ret; -- -- return 0; -+ return i2c_smbus_write_word_data(client, TPS23881_REG_DET_CLA_EN, val); - } - - static int -@@ -594,11 +576,7 @@ tps23881_set_ports_matrix(struct tps2388 - if (ret) - return ret; - -- ret = tps23881_set_ports_conf(priv, port_matrix); -- if (ret) -- return ret; -- -- return 0; -+ return tps23881_set_ports_conf(priv, port_matrix); - } - - static int tps23881_setup_pi_matrix(struct pse_controller_dev *pcdev) diff --git a/target/linux/generic/backport-6.18/626-03-v6.13-net-pse-pd-tps23881-Use-helpers-to-calculate-bit-offset.patch b/target/linux/generic/backport-6.18/626-03-v6.13-net-pse-pd-tps23881-Use-helpers-to-calculate-bit-offset.patch deleted file mode 100644 index 3b390ea565..0000000000 --- a/target/linux/generic/backport-6.18/626-03-v6.13-net-pse-pd-tps23881-Use-helpers-to-calculate-bit-offset.patch +++ /dev/null @@ -1,190 +0,0 @@ -From 4c2bab507eb7edc8e497e91b9b7f05d76d7e32bb Mon Sep 17 00:00:00 2001 -From: Kory Maincent -Date: Fri, 10 Jan 2025 10:40:24 +0100 -Subject: [PATCH] net: pse-pd: tps23881: Use helpers to calculate bit offset - for a channel - -This driver frequently follows a pattern where two registers are read or -written in a single operation, followed by calculating the bit offset for -a specific channel. - -Introduce helpers to streamline this process and reduce code redundancy, -making the codebase cleaner and more maintainable. - -Acked-by: Oleksij Rempel -Signed-off-by: Kory Maincent -Signed-off-by: Paolo Abeni -Signed-off-by: Carlo Szelinsky ---- - drivers/net/pse-pd/tps23881.c | 107 ++++++++++++++++++++++------------ - 1 file changed, 69 insertions(+), 38 deletions(-) ---- a/drivers/net/pse-pd/tps23881.c -+++ b/drivers/net/pse-pd/tps23881.c -@@ -53,6 +53,55 @@ static struct tps23881_priv *to_tps23881 - return container_of(pcdev, struct tps23881_priv, pcdev); - } - -+/* -+ * Helper to extract a value from a u16 register value, which is made of two -+ * u8 registers. The function calculates the bit offset based on the channel -+ * and extracts the relevant bits using a provided field mask. -+ * -+ * @param reg_val: The u16 register value (composed of two u8 registers). -+ * @param chan: The channel number (0-7). -+ * @param field_offset: The base bit offset to apply (e.g., 0 or 4). -+ * @param field_mask: The mask to apply to extract the required bits. -+ * @return: The extracted value for the specific channel. -+ */ -+static u16 tps23881_calc_val(u16 reg_val, u8 chan, u8 field_offset, -+ u16 field_mask) -+{ -+ if (chan >= 4) -+ reg_val >>= 8; -+ -+ return (reg_val >> field_offset) & field_mask; -+} -+ -+/* -+ * Helper to combine individual channel values into a u16 register value. -+ * The function sets the value for a specific channel in the appropriate -+ * position. -+ * -+ * @param reg_val: The current u16 register value. -+ * @param chan: The channel number (0-7). -+ * @param field_offset: The base bit offset to apply (e.g., 0 or 4). -+ * @param field_mask: The mask to apply for the field (e.g., 0x0F). -+ * @param field_val: The value to set for the specific channel (masked by -+ * field_mask). -+ * @return: The updated u16 register value with the channel value set. -+ */ -+static u16 tps23881_set_val(u16 reg_val, u8 chan, u8 field_offset, -+ u16 field_mask, u16 field_val) -+{ -+ field_val &= field_mask; -+ -+ if (chan < 4) { -+ reg_val &= ~(field_mask << field_offset); -+ reg_val |= (field_val << field_offset); -+ } else { -+ reg_val &= ~(field_mask << (field_offset + 8)); -+ reg_val |= (field_val << (field_offset + 8)); -+ } -+ -+ return reg_val; -+} -+ - static int tps23881_pi_enable(struct pse_controller_dev *pcdev, int id) - { - struct tps23881_priv *priv = to_tps23881_priv(pcdev); -@@ -64,17 +113,12 @@ static int tps23881_pi_enable(struct pse - return -ERANGE; - - chan = priv->port[id].chan[0]; -- if (chan < 4) -- val = BIT(chan); -- else -- val = BIT(chan + 4); -+ val = tps23881_set_val(0, chan, 0, BIT(chan % 4), BIT(chan % 4)); - - if (priv->port[id].is_4p) { - chan = priv->port[id].chan[1]; -- if (chan < 4) -- val |= BIT(chan); -- else -- val |= BIT(chan + 4); -+ val = tps23881_set_val(val, chan, 0, BIT(chan % 4), -+ BIT(chan % 4)); - } - - return i2c_smbus_write_word_data(client, TPS23881_REG_PW_EN, val); -@@ -91,17 +135,12 @@ static int tps23881_pi_disable(struct ps - return -ERANGE; - - chan = priv->port[id].chan[0]; -- if (chan < 4) -- val = BIT(chan + 4); -- else -- val = BIT(chan + 8); -+ val = tps23881_set_val(0, chan, 4, BIT(chan % 4), BIT(chan % 4)); - - if (priv->port[id].is_4p) { - chan = priv->port[id].chan[1]; -- if (chan < 4) -- val |= BIT(chan + 4); -- else -- val |= BIT(chan + 8); -+ val = tps23881_set_val(val, chan, 4, BIT(chan % 4), -+ BIT(chan % 4)); - } - - return i2c_smbus_write_word_data(client, TPS23881_REG_PW_EN, val); -@@ -113,6 +152,7 @@ static int tps23881_pi_is_enabled(struct - struct i2c_client *client = priv->client; - bool enabled; - u8 chan; -+ u16 val; - int ret; - - ret = i2c_smbus_read_word_data(client, TPS23881_REG_PW_STATUS); -@@ -120,17 +160,13 @@ static int tps23881_pi_is_enabled(struct - return ret; - - chan = priv->port[id].chan[0]; -- if (chan < 4) -- enabled = ret & BIT(chan); -- else -- enabled = ret & BIT(chan + 4); -+ val = tps23881_calc_val(ret, chan, 0, BIT(chan % 4)); -+ enabled = !!(val); - - if (priv->port[id].is_4p) { - chan = priv->port[id].chan[1]; -- if (chan < 4) -- enabled &= !!(ret & BIT(chan)); -- else -- enabled &= !!(ret & BIT(chan + 4)); -+ val = tps23881_calc_val(ret, chan, 0, BIT(chan % 4)); -+ enabled &= !!(val); - } - - /* Return enabled status only if both channel are on this state */ -@@ -146,6 +182,7 @@ static int tps23881_ethtool_get_status(s - struct i2c_client *client = priv->client; - bool enabled, delivering; - u8 chan; -+ u16 val; - int ret; - - ret = i2c_smbus_read_word_data(client, TPS23881_REG_PW_STATUS); -@@ -153,23 +190,17 @@ static int tps23881_ethtool_get_status(s - return ret; - - chan = priv->port[id].chan[0]; -- if (chan < 4) { -- enabled = ret & BIT(chan); -- delivering = ret & BIT(chan + 4); -- } else { -- enabled = ret & BIT(chan + 4); -- delivering = ret & BIT(chan + 8); -- } -+ val = tps23881_calc_val(ret, chan, 0, BIT(chan % 4)); -+ enabled = !!(val); -+ val = tps23881_calc_val(ret, chan, 4, BIT(chan % 4)); -+ delivering = !!(val); - - if (priv->port[id].is_4p) { - chan = priv->port[id].chan[1]; -- if (chan < 4) { -- enabled &= !!(ret & BIT(chan)); -- delivering &= !!(ret & BIT(chan + 4)); -- } else { -- enabled &= !!(ret & BIT(chan + 4)); -- delivering &= !!(ret & BIT(chan + 8)); -- } -+ val = tps23881_calc_val(ret, chan, 0, BIT(chan % 4)); -+ enabled &= !!(val); -+ val = tps23881_calc_val(ret, chan, 4, BIT(chan % 4)); -+ delivering &= !!(val); - } - - /* Return delivering status only if both channel are on this state */ diff --git a/target/linux/generic/backport-6.18/626-04-v6.13-net-pse-pd-tps23881-Add-missing-configuration-register.patch b/target/linux/generic/backport-6.18/626-04-v6.13-net-pse-pd-tps23881-Add-missing-configuration-register.patch deleted file mode 100644 index c00dd9050f..0000000000 --- a/target/linux/generic/backport-6.18/626-04-v6.13-net-pse-pd-tps23881-Add-missing-configuration-register.patch +++ /dev/null @@ -1,63 +0,0 @@ -From f3cb3c7bea0c08e821d8e9dfd2f96acd1db7c24e Mon Sep 17 00:00:00 2001 -From: Kory Maincent -Date: Fri, 10 Jan 2025 10:40:25 +0100 -Subject: [PATCH] net: pse-pd: tps23881: Add missing configuration register - after disable - -When setting the PWOFF register, the controller resets multiple -configuration registers. This patch ensures these registers are -reconfigured as needed following a disable operation. - -Acked-by: Oleksij Rempel -Signed-off-by: Kory Maincent -Signed-off-by: Paolo Abeni -Signed-off-by: Carlo Szelinsky ---- - drivers/net/pse-pd/tps23881.c | 30 +++++++++++++++++++++++++++++- - 1 file changed, 29 insertions(+), 1 deletion(-) ---- a/drivers/net/pse-pd/tps23881.c -+++ b/drivers/net/pse-pd/tps23881.c -@@ -130,6 +130,7 @@ static int tps23881_pi_disable(struct ps - struct i2c_client *client = priv->client; - u8 chan; - u16 val; -+ int ret; - - if (id >= TPS23881_MAX_CHANS) - return -ERANGE; -@@ -143,7 +144,34 @@ static int tps23881_pi_disable(struct ps - BIT(chan % 4)); - } - -- return i2c_smbus_write_word_data(client, TPS23881_REG_PW_EN, val); -+ ret = i2c_smbus_write_word_data(client, TPS23881_REG_PW_EN, val); -+ if (ret) -+ return ret; -+ -+ /* PWOFF command resets lots of register which need to be -+ * configured again. According to the datasheet "It may take upwards -+ * of 5ms after PWOFFn command for all register values to be updated" -+ */ -+ mdelay(5); -+ -+ /* Enable detection and classification */ -+ ret = i2c_smbus_read_word_data(client, TPS23881_REG_DET_CLA_EN); -+ if (ret < 0) -+ return ret; -+ -+ chan = priv->port[id].chan[0]; -+ val = tps23881_set_val(ret, chan, 0, BIT(chan % 4), BIT(chan % 4)); -+ val = tps23881_set_val(val, chan, 4, BIT(chan % 4), BIT(chan % 4)); -+ -+ if (priv->port[id].is_4p) { -+ chan = priv->port[id].chan[1]; -+ val = tps23881_set_val(ret, chan, 0, BIT(chan % 4), -+ BIT(chan % 4)); -+ val = tps23881_set_val(val, chan, 4, BIT(chan % 4), -+ BIT(chan % 4)); -+ } -+ -+ return i2c_smbus_write_word_data(client, TPS23881_REG_DET_CLA_EN, val); - } - - static int tps23881_pi_is_enabled(struct pse_controller_dev *pcdev, int id) diff --git a/target/linux/generic/backport-6.18/626-05-v6.13-net-pse-pd-Split-ethtool_get_status-into-multiple-callbacks.patch b/target/linux/generic/backport-6.18/626-05-v6.13-net-pse-pd-Split-ethtool_get_status-into-multiple-callbacks.patch deleted file mode 100644 index 71a2379e3b..0000000000 --- a/target/linux/generic/backport-6.18/626-05-v6.13-net-pse-pd-Split-ethtool_get_status-into-multiple-callbacks.patch +++ /dev/null @@ -1,714 +0,0 @@ -From 3e9dbfec499807767d03592ebdf19d9c15fd495b Mon Sep 17 00:00:00 2001 -From: Kory Maincent -Date: Fri, 10 Jan 2025 10:40:27 +0100 -Subject: [PATCH] net: pse-pd: Split ethtool_get_status into multiple callbacks - -The ethtool_get_status callback currently handles all status and PSE -information within a single function. This approach has two key -drawbacks: - -1. If the core requires some information for purposes other than - ethtool_get_status, redundant code will be needed to fetch the same - data from the driver (like is_enabled). - -2. Drivers currently have access to all information passed to ethtool. - New variables will soon be added to ethtool status, such as PSE ID, - power domain IDs, and budget evaluation strategies, which are meant - to be managed solely by the core. Drivers should not have the ability - to modify these variables. - -To resolve these issues, ethtool_get_status has been split into multiple -callbacks, with each handling a specific piece of information required -by ethtool or the core. - -Signed-off-by: Kory Maincent -Signed-off-by: Paolo Abeni -Signed-off-by: Carlo Szelinsky ---- - drivers/net/pse-pd/pd692x0.c | 153 ++++++++++++++++++++--------- - drivers/net/pse-pd/pse_core.c | 83 ++++++++++++++-- - drivers/net/pse-pd/pse_regulator.c | 26 +++-- - drivers/net/pse-pd/tps23881.c | 60 ++++++++--- - include/linux/pse-pd/pse.h | 87 +++++++++++++--- - net/ethtool/pse-pd.c | 8 +- - 6 files changed, 323 insertions(+), 94 deletions(-) - ---- a/drivers/net/pse-pd/pd692x0.c -+++ b/drivers/net/pse-pd/pd692x0.c -@@ -517,21 +517,38 @@ pd692x0_pse_ext_state_map[] = { - { /* sentinel */ } - }; - --static void --pd692x0_get_ext_state(struct ethtool_c33_pse_ext_state_info *c33_ext_state_info, -- u32 status_code) -+static int -+pd692x0_pi_get_ext_state(struct pse_controller_dev *pcdev, int id, -+ struct pse_ext_state_info *ext_state_info) - { -+ struct ethtool_c33_pse_ext_state_info *c33_ext_state_info; - const struct pd692x0_pse_ext_state_mapping *ext_state_map; -+ struct pd692x0_priv *priv = to_pd692x0_priv(pcdev); -+ struct pd692x0_msg msg, buf = {0}; -+ int ret; -+ -+ ret = pd692x0_fw_unavailable(priv); -+ if (ret) -+ return ret; - -+ msg = pd692x0_msg_template_list[PD692X0_MSG_GET_PORT_STATUS]; -+ msg.sub[2] = id; -+ ret = pd692x0_sendrecv_msg(priv, &msg, &buf); -+ if (ret < 0) -+ return ret; -+ -+ c33_ext_state_info = &ext_state_info->c33_ext_state_info; - ext_state_map = pd692x0_pse_ext_state_map; - while (ext_state_map->status_code) { -- if (ext_state_map->status_code == status_code) { -+ if (ext_state_map->status_code == buf.sub[0]) { - c33_ext_state_info->c33_pse_ext_state = ext_state_map->pse_ext_state; - c33_ext_state_info->__c33_pse_ext_substate = ext_state_map->pse_ext_substate; -- return; -+ return 0; - } - ext_state_map++; - } -+ -+ return 0; - } - - struct pd692x0_class_pw { -@@ -613,35 +630,36 @@ static int pd692x0_pi_set_pw_from_table( - } - - static int --pd692x0_pi_get_pw_ranges(struct pse_control_status *st) -+pd692x0_pi_get_pw_limit_ranges(struct pse_controller_dev *pcdev, int id, -+ struct pse_pw_limit_ranges *pw_limit_ranges) - { -+ struct ethtool_c33_pse_pw_limit_range *c33_pw_limit_ranges; - const struct pd692x0_class_pw *pw_table; - int i; - - pw_table = pd692x0_class_pw_table; -- st->c33_pw_limit_ranges = kcalloc(PD692X0_CLASS_PW_TABLE_SIZE, -- sizeof(struct ethtool_c33_pse_pw_limit_range), -- GFP_KERNEL); -- if (!st->c33_pw_limit_ranges) -+ c33_pw_limit_ranges = kcalloc(PD692X0_CLASS_PW_TABLE_SIZE, -+ sizeof(*c33_pw_limit_ranges), -+ GFP_KERNEL); -+ if (!c33_pw_limit_ranges) - return -ENOMEM; - - for (i = 0; i < PD692X0_CLASS_PW_TABLE_SIZE; i++, pw_table++) { -- st->c33_pw_limit_ranges[i].min = pw_table->class_pw; -- st->c33_pw_limit_ranges[i].max = pw_table->class_pw + pw_table->max_added_class_pw; -+ c33_pw_limit_ranges[i].min = pw_table->class_pw; -+ c33_pw_limit_ranges[i].max = pw_table->class_pw + -+ pw_table->max_added_class_pw; - } - -- st->c33_pw_limit_nb_ranges = i; -- return 0; -+ pw_limit_ranges->c33_pw_limit_ranges = c33_pw_limit_ranges; -+ return i; - } - --static int pd692x0_ethtool_get_status(struct pse_controller_dev *pcdev, -- unsigned long id, -- struct netlink_ext_ack *extack, -- struct pse_control_status *status) -+static int -+pd692x0_pi_get_admin_state(struct pse_controller_dev *pcdev, int id, -+ struct pse_admin_state *admin_state) - { - struct pd692x0_priv *priv = to_pd692x0_priv(pcdev); - struct pd692x0_msg msg, buf = {0}; -- u32 class; - int ret; - - ret = pd692x0_fw_unavailable(priv); -@@ -654,39 +672,65 @@ static int pd692x0_ethtool_get_status(st - if (ret < 0) - return ret; - -- /* Compare Port Status (Communication Protocol Document par. 7.1) */ -- if ((buf.sub[0] & 0xf0) == 0x80 || (buf.sub[0] & 0xf0) == 0x90) -- status->c33_pw_status = ETHTOOL_C33_PSE_PW_D_STATUS_DELIVERING; -- else if (buf.sub[0] == 0x1b || buf.sub[0] == 0x22) -- status->c33_pw_status = ETHTOOL_C33_PSE_PW_D_STATUS_SEARCHING; -- else if (buf.sub[0] == 0x12) -- status->c33_pw_status = ETHTOOL_C33_PSE_PW_D_STATUS_FAULT; -- else -- status->c33_pw_status = ETHTOOL_C33_PSE_PW_D_STATUS_DISABLED; -- - if (buf.sub[1]) -- status->c33_admin_state = ETHTOOL_C33_PSE_ADMIN_STATE_ENABLED; -+ admin_state->c33_admin_state = -+ ETHTOOL_C33_PSE_ADMIN_STATE_ENABLED; - else -- status->c33_admin_state = ETHTOOL_C33_PSE_ADMIN_STATE_DISABLED; -+ admin_state->c33_admin_state = -+ ETHTOOL_C33_PSE_ADMIN_STATE_DISABLED; - -- priv->admin_state[id] = status->c33_admin_state; -+ priv->admin_state[id] = admin_state->c33_admin_state; - -- pd692x0_get_ext_state(&status->c33_ext_state_info, buf.sub[0]); -- status->c33_actual_pw = (buf.data[0] << 4 | buf.data[1]) * 100; -+ return 0; -+} - -- msg = pd692x0_msg_template_list[PD692X0_MSG_GET_PORT_PARAM]; -+static int -+pd692x0_pi_get_pw_status(struct pse_controller_dev *pcdev, int id, -+ struct pse_pw_status *pw_status) -+{ -+ struct pd692x0_priv *priv = to_pd692x0_priv(pcdev); -+ struct pd692x0_msg msg, buf = {0}; -+ int ret; -+ -+ ret = pd692x0_fw_unavailable(priv); -+ if (ret) -+ return ret; -+ -+ msg = pd692x0_msg_template_list[PD692X0_MSG_GET_PORT_STATUS]; - msg.sub[2] = id; -- memset(&buf, 0, sizeof(buf)); - ret = pd692x0_sendrecv_msg(priv, &msg, &buf); - if (ret < 0) - return ret; - -- ret = pd692x0_pi_get_pw_from_table(buf.data[0], buf.data[1]); -- if (ret < 0) -+ /* Compare Port Status (Communication Protocol Document par. 7.1) */ -+ if ((buf.sub[0] & 0xf0) == 0x80 || (buf.sub[0] & 0xf0) == 0x90) -+ pw_status->c33_pw_status = -+ ETHTOOL_C33_PSE_PW_D_STATUS_DELIVERING; -+ else if (buf.sub[0] == 0x1b || buf.sub[0] == 0x22) -+ pw_status->c33_pw_status = -+ ETHTOOL_C33_PSE_PW_D_STATUS_SEARCHING; -+ else if (buf.sub[0] == 0x12) -+ pw_status->c33_pw_status = -+ ETHTOOL_C33_PSE_PW_D_STATUS_FAULT; -+ else -+ pw_status->c33_pw_status = -+ ETHTOOL_C33_PSE_PW_D_STATUS_DISABLED; -+ -+ return 0; -+} -+ -+static int -+pd692x0_pi_get_pw_class(struct pse_controller_dev *pcdev, int id) -+{ -+ struct pd692x0_priv *priv = to_pd692x0_priv(pcdev); -+ struct pd692x0_msg msg, buf = {0}; -+ u32 class; -+ int ret; -+ -+ ret = pd692x0_fw_unavailable(priv); -+ if (ret) - return ret; -- status->c33_avail_pw_limit = ret; - -- memset(&buf, 0, sizeof(buf)); - msg = pd692x0_msg_template_list[PD692X0_MSG_GET_PORT_CLASS]; - msg.sub[2] = id; - ret = pd692x0_sendrecv_msg(priv, &msg, &buf); -@@ -695,13 +739,29 @@ static int pd692x0_ethtool_get_status(st - - class = buf.data[3] >> 4; - if (class <= 8) -- status->c33_pw_class = class; -+ return class; -+ -+ return 0; -+} -+ -+static int -+pd692x0_pi_get_actual_pw(struct pse_controller_dev *pcdev, int id) -+{ -+ struct pd692x0_priv *priv = to_pd692x0_priv(pcdev); -+ struct pd692x0_msg msg, buf = {0}; -+ int ret; -+ -+ ret = pd692x0_fw_unavailable(priv); -+ if (ret) -+ return ret; - -- ret = pd692x0_pi_get_pw_ranges(status); -+ msg = pd692x0_msg_template_list[PD692X0_MSG_GET_PORT_STATUS]; -+ msg.sub[2] = id; -+ ret = pd692x0_sendrecv_msg(priv, &msg, &buf); - if (ret < 0) - return ret; - -- return 0; -+ return (buf.data[0] << 4 | buf.data[1]) * 100; - } - - static struct pd692x0_msg_ver pd692x0_get_sw_version(struct pd692x0_priv *priv) -@@ -1038,13 +1098,18 @@ static int pd692x0_pi_set_pw_limit(struc - - static const struct pse_controller_ops pd692x0_ops = { - .setup_pi_matrix = pd692x0_setup_pi_matrix, -- .ethtool_get_status = pd692x0_ethtool_get_status, -+ .pi_get_admin_state = pd692x0_pi_get_admin_state, -+ .pi_get_pw_status = pd692x0_pi_get_pw_status, -+ .pi_get_ext_state = pd692x0_pi_get_ext_state, -+ .pi_get_pw_class = pd692x0_pi_get_pw_class, -+ .pi_get_actual_pw = pd692x0_pi_get_actual_pw, - .pi_enable = pd692x0_pi_enable, - .pi_disable = pd692x0_pi_disable, - .pi_is_enabled = pd692x0_pi_is_enabled, - .pi_get_voltage = pd692x0_pi_get_voltage, - .pi_get_pw_limit = pd692x0_pi_get_pw_limit, - .pi_set_pw_limit = pd692x0_pi_set_pw_limit, -+ .pi_get_pw_limit_ranges = pd692x0_pi_get_pw_limit_ranges, - }; - - #define PD692X0_FW_LINE_MAX_SZ 0xff ---- a/drivers/net/pse-pd/pse_core.c -+++ b/drivers/net/pse-pd/pse_core.c -@@ -443,6 +443,13 @@ int pse_controller_register(struct pse_c - if (!pcdev->nr_lines) - pcdev->nr_lines = 1; - -+ if (!pcdev->ops->pi_get_admin_state || -+ !pcdev->ops->pi_get_pw_status) { -+ dev_err(pcdev->dev, -+ "Mandatory status report callbacks are missing"); -+ return -EINVAL; -+ } -+ - ret = of_load_pse_pis(pcdev); - if (ret) - return ret; -@@ -745,25 +752,81 @@ EXPORT_SYMBOL_GPL(of_pse_control_get); - */ - int pse_ethtool_get_status(struct pse_control *psec, - struct netlink_ext_ack *extack, -- struct pse_control_status *status) -+ struct ethtool_pse_control_status *status) - { -+ struct pse_admin_state admin_state = {0}; -+ struct pse_pw_status pw_status = {0}; - const struct pse_controller_ops *ops; - struct pse_controller_dev *pcdev; -- int err; -+ int ret; - - pcdev = psec->pcdev; - ops = pcdev->ops; -- if (!ops->ethtool_get_status) { -- NL_SET_ERR_MSG(extack, -- "PSE driver does not support status report"); -- return -EOPNOTSUPP; -+ mutex_lock(&pcdev->lock); -+ ret = ops->pi_get_admin_state(pcdev, psec->id, &admin_state); -+ if (ret) -+ goto out; -+ status->podl_admin_state = admin_state.podl_admin_state; -+ status->c33_admin_state = admin_state.c33_admin_state; -+ -+ ret = ops->pi_get_pw_status(pcdev, psec->id, &pw_status); -+ if (ret) -+ goto out; -+ status->podl_pw_status = pw_status.podl_pw_status; -+ status->c33_pw_status = pw_status.c33_pw_status; -+ -+ if (ops->pi_get_ext_state) { -+ struct pse_ext_state_info ext_state_info = {0}; -+ -+ ret = ops->pi_get_ext_state(pcdev, psec->id, -+ &ext_state_info); -+ if (ret) -+ goto out; -+ -+ memcpy(&status->c33_ext_state_info, -+ &ext_state_info.c33_ext_state_info, -+ sizeof(status->c33_ext_state_info)); - } - -- mutex_lock(&pcdev->lock); -- err = ops->ethtool_get_status(pcdev, psec->id, extack, status); -- mutex_unlock(&pcdev->lock); -+ if (ops->pi_get_pw_class) { -+ ret = ops->pi_get_pw_class(pcdev, psec->id); -+ if (ret < 0) -+ goto out; -+ -+ status->c33_pw_class = ret; -+ } -+ -+ if (ops->pi_get_actual_pw) { -+ ret = ops->pi_get_actual_pw(pcdev, psec->id); -+ if (ret < 0) -+ goto out; -+ -+ status->c33_actual_pw = ret; -+ } -+ -+ if (ops->pi_get_pw_limit) { -+ ret = ops->pi_get_pw_limit(pcdev, psec->id); -+ if (ret < 0) -+ goto out; -+ -+ status->c33_avail_pw_limit = ret; -+ } -+ -+ if (ops->pi_get_pw_limit_ranges) { -+ struct pse_pw_limit_ranges pw_limit_ranges = {0}; - -- return err; -+ ret = ops->pi_get_pw_limit_ranges(pcdev, psec->id, -+ &pw_limit_ranges); -+ if (ret < 0) -+ goto out; -+ -+ status->c33_pw_limit_ranges = -+ pw_limit_ranges.c33_pw_limit_ranges; -+ status->c33_pw_limit_nb_ranges = ret; -+ } -+out: -+ mutex_unlock(&psec->pcdev->lock); -+ return ret; - } - EXPORT_SYMBOL_GPL(pse_ethtool_get_status); - ---- a/drivers/net/pse-pd/pse_regulator.c -+++ b/drivers/net/pse-pd/pse_regulator.c -@@ -60,9 +60,19 @@ pse_reg_pi_is_enabled(struct pse_control - } - - static int --pse_reg_ethtool_get_status(struct pse_controller_dev *pcdev, unsigned long id, -- struct netlink_ext_ack *extack, -- struct pse_control_status *status) -+pse_reg_pi_get_admin_state(struct pse_controller_dev *pcdev, int id, -+ struct pse_admin_state *admin_state) -+{ -+ struct pse_reg_priv *priv = to_pse_reg(pcdev); -+ -+ admin_state->podl_admin_state = priv->admin_state; -+ -+ return 0; -+} -+ -+static int -+pse_reg_pi_get_pw_status(struct pse_controller_dev *pcdev, int id, -+ struct pse_pw_status *pw_status) - { - struct pse_reg_priv *priv = to_pse_reg(pcdev); - int ret; -@@ -72,18 +82,18 @@ pse_reg_ethtool_get_status(struct pse_co - return ret; - - if (!ret) -- status->podl_pw_status = ETHTOOL_PODL_PSE_PW_D_STATUS_DISABLED; -+ pw_status->podl_pw_status = -+ ETHTOOL_PODL_PSE_PW_D_STATUS_DISABLED; - else -- status->podl_pw_status = -+ pw_status->podl_pw_status = - ETHTOOL_PODL_PSE_PW_D_STATUS_DELIVERING; - -- status->podl_admin_state = priv->admin_state; -- - return 0; - } - - static const struct pse_controller_ops pse_reg_ops = { -- .ethtool_get_status = pse_reg_ethtool_get_status, -+ .pi_get_admin_state = pse_reg_pi_get_admin_state, -+ .pi_get_pw_status = pse_reg_pi_get_pw_status, - .pi_enable = pse_reg_pi_enable, - .pi_is_enabled = pse_reg_pi_is_enabled, - .pi_disable = pse_reg_pi_disable, ---- a/drivers/net/pse-pd/tps23881.c -+++ b/drivers/net/pse-pd/tps23881.c -@@ -201,14 +201,13 @@ static int tps23881_pi_is_enabled(struct - return enabled; - } - --static int tps23881_ethtool_get_status(struct pse_controller_dev *pcdev, -- unsigned long id, -- struct netlink_ext_ack *extack, -- struct pse_control_status *status) -+static int -+tps23881_pi_get_admin_state(struct pse_controller_dev *pcdev, int id, -+ struct pse_admin_state *admin_state) - { - struct tps23881_priv *priv = to_tps23881_priv(pcdev); - struct i2c_client *client = priv->client; -- bool enabled, delivering; -+ bool enabled; - u8 chan; - u16 val; - int ret; -@@ -220,28 +219,56 @@ static int tps23881_ethtool_get_status(s - chan = priv->port[id].chan[0]; - val = tps23881_calc_val(ret, chan, 0, BIT(chan % 4)); - enabled = !!(val); -- val = tps23881_calc_val(ret, chan, 4, BIT(chan % 4)); -- delivering = !!(val); - - if (priv->port[id].is_4p) { - chan = priv->port[id].chan[1]; - val = tps23881_calc_val(ret, chan, 0, BIT(chan % 4)); - enabled &= !!(val); -+ } -+ -+ /* Return enabled status only if both channel are on this state */ -+ if (enabled) -+ admin_state->c33_admin_state = -+ ETHTOOL_C33_PSE_ADMIN_STATE_ENABLED; -+ else -+ admin_state->c33_admin_state = -+ ETHTOOL_C33_PSE_ADMIN_STATE_DISABLED; -+ -+ return 0; -+} -+ -+static int -+tps23881_pi_get_pw_status(struct pse_controller_dev *pcdev, int id, -+ struct pse_pw_status *pw_status) -+{ -+ struct tps23881_priv *priv = to_tps23881_priv(pcdev); -+ struct i2c_client *client = priv->client; -+ bool delivering; -+ u8 chan; -+ u16 val; -+ int ret; -+ -+ ret = i2c_smbus_read_word_data(client, TPS23881_REG_PW_STATUS); -+ if (ret < 0) -+ return ret; -+ -+ chan = priv->port[id].chan[0]; -+ val = tps23881_calc_val(ret, chan, 4, BIT(chan % 4)); -+ delivering = !!(val); -+ -+ if (priv->port[id].is_4p) { -+ chan = priv->port[id].chan[1]; - val = tps23881_calc_val(ret, chan, 4, BIT(chan % 4)); - delivering &= !!(val); - } - - /* Return delivering status only if both channel are on this state */ - if (delivering) -- status->c33_pw_status = ETHTOOL_C33_PSE_PW_D_STATUS_DELIVERING; -- else -- status->c33_pw_status = ETHTOOL_C33_PSE_PW_D_STATUS_DISABLED; -- -- /* Return enabled status only if both channel are on this state */ -- if (enabled) -- status->c33_admin_state = ETHTOOL_C33_PSE_ADMIN_STATE_ENABLED; -+ pw_status->c33_pw_status = -+ ETHTOOL_C33_PSE_PW_D_STATUS_DELIVERING; - else -- status->c33_admin_state = ETHTOOL_C33_PSE_ADMIN_STATE_DISABLED; -+ pw_status->c33_pw_status = -+ ETHTOOL_C33_PSE_PW_D_STATUS_DISABLED; - - return 0; - } -@@ -664,7 +691,8 @@ static const struct pse_controller_ops t - .pi_enable = tps23881_pi_enable, - .pi_disable = tps23881_pi_disable, - .pi_is_enabled = tps23881_pi_is_enabled, -- .ethtool_get_status = tps23881_ethtool_get_status, -+ .pi_get_admin_state = tps23881_pi_get_admin_state, -+ .pi_get_pw_status = tps23881_pi_get_pw_status, - }; - - static const char fw_parity_name[] = "ti/tps23881/tps23881-parity-14.bin"; ---- a/include/linux/pse-pd/pse.h -+++ b/include/linux/pse-pd/pse.h -@@ -31,7 +31,52 @@ struct pse_control_config { - }; - - /** -- * struct pse_control_status - PSE control/channel status. -+ * struct pse_admin_state - PSE operational state -+ * -+ * @podl_admin_state: operational state of the PoDL PSE -+ * functions. IEEE 802.3-2018 30.15.1.1.2 aPoDLPSEAdminState -+ * @c33_admin_state: operational state of the PSE -+ * functions. IEEE 802.3-2022 30.9.1.1.2 aPSEAdminState -+ */ -+struct pse_admin_state { -+ enum ethtool_podl_pse_admin_state podl_admin_state; -+ enum ethtool_c33_pse_admin_state c33_admin_state; -+}; -+ -+/** -+ * struct pse_pw_status - PSE power detection status -+ * -+ * @podl_pw_status: power detection status of the PoDL PSE. -+ * IEEE 802.3-2018 30.15.1.1.3 aPoDLPSEPowerDetectionStatus: -+ * @c33_pw_status: power detection status of the PSE. -+ * IEEE 802.3-2022 30.9.1.1.5 aPSEPowerDetectionStatus: -+ */ -+struct pse_pw_status { -+ enum ethtool_podl_pse_pw_d_status podl_pw_status; -+ enum ethtool_c33_pse_pw_d_status c33_pw_status; -+}; -+ -+/** -+ * struct pse_ext_state_info - PSE extended state information -+ * -+ * @c33_ext_state_info: extended state information of the PSE -+ */ -+struct pse_ext_state_info { -+ struct ethtool_c33_pse_ext_state_info c33_ext_state_info; -+}; -+ -+/** -+ * struct pse_pw_limit_ranges - PSE power limit configuration range -+ * -+ * @c33_pw_limit_ranges: supported power limit configuration range. The driver -+ * is in charge of the memory allocation. -+ */ -+struct pse_pw_limit_ranges { -+ struct ethtool_c33_pse_pw_limit_range *c33_pw_limit_ranges; -+}; -+ -+/** -+ * struct ethtool_pse_control_status - PSE control/channel status. - * - * @podl_admin_state: operational state of the PoDL PSE - * functions. IEEE 802.3-2018 30.15.1.1.2 aPoDLPSEAdminState -@@ -49,11 +94,11 @@ struct pse_control_config { - * @c33_avail_pw_limit: available power limit of the PSE in mW - * IEEE 802.3-2022 145.2.5.4 pse_avail_pwr - * @c33_pw_limit_ranges: supported power limit configuration range. The driver -- * is in charge of the memory allocation. -+ * is in charge of the memory allocation - * @c33_pw_limit_nb_ranges: number of supported power limit configuration - * ranges - */ --struct pse_control_status { -+struct ethtool_pse_control_status { - enum ethtool_podl_pse_admin_state podl_admin_state; - enum ethtool_podl_pse_pw_d_status podl_pw_status; - enum ethtool_c33_pse_admin_state c33_admin_state; -@@ -69,22 +114,37 @@ struct pse_control_status { - /** - * struct pse_controller_ops - PSE controller driver callbacks - * -- * @ethtool_get_status: get PSE control status for ethtool interface - * @setup_pi_matrix: setup PI matrix of the PSE controller -+ * @pi_get_admin_state: Get the operational state of the PSE PI. This ops -+ * is mandatory. -+ * @pi_get_pw_status: Get the power detection status of the PSE PI. This -+ * ops is mandatory. -+ * @pi_get_ext_state: Get the extended state of the PSE PI. -+ * @pi_get_pw_class: Get the power class of the PSE PI. -+ * @pi_get_actual_pw: Get actual power of the PSE PI in mW. - * @pi_is_enabled: Return 1 if the PSE PI is enabled, 0 if not. - * May also return negative errno. - * @pi_enable: Configure the PSE PI as enabled. - * @pi_disable: Configure the PSE PI as disabled. - * @pi_get_voltage: Return voltage similarly to get_voltage regulator -- * callback. -- * @pi_get_pw_limit: Get the configured power limit of the PSE PI. -- * @pi_set_pw_limit: Configure the power limit of the PSE PI. -+ * callback in uV. -+ * @pi_get_pw_limit: Get the configured power limit of the PSE PI in mW. -+ * @pi_set_pw_limit: Configure the power limit of the PSE PI in mW. -+ * @pi_get_pw_limit_ranges: Get the supported power limit configuration -+ * range. The driver is in charge of the memory -+ * allocation and should return the number of -+ * ranges. - */ - struct pse_controller_ops { -- int (*ethtool_get_status)(struct pse_controller_dev *pcdev, -- unsigned long id, struct netlink_ext_ack *extack, -- struct pse_control_status *status); - int (*setup_pi_matrix)(struct pse_controller_dev *pcdev); -+ int (*pi_get_admin_state)(struct pse_controller_dev *pcdev, int id, -+ struct pse_admin_state *admin_state); -+ int (*pi_get_pw_status)(struct pse_controller_dev *pcdev, int id, -+ struct pse_pw_status *pw_status); -+ int (*pi_get_ext_state)(struct pse_controller_dev *pcdev, int id, -+ struct pse_ext_state_info *ext_state_info); -+ int (*pi_get_pw_class)(struct pse_controller_dev *pcdev, int id); -+ int (*pi_get_actual_pw)(struct pse_controller_dev *pcdev, int id); - int (*pi_is_enabled)(struct pse_controller_dev *pcdev, int id); - int (*pi_enable)(struct pse_controller_dev *pcdev, int id); - int (*pi_disable)(struct pse_controller_dev *pcdev, int id); -@@ -93,12 +153,15 @@ struct pse_controller_ops { - int id); - int (*pi_set_pw_limit)(struct pse_controller_dev *pcdev, - int id, int max_mW); -+ int (*pi_get_pw_limit_ranges)(struct pse_controller_dev *pcdev, int id, -+ struct pse_pw_limit_ranges *pw_limit_ranges); - }; - - struct module; - struct device_node; - struct of_phandle_args; - struct pse_control; -+struct ethtool_pse_control_status; - - /* PSE PI pairset pinout can either be Alternative A or Alternative B */ - enum pse_pi_pairset_pinout { -@@ -175,7 +238,7 @@ void pse_control_put(struct pse_control - - int pse_ethtool_get_status(struct pse_control *psec, - struct netlink_ext_ack *extack, -- struct pse_control_status *status); -+ struct ethtool_pse_control_status *status); - int pse_ethtool_set_config(struct pse_control *psec, - struct netlink_ext_ack *extack, - const struct pse_control_config *config); -@@ -201,7 +264,7 @@ static inline void pse_control_put(struc - - static inline int pse_ethtool_get_status(struct pse_control *psec, - struct netlink_ext_ack *extack, -- struct pse_control_status *status) -+ struct ethtool_pse_control_status *status) - { - return -EOPNOTSUPP; - } ---- a/net/ethtool/pse-pd.c -+++ b/net/ethtool/pse-pd.c -@@ -19,7 +19,7 @@ struct pse_req_info { - - struct pse_reply_data { - struct ethnl_reply_data base; -- struct pse_control_status status; -+ struct ethtool_pse_control_status status; - }; - - #define PSE_REPDATA(__reply_base) \ -@@ -80,7 +80,7 @@ static int pse_reply_size(const struct e - const struct ethnl_reply_data *reply_base) - { - const struct pse_reply_data *data = PSE_REPDATA(reply_base); -- const struct pse_control_status *st = &data->status; -+ const struct ethtool_pse_control_status *st = &data->status; - int len = 0; - - if (st->podl_admin_state > 0) -@@ -114,7 +114,7 @@ static int pse_reply_size(const struct e - } - - static int pse_put_pw_limit_ranges(struct sk_buff *skb, -- const struct pse_control_status *st) -+ const struct ethtool_pse_control_status *st) - { - const struct ethtool_c33_pse_pw_limit_range *pw_limit_ranges; - int i; -@@ -146,7 +146,7 @@ static int pse_fill_reply(struct sk_buff - const struct ethnl_reply_data *reply_base) - { - const struct pse_reply_data *data = PSE_REPDATA(reply_base); -- const struct pse_control_status *st = &data->status; -+ const struct ethtool_pse_control_status *st = &data->status; - - if (st->podl_admin_state > 0 && - nla_put_u32(skb, ETHTOOL_A_PODL_PSE_ADMIN_STATE, diff --git a/target/linux/generic/backport-6.18/626-06-v6.13-net-pse-pd-Remove-is_enabled-callback-from-drivers.patch b/target/linux/generic/backport-6.18/626-06-v6.13-net-pse-pd-Remove-is_enabled-callback-from-drivers.patch deleted file mode 100644 index dd7a20efaa..0000000000 --- a/target/linux/generic/backport-6.18/626-06-v6.13-net-pse-pd-Remove-is_enabled-callback-from-drivers.patch +++ /dev/null @@ -1,184 +0,0 @@ -From 4640a1f0d8f2246f34d6e74330d7e7d2cf75605b Mon Sep 17 00:00:00 2001 -From: Kory Maincent -Date: Fri, 10 Jan 2025 10:40:28 +0100 -Subject: [PATCH] net: pse-pd: Remove is_enabled callback from drivers - -The is_enabled callback is now redundant as the admin_state can be obtained -directly from the driver and provides the same information. - -To simplify functionality, the core will handle this internally, making -the is_enabled callback unnecessary at the driver level. Remove the -callback from all drivers. - -Acked-by: Oleksij Rempel -Signed-off-by: Kory Maincent -Signed-off-by: Paolo Abeni -Signed-off-by: Carlo Szelinsky ---- - drivers/net/pse-pd/pd692x0.c | 26 -------------------------- - drivers/net/pse-pd/pse_core.c | 13 +++++++++++-- - drivers/net/pse-pd/pse_regulator.c | 9 --------- - drivers/net/pse-pd/tps23881.c | 28 ---------------------------- - include/linux/pse-pd/pse.h | 3 --- - 5 files changed, 11 insertions(+), 68 deletions(-) - ---- a/drivers/net/pse-pd/pd692x0.c -+++ b/drivers/net/pse-pd/pd692x0.c -@@ -431,31 +431,6 @@ static int pd692x0_pi_disable(struct pse - return 0; - } - --static int pd692x0_pi_is_enabled(struct pse_controller_dev *pcdev, int id) --{ -- struct pd692x0_priv *priv = to_pd692x0_priv(pcdev); -- struct pd692x0_msg msg, buf = {0}; -- int ret; -- -- ret = pd692x0_fw_unavailable(priv); -- if (ret) -- return ret; -- -- msg = pd692x0_msg_template_list[PD692X0_MSG_GET_PORT_STATUS]; -- msg.sub[2] = id; -- ret = pd692x0_sendrecv_msg(priv, &msg, &buf); -- if (ret < 0) -- return ret; -- -- if (buf.sub[1]) { -- priv->admin_state[id] = ETHTOOL_C33_PSE_ADMIN_STATE_ENABLED; -- return 1; -- } else { -- priv->admin_state[id] = ETHTOOL_C33_PSE_ADMIN_STATE_DISABLED; -- return 0; -- } --} -- - struct pd692x0_pse_ext_state_mapping { - u32 status_code; - enum ethtool_c33_pse_ext_state pse_ext_state; -@@ -1105,7 +1080,6 @@ static const struct pse_controller_ops p - .pi_get_actual_pw = pd692x0_pi_get_actual_pw, - .pi_enable = pd692x0_pi_enable, - .pi_disable = pd692x0_pi_disable, -- .pi_is_enabled = pd692x0_pi_is_enabled, - .pi_get_voltage = pd692x0_pi_get_voltage, - .pi_get_pw_limit = pd692x0_pi_get_pw_limit, - .pi_set_pw_limit = pd692x0_pi_set_pw_limit, ---- a/drivers/net/pse-pd/pse_core.c -+++ b/drivers/net/pse-pd/pse_core.c -@@ -210,16 +210,25 @@ out: - static int pse_pi_is_enabled(struct regulator_dev *rdev) - { - struct pse_controller_dev *pcdev = rdev_get_drvdata(rdev); -+ struct pse_admin_state admin_state = {0}; - const struct pse_controller_ops *ops; - int id, ret; - - ops = pcdev->ops; -- if (!ops->pi_is_enabled) -+ if (!ops->pi_get_admin_state) - return -EOPNOTSUPP; - - id = rdev_get_id(rdev); - mutex_lock(&pcdev->lock); -- ret = ops->pi_is_enabled(pcdev, id); -+ ret = ops->pi_get_admin_state(pcdev, id, &admin_state); -+ if (ret) -+ goto out; -+ -+ if (admin_state.podl_admin_state == ETHTOOL_PODL_PSE_ADMIN_STATE_ENABLED || -+ admin_state.c33_admin_state == ETHTOOL_C33_PSE_ADMIN_STATE_ENABLED) -+ ret = 1; -+ -+out: - mutex_unlock(&pcdev->lock); - - return ret; ---- a/drivers/net/pse-pd/pse_regulator.c -+++ b/drivers/net/pse-pd/pse_regulator.c -@@ -52,14 +52,6 @@ pse_reg_pi_disable(struct pse_controller - } - - static int --pse_reg_pi_is_enabled(struct pse_controller_dev *pcdev, int id) --{ -- struct pse_reg_priv *priv = to_pse_reg(pcdev); -- -- return regulator_is_enabled(priv->ps); --} -- --static int - pse_reg_pi_get_admin_state(struct pse_controller_dev *pcdev, int id, - struct pse_admin_state *admin_state) - { -@@ -95,7 +87,6 @@ static const struct pse_controller_ops p - .pi_get_admin_state = pse_reg_pi_get_admin_state, - .pi_get_pw_status = pse_reg_pi_get_pw_status, - .pi_enable = pse_reg_pi_enable, -- .pi_is_enabled = pse_reg_pi_is_enabled, - .pi_disable = pse_reg_pi_disable, - }; - ---- a/drivers/net/pse-pd/tps23881.c -+++ b/drivers/net/pse-pd/tps23881.c -@@ -174,33 +174,6 @@ static int tps23881_pi_disable(struct ps - return i2c_smbus_write_word_data(client, TPS23881_REG_DET_CLA_EN, val); - } - --static int tps23881_pi_is_enabled(struct pse_controller_dev *pcdev, int id) --{ -- struct tps23881_priv *priv = to_tps23881_priv(pcdev); -- struct i2c_client *client = priv->client; -- bool enabled; -- u8 chan; -- u16 val; -- int ret; -- -- ret = i2c_smbus_read_word_data(client, TPS23881_REG_PW_STATUS); -- if (ret < 0) -- return ret; -- -- chan = priv->port[id].chan[0]; -- val = tps23881_calc_val(ret, chan, 0, BIT(chan % 4)); -- enabled = !!(val); -- -- if (priv->port[id].is_4p) { -- chan = priv->port[id].chan[1]; -- val = tps23881_calc_val(ret, chan, 0, BIT(chan % 4)); -- enabled &= !!(val); -- } -- -- /* Return enabled status only if both channel are on this state */ -- return enabled; --} -- - static int - tps23881_pi_get_admin_state(struct pse_controller_dev *pcdev, int id, - struct pse_admin_state *admin_state) -@@ -690,7 +663,6 @@ static const struct pse_controller_ops t - .setup_pi_matrix = tps23881_setup_pi_matrix, - .pi_enable = tps23881_pi_enable, - .pi_disable = tps23881_pi_disable, -- .pi_is_enabled = tps23881_pi_is_enabled, - .pi_get_admin_state = tps23881_pi_get_admin_state, - .pi_get_pw_status = tps23881_pi_get_pw_status, - }; ---- a/include/linux/pse-pd/pse.h -+++ b/include/linux/pse-pd/pse.h -@@ -122,8 +122,6 @@ struct ethtool_pse_control_status { - * @pi_get_ext_state: Get the extended state of the PSE PI. - * @pi_get_pw_class: Get the power class of the PSE PI. - * @pi_get_actual_pw: Get actual power of the PSE PI in mW. -- * @pi_is_enabled: Return 1 if the PSE PI is enabled, 0 if not. -- * May also return negative errno. - * @pi_enable: Configure the PSE PI as enabled. - * @pi_disable: Configure the PSE PI as disabled. - * @pi_get_voltage: Return voltage similarly to get_voltage regulator -@@ -145,7 +143,6 @@ struct pse_controller_ops { - struct pse_ext_state_info *ext_state_info); - int (*pi_get_pw_class)(struct pse_controller_dev *pcdev, int id); - int (*pi_get_actual_pw)(struct pse_controller_dev *pcdev, int id); -- int (*pi_is_enabled)(struct pse_controller_dev *pcdev, int id); - int (*pi_enable)(struct pse_controller_dev *pcdev, int id); - int (*pi_disable)(struct pse_controller_dev *pcdev, int id); - int (*pi_get_voltage)(struct pse_controller_dev *pcdev, int id); diff --git a/target/linux/generic/backport-6.18/626-07-v6.13-net-pse-pd-tps23881-Add-power-limit-and-measurement-features.patch b/target/linux/generic/backport-6.18/626-07-v6.13-net-pse-pd-tps23881-Add-power-limit-and-measurement-features.patch deleted file mode 100644 index de3cc76b4f..0000000000 --- a/target/linux/generic/backport-6.18/626-07-v6.13-net-pse-pd-tps23881-Add-power-limit-and-measurement-features.patch +++ /dev/null @@ -1,337 +0,0 @@ -From 7f076ce3f17334964590c2cce49a02c0851c099a Mon Sep 17 00:00:00 2001 -From: Kory Maincent -Date: Fri, 10 Jan 2025 10:40:29 +0100 -Subject: [PATCH] net: pse-pd: tps23881: Add support for power limit and - measurement features - -Expand PSE callbacks to support the newly introduced -pi_get/set_pw_limit() and pi_get_voltage() functions. These callbacks -allow for power limit configuration in the TPS23881 controller. - -Additionally, the patch includes the pi_get_pw_class() the -pi_get_actual_pw(), and the pi_get_pw_limit_ranges') callbacks providing -more comprehensive PoE status reporting. - -Acked-by: Oleksij Rempel -Signed-off-by: Kory Maincent -Signed-off-by: Paolo Abeni -Signed-off-by: Carlo Szelinsky ---- - drivers/net/pse-pd/tps23881.c | 258 +++++++++++++++++++++++++++++++++- - 1 file changed, 256 insertions(+), 2 deletions(-) - ---- a/drivers/net/pse-pd/tps23881.c -+++ b/drivers/net/pse-pd/tps23881.c -@@ -25,20 +25,32 @@ - #define TPS23881_REG_GEN_MASK 0x17 - #define TPS23881_REG_NBITACC BIT(5) - #define TPS23881_REG_PW_EN 0x19 -+#define TPS23881_REG_2PAIR_POL1 0x1e - #define TPS23881_REG_PORT_MAP 0x26 - #define TPS23881_REG_PORT_POWER 0x29 --#define TPS23881_REG_POEPLUS 0x40 -+#define TPS23881_REG_4PAIR_POL1 0x2a -+#define TPS23881_REG_INPUT_V 0x2e -+#define TPS23881_REG_CHAN1_A 0x30 -+#define TPS23881_REG_CHAN1_V 0x32 -+#define TPS23881_REG_FOLDBACK 0x40 - #define TPS23881_REG_TPON BIT(0) - #define TPS23881_REG_FWREV 0x41 - #define TPS23881_REG_DEVID 0x43 - #define TPS23881_REG_DEVID_MASK 0xF0 - #define TPS23881_DEVICE_ID 0x02 -+#define TPS23881_REG_CHAN1_CLASS 0x4c - #define TPS23881_REG_SRAM_CTRL 0x60 - #define TPS23881_REG_SRAM_DATA 0x61 - -+#define TPS23881_UV_STEP 3662 -+#define TPS23881_NA_STEP 70190 -+#define TPS23881_MW_STEP 500 -+#define TPS23881_MIN_PI_PW_LIMIT_MW 2000 -+ - struct tps23881_port_desc { - u8 chan[2]; - bool is_4p; -+ int pw_pol; - }; - - struct tps23881_priv { -@@ -102,6 +114,54 @@ static u16 tps23881_set_val(u16 reg_val, - return reg_val; - } - -+static int -+tps23881_pi_set_pw_pol_limit(struct tps23881_priv *priv, int id, u8 pw_pol, -+ bool is_4p) -+{ -+ struct i2c_client *client = priv->client; -+ int ret, reg; -+ u16 val; -+ u8 chan; -+ -+ chan = priv->port[id].chan[0]; -+ if (!is_4p) { -+ reg = TPS23881_REG_2PAIR_POL1 + (chan % 4); -+ } else { -+ /* One chan is enough to configure the 4p PI power limit */ -+ if ((chan % 4) < 2) -+ reg = TPS23881_REG_4PAIR_POL1; -+ else -+ reg = TPS23881_REG_4PAIR_POL1 + 1; -+ } -+ -+ ret = i2c_smbus_read_word_data(client, reg); -+ if (ret < 0) -+ return ret; -+ -+ val = tps23881_set_val(ret, chan, 0, 0xff, pw_pol); -+ return i2c_smbus_write_word_data(client, reg, val); -+} -+ -+static int tps23881_pi_enable_manual_pol(struct tps23881_priv *priv, int id) -+{ -+ struct i2c_client *client = priv->client; -+ int ret; -+ u8 chan; -+ u16 val; -+ -+ ret = i2c_smbus_read_byte_data(client, TPS23881_REG_FOLDBACK); -+ if (ret < 0) -+ return ret; -+ -+ /* No need to test if the chan is PoE4 as setting either bit for a -+ * 4P configured port disables the automatic configuration on both -+ * channels. -+ */ -+ chan = priv->port[id].chan[0]; -+ val = tps23881_set_val(ret, chan, 0, BIT(chan % 4), BIT(chan % 4)); -+ return i2c_smbus_write_byte_data(client, TPS23881_REG_FOLDBACK, val); -+} -+ - static int tps23881_pi_enable(struct pse_controller_dev *pcdev, int id) - { - struct tps23881_priv *priv = to_tps23881_priv(pcdev); -@@ -171,7 +231,21 @@ static int tps23881_pi_disable(struct ps - BIT(chan % 4)); - } - -- return i2c_smbus_write_word_data(client, TPS23881_REG_DET_CLA_EN, val); -+ ret = i2c_smbus_write_word_data(client, TPS23881_REG_DET_CLA_EN, val); -+ if (ret) -+ return ret; -+ -+ /* No power policy */ -+ if (priv->port[id].pw_pol < 0) -+ return 0; -+ -+ ret = tps23881_pi_enable_manual_pol(priv, id); -+ if (ret < 0) -+ return ret; -+ -+ /* Set power policy */ -+ return tps23881_pi_set_pw_pol_limit(priv, id, priv->port[id].pw_pol, -+ priv->port[id].is_4p); - } - - static int -@@ -246,6 +320,177 @@ tps23881_pi_get_pw_status(struct pse_con - return 0; - } - -+static int tps23881_pi_get_voltage(struct pse_controller_dev *pcdev, int id) -+{ -+ struct tps23881_priv *priv = to_tps23881_priv(pcdev); -+ struct i2c_client *client = priv->client; -+ int ret; -+ u64 uV; -+ -+ ret = i2c_smbus_read_word_data(client, TPS23881_REG_INPUT_V); -+ if (ret < 0) -+ return ret; -+ -+ uV = ret & 0x3fff; -+ uV *= TPS23881_UV_STEP; -+ -+ return (int)uV; -+} -+ -+static int -+tps23881_pi_get_chan_current(struct tps23881_priv *priv, u8 chan) -+{ -+ struct i2c_client *client = priv->client; -+ int reg, ret; -+ u64 tmp_64; -+ -+ /* Registers 0x30 to 0x3d */ -+ reg = TPS23881_REG_CHAN1_A + (chan % 4) * 4 + (chan >= 4); -+ ret = i2c_smbus_read_word_data(client, reg); -+ if (ret < 0) -+ return ret; -+ -+ tmp_64 = ret & 0x3fff; -+ tmp_64 *= TPS23881_NA_STEP; -+ /* uA = nA / 1000 */ -+ tmp_64 = DIV_ROUND_CLOSEST_ULL(tmp_64, 1000); -+ return (int)tmp_64; -+} -+ -+static int tps23881_pi_get_pw_class(struct pse_controller_dev *pcdev, -+ int id) -+{ -+ struct tps23881_priv *priv = to_tps23881_priv(pcdev); -+ struct i2c_client *client = priv->client; -+ int ret, reg; -+ u8 chan; -+ -+ chan = priv->port[id].chan[0]; -+ reg = TPS23881_REG_CHAN1_CLASS + (chan % 4); -+ ret = i2c_smbus_read_word_data(client, reg); -+ if (ret < 0) -+ return ret; -+ -+ return tps23881_calc_val(ret, chan, 4, 0x0f); -+} -+ -+static int -+tps23881_pi_get_actual_pw(struct pse_controller_dev *pcdev, int id) -+{ -+ struct tps23881_priv *priv = to_tps23881_priv(pcdev); -+ int ret, uV, uA; -+ u64 tmp_64; -+ u8 chan; -+ -+ ret = tps23881_pi_get_voltage(&priv->pcdev, id); -+ if (ret < 0) -+ return ret; -+ uV = ret; -+ -+ chan = priv->port[id].chan[0]; -+ ret = tps23881_pi_get_chan_current(priv, chan); -+ if (ret < 0) -+ return ret; -+ uA = ret; -+ -+ if (priv->port[id].is_4p) { -+ chan = priv->port[id].chan[1]; -+ ret = tps23881_pi_get_chan_current(priv, chan); -+ if (ret < 0) -+ return ret; -+ uA += ret; -+ } -+ -+ tmp_64 = uV; -+ tmp_64 *= uA; -+ /* mW = uV * uA / 1000000000 */ -+ return DIV_ROUND_CLOSEST_ULL(tmp_64, 1000000000); -+} -+ -+static int -+tps23881_pi_get_pw_limit_chan(struct tps23881_priv *priv, u8 chan) -+{ -+ struct i2c_client *client = priv->client; -+ int ret, reg; -+ u16 val; -+ -+ reg = TPS23881_REG_2PAIR_POL1 + (chan % 4); -+ ret = i2c_smbus_read_word_data(client, reg); -+ if (ret < 0) -+ return ret; -+ -+ val = tps23881_calc_val(ret, chan, 0, 0xff); -+ return val * TPS23881_MW_STEP; -+} -+ -+static int tps23881_pi_get_pw_limit(struct pse_controller_dev *pcdev, int id) -+{ -+ struct tps23881_priv *priv = to_tps23881_priv(pcdev); -+ int ret, mW; -+ u8 chan; -+ -+ chan = priv->port[id].chan[0]; -+ ret = tps23881_pi_get_pw_limit_chan(priv, chan); -+ if (ret < 0) -+ return ret; -+ -+ mW = ret; -+ if (priv->port[id].is_4p) { -+ chan = priv->port[id].chan[1]; -+ ret = tps23881_pi_get_pw_limit_chan(priv, chan); -+ if (ret < 0) -+ return ret; -+ mW += ret; -+ } -+ -+ return mW; -+} -+ -+static int tps23881_pi_set_pw_limit(struct pse_controller_dev *pcdev, -+ int id, int max_mW) -+{ -+ struct tps23881_priv *priv = to_tps23881_priv(pcdev); -+ u8 pw_pol; -+ int ret; -+ -+ if (max_mW < TPS23881_MIN_PI_PW_LIMIT_MW || MAX_PI_PW < max_mW) { -+ dev_err(&priv->client->dev, -+ "power limit %d out of ranges [%d,%d]", -+ max_mW, TPS23881_MIN_PI_PW_LIMIT_MW, MAX_PI_PW); -+ return -ERANGE; -+ } -+ -+ ret = tps23881_pi_enable_manual_pol(priv, id); -+ if (ret < 0) -+ return ret; -+ -+ pw_pol = DIV_ROUND_CLOSEST_ULL(max_mW, TPS23881_MW_STEP); -+ -+ /* Save power policy to reconfigure it after a disabled call */ -+ priv->port[id].pw_pol = pw_pol; -+ return tps23881_pi_set_pw_pol_limit(priv, id, pw_pol, -+ priv->port[id].is_4p); -+} -+ -+static int -+tps23881_pi_get_pw_limit_ranges(struct pse_controller_dev *pcdev, int id, -+ struct pse_pw_limit_ranges *pw_limit_ranges) -+{ -+ struct ethtool_c33_pse_pw_limit_range *c33_pw_limit_ranges; -+ -+ c33_pw_limit_ranges = kzalloc(sizeof(*c33_pw_limit_ranges), -+ GFP_KERNEL); -+ if (!c33_pw_limit_ranges) -+ return -ENOMEM; -+ -+ c33_pw_limit_ranges->min = TPS23881_MIN_PI_PW_LIMIT_MW; -+ c33_pw_limit_ranges->max = MAX_PI_PW; -+ pw_limit_ranges->c33_pw_limit_ranges = c33_pw_limit_ranges; -+ -+ /* Return the number of ranges */ -+ return 1; -+} -+ - /* Parse managers subnode into a array of device node */ - static int - tps23881_get_of_channels(struct tps23881_priv *priv, -@@ -540,6 +785,9 @@ tps23881_write_port_matrix(struct tps238 - if (port_matrix[i].exist) - priv->port[pi_id].chan[0] = lgcl_chan; - -+ /* Initialize power policy internal value */ -+ priv->port[pi_id].pw_pol = -1; -+ - /* Set hardware port matrix for all ports */ - val |= hw_chan << (lgcl_chan * 2); - -@@ -665,6 +913,12 @@ static const struct pse_controller_ops t - .pi_disable = tps23881_pi_disable, - .pi_get_admin_state = tps23881_pi_get_admin_state, - .pi_get_pw_status = tps23881_pi_get_pw_status, -+ .pi_get_pw_class = tps23881_pi_get_pw_class, -+ .pi_get_actual_pw = tps23881_pi_get_actual_pw, -+ .pi_get_voltage = tps23881_pi_get_voltage, -+ .pi_get_pw_limit = tps23881_pi_get_pw_limit, -+ .pi_set_pw_limit = tps23881_pi_set_pw_limit, -+ .pi_get_pw_limit_ranges = tps23881_pi_get_pw_limit_ranges, - }; - - static const char fw_parity_name[] = "ti/tps23881/tps23881-parity-14.bin"; diff --git a/target/linux/generic/backport-6.18/626-08-v6.13-net-pse-pd-Fix-missing-PI-of_node-description.patch b/target/linux/generic/backport-6.18/626-08-v6.13-net-pse-pd-Fix-missing-PI-of_node-description.patch deleted file mode 100644 index 3aa46cde42..0000000000 --- a/target/linux/generic/backport-6.18/626-08-v6.13-net-pse-pd-Fix-missing-PI-of_node-description.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 10276f3e1c7e7f5de9f0bba58f8a849cb195253d Mon Sep 17 00:00:00 2001 -From: Kory Maincent -Date: Fri, 10 Jan 2025 10:40:30 +0100 -Subject: [PATCH] net: pse-pd: Fix missing PI of_node description - -The PI of_node was not assigned in the regulator_config structure, leading -to failures in resolving the correct supply when different power supplies -are assigned to multiple PIs of a PSE controller. This fix ensures that the -of_node is properly set in the regulator_config, allowing accurate supply -resolution for each PI. - -Acked-by: Oleksij Rempel -Signed-off-by: Kory Maincent -Signed-off-by: Paolo Abeni -Signed-off-by: Carlo Szelinsky ---- - drivers/net/pse-pd/pse_core.c | 1 + - 1 file changed, 1 insertion(+) ---- a/drivers/net/pse-pd/pse_core.c -+++ b/drivers/net/pse-pd/pse_core.c -@@ -422,6 +422,7 @@ devm_pse_pi_regulator_register(struct ps - rconfig.dev = pcdev->dev; - rconfig.driver_data = pcdev; - rconfig.init_data = rinit_data; -+ rconfig.of_node = pcdev->pi[id].np; - - rdev = devm_regulator_register(pcdev->dev, rdesc, &rconfig); - if (IS_ERR(rdev)) { diff --git a/target/linux/generic/backport-6.18/626-09-v6.13-net-pse-pd-Clean-ethtool-header-of-PSE-structures.patch b/target/linux/generic/backport-6.18/626-09-v6.13-net-pse-pd-Clean-ethtool-header-of-PSE-structures.patch deleted file mode 100644 index 7d338125a0..0000000000 --- a/target/linux/generic/backport-6.18/626-09-v6.13-net-pse-pd-Clean-ethtool-header-of-PSE-structures.patch +++ /dev/null @@ -1,92 +0,0 @@ -From 5385f1e1923ca8131eb143567d509b101a344e06 Mon Sep 17 00:00:00 2001 -From: Kory Maincent -Date: Fri, 10 Jan 2025 10:40:31 +0100 -Subject: [PATCH] net: pse-pd: Clean ethtool header of PSE structures - -Remove PSE-specific structures from the ethtool header to improve code -modularity, maintain independent headers, and reduce incremental build -time. - -Signed-off-by: Kory Maincent -Signed-off-by: Paolo Abeni -Signed-off-by: Carlo Szelinsky ---- - drivers/net/pse-pd/pse_core.c | 1 + - include/linux/ethtool.h | 20 -------------------- - include/linux/pse-pd/pse.h | 22 +++++++++++++++++++++- - 3 files changed, 22 insertions(+), 21 deletions(-) ---- a/drivers/net/pse-pd/pse_core.c -+++ b/drivers/net/pse-pd/pse_core.c -@@ -6,6 +6,7 @@ - // - - #include -+#include - #include - #include - #include ---- a/include/linux/ethtool.h -+++ b/include/linux/ethtool.h -@@ -1322,24 +1322,4 @@ struct ethtool_forced_speed_map { - - void - ethtool_forced_speed_maps_init(struct ethtool_forced_speed_map *maps, u32 size); -- --/* C33 PSE extended state and substate. */ --struct ethtool_c33_pse_ext_state_info { -- enum ethtool_c33_pse_ext_state c33_pse_ext_state; -- union { -- enum ethtool_c33_pse_ext_substate_error_condition error_condition; -- enum ethtool_c33_pse_ext_substate_mr_pse_enable mr_pse_enable; -- enum ethtool_c33_pse_ext_substate_option_detect_ted option_detect_ted; -- enum ethtool_c33_pse_ext_substate_option_vport_lim option_vport_lim; -- enum ethtool_c33_pse_ext_substate_ovld_detected ovld_detected; -- enum ethtool_c33_pse_ext_substate_power_not_available power_not_available; -- enum ethtool_c33_pse_ext_substate_short_detected short_detected; -- u32 __c33_pse_ext_substate; -- }; --}; -- --struct ethtool_c33_pse_pw_limit_range { -- u32 min; -- u32 max; --}; - #endif /* _LINUX_ETHTOOL_H */ ---- a/include/linux/pse-pd/pse.h -+++ b/include/linux/pse-pd/pse.h -@@ -5,7 +5,6 @@ - #ifndef _LINUX_PSE_CONTROLLER_H - #define _LINUX_PSE_CONTROLLER_H - --#include - #include - #include - -@@ -16,6 +15,27 @@ - - struct phy_device; - struct pse_controller_dev; -+struct netlink_ext_ack; -+ -+/* C33 PSE extended state and substate. */ -+struct ethtool_c33_pse_ext_state_info { -+ enum ethtool_c33_pse_ext_state c33_pse_ext_state; -+ union { -+ enum ethtool_c33_pse_ext_substate_error_condition error_condition; -+ enum ethtool_c33_pse_ext_substate_mr_pse_enable mr_pse_enable; -+ enum ethtool_c33_pse_ext_substate_option_detect_ted option_detect_ted; -+ enum ethtool_c33_pse_ext_substate_option_vport_lim option_vport_lim; -+ enum ethtool_c33_pse_ext_substate_ovld_detected ovld_detected; -+ enum ethtool_c33_pse_ext_substate_power_not_available power_not_available; -+ enum ethtool_c33_pse_ext_substate_short_detected short_detected; -+ u32 __c33_pse_ext_substate; -+ }; -+}; -+ -+struct ethtool_c33_pse_pw_limit_range { -+ u32 min; -+ u32 max; -+}; - - /** - * struct pse_control_config - PSE control/channel configuration. diff --git a/target/linux/generic/backport-6.18/626-10-v6.17-net-pse-pd-Introduce-attached_phydev-to-pse-control.patch b/target/linux/generic/backport-6.18/626-10-v6.17-net-pse-pd-Introduce-attached_phydev-to-pse-control.patch deleted file mode 100644 index b00c0e1475..0000000000 --- a/target/linux/generic/backport-6.18/626-10-v6.17-net-pse-pd-Introduce-attached_phydev-to-pse-control.patch +++ /dev/null @@ -1,171 +0,0 @@ -From fa2f0454174c2f33005f5a6e6f70c7160a15b2a1 Mon Sep 17 00:00:00 2001 -From: "Kory Maincent (Dent Project)" -Date: Tue, 17 Jun 2025 14:12:00 +0200 -Subject: [PATCH] net: pse-pd: Introduce attached_phydev to pse control - -In preparation for reporting PSE events via ethtool notifications, -introduce an attached_phydev field in the pse_control structure. -This field stores the phy_device associated with the PSE PI, -ensuring that notifications are sent to the correct network -interface. - -The attached_phydev pointer is directly tied to the PHY lifecycle. It -is set when the PHY is registered and cleared when the PHY is removed. -There is no need to use a refcount, as doing so could interfere with -the PHY removal process. - -Signed-off-by: Kory Maincent (Dent Project) -Reviewed-by: Oleksij Rempel -Link: https://patch.msgid.link/20250617-feature_poe_port_prio-v14-1-78a1a645e2ee@bootlin.com -Signed-off-by: Jakub Kicinski -Signed-off-by: Carlo Szelinsky ---- - drivers/net/mdio/fwnode_mdio.c | 26 ++++++++++++++------------ - drivers/net/pse-pd/pse_core.c | 11 ++++++++--- - include/linux/pse-pd/pse.h | 6 ++++-- - 3 files changed, 26 insertions(+), 17 deletions(-) ---- a/drivers/net/mdio/fwnode_mdio.c -+++ b/drivers/net/mdio/fwnode_mdio.c -@@ -18,7 +18,8 @@ MODULE_LICENSE("GPL"); - MODULE_DESCRIPTION("FWNODE MDIO bus (Ethernet PHY) accessors"); - - static struct pse_control * --fwnode_find_pse_control(struct fwnode_handle *fwnode) -+fwnode_find_pse_control(struct fwnode_handle *fwnode, -+ struct phy_device *phydev) - { - struct pse_control *psec; - struct device_node *np; -@@ -30,7 +31,7 @@ fwnode_find_pse_control(struct fwnode_ha - if (!np) - return NULL; - -- psec = of_pse_control_get(np); -+ psec = of_pse_control_get(np, phydev); - if (PTR_ERR(psec) == -ENOENT) - return NULL; - -@@ -128,15 +129,9 @@ int fwnode_mdiobus_register_phy(struct m - u32 phy_id; - int rc; - -- psec = fwnode_find_pse_control(child); -- if (IS_ERR(psec)) -- return PTR_ERR(psec); -- - mii_ts = fwnode_find_mii_timestamper(child); -- if (IS_ERR(mii_ts)) { -- rc = PTR_ERR(mii_ts); -- goto clean_pse; -- } -+ if (IS_ERR(mii_ts)) -+ return PTR_ERR(mii_ts); - - is_c45 = fwnode_device_is_compatible(child, "ethernet-phy-ieee802.3-c45"); - if (is_c45 || fwnode_get_phy_id(child, &phy_id)) -@@ -169,6 +164,12 @@ int fwnode_mdiobus_register_phy(struct m - goto clean_phy; - } - -+ psec = fwnode_find_pse_control(child, phy); -+ if (IS_ERR(psec)) { -+ rc = PTR_ERR(psec); -+ goto unregister_phy; -+ } -+ - phy->psec = psec; - - /* phy->mii_ts may already be defined by the PHY driver. A -@@ -180,12 +181,13 @@ int fwnode_mdiobus_register_phy(struct m - - return 0; - -+unregister_phy: -+ if (is_acpi_node(child) || is_of_node(child)) -+ phy_device_remove(phy); - clean_phy: - phy_device_free(phy); - clean_mii_ts: - unregister_mii_timestamper(mii_ts); --clean_pse: -- pse_control_put(psec); - - return rc; - } ---- a/drivers/net/pse-pd/pse_core.c -+++ b/drivers/net/pse-pd/pse_core.c -@@ -23,6 +23,7 @@ static LIST_HEAD(pse_controller_list); - * @list: list entry for the pcdev's PSE controller list - * @id: ID of the PSE line in the PSE controller device - * @refcnt: Number of gets of this pse_control -+ * @attached_phydev: PHY device pointer attached by the PSE control - */ - struct pse_control { - struct pse_controller_dev *pcdev; -@@ -30,6 +31,7 @@ struct pse_control { - struct list_head list; - unsigned int id; - struct kref refcnt; -+ struct phy_device *attached_phydev; - }; - - static int of_load_single_pse_pi_pairset(struct device_node *node, -@@ -599,7 +601,8 @@ void pse_control_put(struct pse_control - EXPORT_SYMBOL_GPL(pse_control_put); - - static struct pse_control * --pse_control_get_internal(struct pse_controller_dev *pcdev, unsigned int index) -+pse_control_get_internal(struct pse_controller_dev *pcdev, unsigned int index, -+ struct phy_device *phydev) - { - struct pse_control *psec; - int ret; -@@ -638,6 +641,7 @@ pse_control_get_internal(struct pse_cont - psec->pcdev = pcdev; - list_add(&psec->list, &pcdev->pse_control_head); - psec->id = index; -+ psec->attached_phydev = phydev; - kref_init(&psec->refcnt); - - return psec; -@@ -693,7 +697,8 @@ static int psec_id_xlate(struct pse_cont - return pse_spec->args[0]; - } - --struct pse_control *of_pse_control_get(struct device_node *node) -+struct pse_control *of_pse_control_get(struct device_node *node, -+ struct phy_device *phydev) - { - struct pse_controller_dev *r, *pcdev; - struct of_phandle_args args; -@@ -743,7 +748,7 @@ struct pse_control *of_pse_control_get(s - } - - /* pse_list_mutex also protects the pcdev's pse_control list */ -- psec = pse_control_get_internal(pcdev, psec_id); -+ psec = pse_control_get_internal(pcdev, psec_id, phydev); - - out: - mutex_unlock(&pse_list_mutex); ---- a/include/linux/pse-pd/pse.h -+++ b/include/linux/pse-pd/pse.h -@@ -250,7 +250,8 @@ struct device; - int devm_pse_controller_register(struct device *dev, - struct pse_controller_dev *pcdev); - --struct pse_control *of_pse_control_get(struct device_node *node); -+struct pse_control *of_pse_control_get(struct device_node *node, -+ struct phy_device *phydev); - void pse_control_put(struct pse_control *psec); - - int pse_ethtool_get_status(struct pse_control *psec, -@@ -270,7 +271,8 @@ bool pse_has_c33(struct pse_control *pse - - #else - --static inline struct pse_control *of_pse_control_get(struct device_node *node) -+static inline struct pse_control *of_pse_control_get(struct device_node *node, -+ struct phy_device *phydev) - { - return ERR_PTR(-ENOENT); - } diff --git a/target/linux/generic/backport-6.18/626-11-v6.17-net-pse-pd-Add-support-for-reporting-events.patch b/target/linux/generic/backport-6.18/626-11-v6.17-net-pse-pd-Add-support-for-reporting-events.patch deleted file mode 100644 index ec99fcab82..0000000000 --- a/target/linux/generic/backport-6.18/626-11-v6.17-net-pse-pd-Add-support-for-reporting-events.patch +++ /dev/null @@ -1,363 +0,0 @@ -# ADAPTED FOR OPENWRT 6.12.67 - Documentation changes removed -# Original commit: fc0e6db30941 -From fc0e6db30941a66e284b8516b82356f97f31061d Mon Sep 17 00:00:00 2001 -From: "Kory Maincent (Dent Project)" -Date: Tue, 17 Jun 2025 14:12:01 +0200 -Subject: [PATCH] net: pse-pd: Add support for reporting events - -Add support for devm_pse_irq_helper() to register PSE interrupts and report -events such as over-current or over-temperature conditions. This follows a -similar approach to the regulator API but also sends notifications using a -dedicated PSE ethtool netlink socket. - -Signed-off-by: Kory Maincent (Dent Project) -Link: https://patch.msgid.link/20250617-feature_poe_port_prio-v14-2-78a1a645e2ee@bootlin.com -Signed-off-by: Jakub Kicinski -Signed-off-by: Carlo Szelinsky ---- - Documentation/netlink/specs/ethtool.yaml | 34 ++++ - Documentation/networking/ethtool-netlink.rst | 19 ++ - drivers/net/pse-pd/pse_core.c | 179 ++++++++++++++++++ - include/linux/ethtool_netlink.h | 7 + - include/linux/pse-pd/pse.h | 20 ++ - .../uapi/linux/ethtool_netlink_generated.h | 19 ++ - net/ethtool/pse-pd.c | 39 ++++ - 7 files changed, 317 insertions(+) - ---- a/drivers/net/pse-pd/pse_core.c -+++ b/drivers/net/pse-pd/pse_core.c -@@ -7,10 +7,14 @@ - - #include - #include -+#include - #include -+#include - #include - #include - #include -+#include -+#include - - static DEFINE_MUTEX(pse_list_mutex); - static LIST_HEAD(pse_controller_list); -@@ -210,6 +214,48 @@ out: - return ret; - } - -+/** -+ * pse_control_find_net_by_id - Find net attached to the pse control id -+ * @pcdev: a pointer to the PSE -+ * @id: index of the PSE control -+ * -+ * Return: pse_control pointer or NULL. The device returned has had a -+ * reference added and the pointer is safe until the user calls -+ * pse_control_put() to indicate they have finished with it. -+ */ -+static struct pse_control * -+pse_control_find_by_id(struct pse_controller_dev *pcdev, int id) -+{ -+ struct pse_control *psec; -+ -+ mutex_lock(&pse_list_mutex); -+ list_for_each_entry(psec, &pcdev->pse_control_head, list) { -+ if (psec->id == id) { -+ kref_get(&psec->refcnt); -+ mutex_unlock(&pse_list_mutex); -+ return psec; -+ } -+ } -+ mutex_unlock(&pse_list_mutex); -+ return NULL; -+} -+ -+/** -+ * pse_control_get_netdev - Return netdev associated to a PSE control -+ * @psec: PSE control pointer -+ * -+ * Return: netdev pointer or NULL -+ */ -+static struct net_device *pse_control_get_netdev(struct pse_control *psec) -+{ -+ ASSERT_RTNL(); -+ -+ if (!psec || !psec->attached_phydev) -+ return NULL; -+ -+ return psec->attached_phydev->attached_dev; -+} -+ - static int pse_pi_is_enabled(struct regulator_dev *rdev) - { - struct pse_controller_dev *pcdev = rdev_get_drvdata(rdev); -@@ -559,6 +605,139 @@ int devm_pse_controller_register(struct - } - EXPORT_SYMBOL_GPL(devm_pse_controller_register); - -+struct pse_irq { -+ struct pse_controller_dev *pcdev; -+ struct pse_irq_desc desc; -+ unsigned long *notifs; -+}; -+ -+/** -+ * pse_to_regulator_notifs - Convert PSE notifications to Regulator -+ * notifications -+ * @notifs: PSE notifications -+ * -+ * Return: Regulator notifications -+ */ -+static unsigned long pse_to_regulator_notifs(unsigned long notifs) -+{ -+ unsigned long rnotifs = 0; -+ -+ if (notifs & ETHTOOL_PSE_EVENT_OVER_CURRENT) -+ rnotifs |= REGULATOR_EVENT_OVER_CURRENT; -+ if (notifs & ETHTOOL_PSE_EVENT_OVER_TEMP) -+ rnotifs |= REGULATOR_EVENT_OVER_TEMP; -+ -+ return rnotifs; -+} -+ -+/** -+ * pse_isr - IRQ handler for PSE -+ * @irq: irq number -+ * @data: pointer to user interrupt structure -+ * -+ * Return: irqreturn_t - status of IRQ -+ */ -+static irqreturn_t pse_isr(int irq, void *data) -+{ -+ struct pse_controller_dev *pcdev; -+ unsigned long notifs_mask = 0; -+ struct pse_irq_desc *desc; -+ struct pse_irq *h = data; -+ int ret, i; -+ -+ desc = &h->desc; -+ pcdev = h->pcdev; -+ -+ /* Clear notifs mask */ -+ memset(h->notifs, 0, pcdev->nr_lines * sizeof(*h->notifs)); -+ mutex_lock(&pcdev->lock); -+ ret = desc->map_event(irq, pcdev, h->notifs, ¬ifs_mask); -+ mutex_unlock(&pcdev->lock); -+ if (ret || !notifs_mask) -+ return IRQ_NONE; -+ -+ for_each_set_bit(i, ¬ifs_mask, pcdev->nr_lines) { -+ unsigned long notifs, rnotifs; -+ struct net_device *netdev; -+ struct pse_control *psec; -+ -+ /* Do nothing PI not described */ -+ if (!pcdev->pi[i].rdev) -+ continue; -+ -+ notifs = h->notifs[i]; -+ dev_dbg(h->pcdev->dev, -+ "Sending PSE notification EVT 0x%lx\n", notifs); -+ -+ psec = pse_control_find_by_id(pcdev, i); -+ rtnl_lock(); -+ netdev = pse_control_get_netdev(psec); -+ if (netdev) -+ ethnl_pse_send_ntf(netdev, notifs); -+ rtnl_unlock(); -+ pse_control_put(psec); -+ -+ rnotifs = pse_to_regulator_notifs(notifs); -+ regulator_notifier_call_chain(pcdev->pi[i].rdev, rnotifs, -+ NULL); -+ } -+ -+ return IRQ_HANDLED; -+} -+ -+/** -+ * devm_pse_irq_helper - Register IRQ based PSE event notifier -+ * @pcdev: a pointer to the PSE -+ * @irq: the irq value to be passed to request_irq -+ * @irq_flags: the flags to be passed to request_irq -+ * @d: PSE interrupt description -+ * -+ * Return: 0 on success and errno on failure -+ */ -+int devm_pse_irq_helper(struct pse_controller_dev *pcdev, int irq, -+ int irq_flags, const struct pse_irq_desc *d) -+{ -+ struct device *dev = pcdev->dev; -+ size_t irq_name_len; -+ struct pse_irq *h; -+ char *irq_name; -+ int ret; -+ -+ if (!d || !d->map_event || !d->name) -+ return -EINVAL; -+ -+ h = devm_kzalloc(dev, sizeof(*h), GFP_KERNEL); -+ if (!h) -+ return -ENOMEM; -+ -+ h->pcdev = pcdev; -+ h->desc = *d; -+ -+ /* IRQ name len is pcdev dev name + 5 char + irq desc name + 1 */ -+ irq_name_len = strlen(dev_name(pcdev->dev)) + 5 + strlen(d->name) + 1; -+ irq_name = devm_kzalloc(dev, irq_name_len, GFP_KERNEL); -+ if (!irq_name) -+ return -ENOMEM; -+ -+ snprintf(irq_name, irq_name_len, "pse-%s:%s", dev_name(pcdev->dev), -+ d->name); -+ -+ h->notifs = devm_kcalloc(dev, pcdev->nr_lines, -+ sizeof(*h->notifs), GFP_KERNEL); -+ if (!h->notifs) -+ return -ENOMEM; -+ -+ ret = devm_request_threaded_irq(dev, irq, NULL, pse_isr, -+ IRQF_ONESHOT | irq_flags, -+ irq_name, h); -+ if (ret) -+ dev_err(pcdev->dev, "Failed to request IRQ %d\n", irq); -+ -+ pcdev->irq = irq; -+ return ret; -+} -+EXPORT_SYMBOL_GPL(devm_pse_irq_helper); -+ - /* PSE control section */ - - static void __pse_control_release(struct kref *kref) ---- a/include/linux/ethtool_netlink.h -+++ b/include/linux/ethtool_netlink.h -@@ -43,6 +43,8 @@ void ethtool_aggregate_rmon_stats(struct - struct ethtool_rmon_stats *rmon_stats); - bool ethtool_dev_mm_supported(struct net_device *dev); - -+void ethnl_pse_send_ntf(struct net_device *netdev, unsigned long notif); -+ - #else - static inline int ethnl_cable_test_alloc(struct phy_device *phydev, u8 cmd) - { -@@ -120,6 +122,11 @@ static inline bool ethtool_dev_mm_suppor - return false; - } - -+static inline void ethnl_pse_send_ntf(struct phy_device *phydev, -+ unsigned long notif) -+{ -+} -+ - #endif /* IS_ENABLED(CONFIG_ETHTOOL_NETLINK) */ - - static inline int ethnl_cable_test_result(struct phy_device *phydev, u8 pair, ---- a/include/linux/pse-pd/pse.h -+++ b/include/linux/pse-pd/pse.h -@@ -7,12 +7,15 @@ - - #include - #include -+#include -+#include - - /* Maximum current in uA according to IEEE 802.3-2022 Table 145-1 */ - #define MAX_PI_CURRENT 1920000 - /* Maximum power in mW according to IEEE 802.3-2022 Table 145-16 */ - #define MAX_PI_PW 99900 - -+struct net_device; - struct phy_device; - struct pse_controller_dev; - struct netlink_ext_ack; -@@ -38,6 +41,19 @@ struct ethtool_c33_pse_pw_limit_range { - }; - - /** -+ * struct pse_irq_desc - notification sender description for IRQ based events. -+ * -+ * @name: the visible name for the IRQ -+ * @map_event: driver callback to map IRQ status into PSE devices with events. -+ */ -+struct pse_irq_desc { -+ const char *name; -+ int (*map_event)(int irq, struct pse_controller_dev *pcdev, -+ unsigned long *notifs, -+ unsigned long *notifs_mask); -+}; -+ -+/** - * struct pse_control_config - PSE control/channel configuration. - * - * @podl_admin_control: set PoDL PSE admin control as described in -@@ -228,6 +244,7 @@ struct pse_pi { - * @types: types of the PSE controller - * @pi: table of PSE PIs described in this controller device - * @no_of_pse_pi: flag set if the pse_pis devicetree node is not used -+ * @irq: PSE interrupt - */ - struct pse_controller_dev { - const struct pse_controller_ops *ops; -@@ -241,6 +258,7 @@ struct pse_controller_dev { - enum ethtool_pse_types types; - struct pse_pi *pi; - bool no_of_pse_pi; -+ int irq; - }; - - #if IS_ENABLED(CONFIG_PSE_CONTROLLER) -@@ -249,6 +267,8 @@ void pse_controller_unregister(struct ps - struct device; - int devm_pse_controller_register(struct device *dev, - struct pse_controller_dev *pcdev); -+int devm_pse_irq_helper(struct pse_controller_dev *pcdev, int irq, -+ int irq_flags, const struct pse_irq_desc *d); - - struct pse_control *of_pse_control_get(struct device_node *node, - struct phy_device *phydev); ---- a/net/ethtool/pse-pd.c -+++ b/net/ethtool/pse-pd.c -@@ -315,3 +315,42 @@ const struct ethnl_request_ops ethnl_pse - .set = ethnl_set_pse, - /* PSE has no notification */ - }; -+ -+void ethnl_pse_send_ntf(struct net_device *netdev, unsigned long notifs) -+{ -+ void *reply_payload; -+ struct sk_buff *skb; -+ int reply_len; -+ int ret; -+ -+ ASSERT_RTNL(); -+ -+ if (!netdev || !notifs) -+ return; -+ -+ reply_len = ethnl_reply_header_size() + -+ nla_total_size(sizeof(u32)); /* _PSE_NTF_EVENTS */ -+ -+ skb = genlmsg_new(reply_len, GFP_KERNEL); -+ if (!skb) -+ return; -+ -+ reply_payload = ethnl_bcastmsg_put(skb, ETHTOOL_MSG_PSE_NTF); -+ if (!reply_payload) -+ goto err_skb; -+ -+ ret = ethnl_fill_reply_header(skb, netdev, ETHTOOL_A_PSE_NTF_HEADER); -+ if (ret < 0) -+ goto err_skb; -+ -+ if (nla_put_uint(skb, ETHTOOL_A_PSE_NTF_EVENTS, notifs)) -+ goto err_skb; -+ -+ genlmsg_end(skb, reply_payload); -+ ethnl_multicast(skb, netdev); -+ return; -+ -+err_skb: -+ nlmsg_free(skb); -+} -+EXPORT_SYMBOL_GPL(ethnl_pse_send_ntf); diff --git a/target/linux/generic/backport-6.18/626-12-v6.17-net-pse-pd-tps23881-Add-support-for-PSE-events.patch b/target/linux/generic/backport-6.18/626-12-v6.17-net-pse-pd-tps23881-Add-support-for-PSE-events.patch deleted file mode 100644 index 8afcb3f870..0000000000 --- a/target/linux/generic/backport-6.18/626-12-v6.17-net-pse-pd-tps23881-Add-support-for-PSE-events.patch +++ /dev/null @@ -1,252 +0,0 @@ -From f5e7aecaa4efcd4c85477b6a62f94fea668031db Mon Sep 17 00:00:00 2001 -From: "Kory Maincent (Dent Project)" -Date: Tue, 17 Jun 2025 14:12:02 +0200 -Subject: [PATCH] net: pse-pd: tps23881: Add support for PSE events and - interrupts - -Add support for PSE event reporting through interrupts. Set up the newly -introduced devm_pse_irq_helper helper to register the interrupt. Events are -reported for over-current and over-temperature conditions. - -Signed-off-by: Kory Maincent (Dent Project) -Reviewed-by: Oleksij Rempel -Link: https://patch.msgid.link/20250617-feature_poe_port_prio-v14-3-78a1a645e2ee@bootlin.com -Signed-off-by: Jakub Kicinski -Signed-off-by: Carlo Szelinsky ---- - drivers/net/pse-pd/tps23881.c | 189 +++++++++++++++++++++++++++++++++- - 1 file changed, 187 insertions(+), 2 deletions(-) - ---- a/drivers/net/pse-pd/tps23881.c -+++ b/drivers/net/pse-pd/tps23881.c -@@ -16,7 +16,15 @@ - #include - - #define TPS23881_MAX_CHANS 8 -+#define TPS23881_MAX_IRQ_RETRIES 10 - -+#define TPS23881_REG_IT 0x0 -+#define TPS23881_REG_IT_MASK 0x1 -+#define TPS23881_REG_IT_IFAULT BIT(5) -+#define TPS23881_REG_IT_SUPF BIT(7) -+#define TPS23881_REG_FAULT 0x7 -+#define TPS23881_REG_SUPF_EVENT 0xb -+#define TPS23881_REG_TSD BIT(7) - #define TPS23881_REG_PW_STATUS 0x10 - #define TPS23881_REG_OP_MODE 0x12 - #define TPS23881_OP_MODE_SEMIAUTO 0xaaaa -@@ -24,6 +32,7 @@ - #define TPS23881_REG_DET_CLA_EN 0x14 - #define TPS23881_REG_GEN_MASK 0x17 - #define TPS23881_REG_NBITACC BIT(5) -+#define TPS23881_REG_INTEN BIT(7) - #define TPS23881_REG_PW_EN 0x19 - #define TPS23881_REG_2PAIR_POL1 0x1e - #define TPS23881_REG_PORT_MAP 0x26 -@@ -51,6 +60,7 @@ struct tps23881_port_desc { - u8 chan[2]; - bool is_4p; - int pw_pol; -+ bool exist; - }; - - struct tps23881_priv { -@@ -782,8 +792,10 @@ tps23881_write_port_matrix(struct tps238 - hw_chan = port_matrix[i].hw_chan[0] % 4; - - /* Set software port matrix for existing ports */ -- if (port_matrix[i].exist) -+ if (port_matrix[i].exist) { - priv->port[pi_id].chan[0] = lgcl_chan; -+ priv->port[pi_id].exist = true; -+ } - - /* Initialize power policy internal value */ - priv->port[pi_id].pw_pol = -1; -@@ -1017,6 +1029,173 @@ static int tps23881_flash_sram_fw(struct - return 0; - } - -+/* Convert interrupt events to 0xff to be aligned with the chan -+ * number. -+ */ -+static u8 tps23881_irq_export_chans_helper(u16 reg_val, u8 field_offset) -+{ -+ u8 val; -+ -+ val = (reg_val >> (4 + field_offset) & 0xf0) | -+ (reg_val >> field_offset & 0x0f); -+ -+ return val; -+} -+ -+/* Convert chan number to port number */ -+static void tps23881_set_notifs_helper(struct tps23881_priv *priv, -+ u8 chans, -+ unsigned long *notifs, -+ unsigned long *notifs_mask, -+ enum ethtool_pse_event event) -+{ -+ u8 chan; -+ int i; -+ -+ if (!chans) -+ return; -+ -+ for (i = 0; i < TPS23881_MAX_CHANS; i++) { -+ if (!priv->port[i].exist) -+ continue; -+ /* No need to look at the 2nd channel in case of PoE4 as -+ * both registers are set. -+ */ -+ chan = priv->port[i].chan[0]; -+ -+ if (BIT(chan) & chans) { -+ *notifs_mask |= BIT(i); -+ notifs[i] |= event; -+ } -+ } -+} -+ -+static void tps23881_irq_event_over_temp(struct tps23881_priv *priv, -+ u16 reg_val, -+ unsigned long *notifs, -+ unsigned long *notifs_mask) -+{ -+ int i; -+ -+ if (reg_val & TPS23881_REG_TSD) { -+ for (i = 0; i < TPS23881_MAX_CHANS; i++) { -+ if (!priv->port[i].exist) -+ continue; -+ -+ *notifs_mask |= BIT(i); -+ notifs[i] |= ETHTOOL_PSE_EVENT_OVER_TEMP; -+ } -+ } -+} -+ -+static void tps23881_irq_event_over_current(struct tps23881_priv *priv, -+ u16 reg_val, -+ unsigned long *notifs, -+ unsigned long *notifs_mask) -+{ -+ u8 chans; -+ -+ chans = tps23881_irq_export_chans_helper(reg_val, 0); -+ if (chans) -+ tps23881_set_notifs_helper(priv, chans, notifs, notifs_mask, -+ ETHTOOL_PSE_EVENT_OVER_CURRENT); -+} -+ -+static int tps23881_irq_event_handler(struct tps23881_priv *priv, u16 reg, -+ unsigned long *notifs, -+ unsigned long *notifs_mask) -+{ -+ struct i2c_client *client = priv->client; -+ int ret; -+ -+ /* The Supply event bit is repeated twice so we only need to read -+ * the one from the first byte. -+ */ -+ if (reg & TPS23881_REG_IT_SUPF) { -+ ret = i2c_smbus_read_word_data(client, TPS23881_REG_SUPF_EVENT); -+ if (ret < 0) -+ return ret; -+ tps23881_irq_event_over_temp(priv, ret, notifs, notifs_mask); -+ } -+ -+ if (reg & (TPS23881_REG_IT_IFAULT | TPS23881_REG_IT_IFAULT << 8)) { -+ ret = i2c_smbus_read_word_data(client, TPS23881_REG_FAULT); -+ if (ret < 0) -+ return ret; -+ tps23881_irq_event_over_current(priv, ret, notifs, notifs_mask); -+ } -+ -+ return 0; -+} -+ -+static int tps23881_irq_handler(int irq, struct pse_controller_dev *pcdev, -+ unsigned long *notifs, -+ unsigned long *notifs_mask) -+{ -+ struct tps23881_priv *priv = to_tps23881_priv(pcdev); -+ struct i2c_client *client = priv->client; -+ int ret, it_mask, retry; -+ -+ /* Get interruption mask */ -+ ret = i2c_smbus_read_word_data(client, TPS23881_REG_IT_MASK); -+ if (ret < 0) -+ return ret; -+ it_mask = ret; -+ -+ /* Read interrupt register until it frees the interruption pin. */ -+ retry = 0; -+ while (true) { -+ if (retry > TPS23881_MAX_IRQ_RETRIES) { -+ dev_err(&client->dev, "interrupt never freed"); -+ return -ETIMEDOUT; -+ } -+ -+ ret = i2c_smbus_read_word_data(client, TPS23881_REG_IT); -+ if (ret < 0) -+ return ret; -+ -+ /* No more relevant interruption */ -+ if (!(ret & it_mask)) -+ return 0; -+ -+ ret = tps23881_irq_event_handler(priv, (u16)ret, notifs, -+ notifs_mask); -+ if (ret) -+ return ret; -+ -+ retry++; -+ } -+ return 0; -+} -+ -+static int tps23881_setup_irq(struct tps23881_priv *priv, int irq) -+{ -+ struct i2c_client *client = priv->client; -+ struct pse_irq_desc irq_desc = { -+ .name = "tps23881-irq", -+ .map_event = tps23881_irq_handler, -+ }; -+ int ret; -+ u16 val; -+ -+ val = TPS23881_REG_IT_IFAULT | TPS23881_REG_IT_SUPF; -+ val |= val << 8; -+ ret = i2c_smbus_write_word_data(client, TPS23881_REG_IT_MASK, val); -+ if (ret) -+ return ret; -+ -+ ret = i2c_smbus_read_word_data(client, TPS23881_REG_GEN_MASK); -+ if (ret < 0) -+ return ret; -+ -+ val = (u16)(ret | TPS23881_REG_INTEN | TPS23881_REG_INTEN << 8); -+ ret = i2c_smbus_write_word_data(client, TPS23881_REG_GEN_MASK, val); -+ if (ret < 0) -+ return ret; -+ -+ return devm_pse_irq_helper(&priv->pcdev, irq, 0, &irq_desc); -+} -+ - static int tps23881_i2c_probe(struct i2c_client *client) - { - struct device *dev = &client->dev; -@@ -1097,6 +1276,12 @@ static int tps23881_i2c_probe(struct i2c - "failed to register PSE controller\n"); - } - -+ if (client->irq) { -+ ret = tps23881_setup_irq(priv, client->irq); -+ if (ret) -+ return ret; -+ } -+ - return ret; - } - diff --git a/target/linux/generic/backport-6.18/626-13-v6.17-net-pse-pd-Add-support-for-PSE-power-domains.patch b/target/linux/generic/backport-6.18/626-13-v6.17-net-pse-pd-Add-support-for-PSE-power-domains.patch deleted file mode 100644 index a02bbbc28b..0000000000 --- a/target/linux/generic/backport-6.18/626-13-v6.17-net-pse-pd-Add-support-for-PSE-power-domains.patch +++ /dev/null @@ -1,218 +0,0 @@ -From 50f8b341d26826aa5fdccb8f497fbff2500934b3 Mon Sep 17 00:00:00 2001 -From: "Kory Maincent (Dent Project)" -Date: Tue, 17 Jun 2025 14:12:03 +0200 -Subject: [PATCH] net: pse-pd: Add support for PSE power domains - -Introduce PSE power domain support as groundwork for upcoming port -priority features. Multiple PSE PIs can now be grouped under a single -PSE power domain, enabling future enhancements like defining available -power budgets, port priority modes, and disconnection policies. This -setup will allow the system to assess whether activating a port would -exceed the available power budget, preventing over-budget states -proactively. - -Signed-off-by: Kory Maincent (Dent Project) -Reviewed-by: Oleksij Rempel -Link: https://patch.msgid.link/20250617-feature_poe_port_prio-v14-4-78a1a645e2ee@bootlin.com -Signed-off-by: Jakub Kicinski -Signed-off-by: Carlo Szelinsky ---- - drivers/net/pse-pd/pse_core.c | 140 ++++++++++++++++++++++++++++++++++ - include/linux/pse-pd/pse.h | 2 + - 2 files changed, 142 insertions(+) ---- a/drivers/net/pse-pd/pse_core.c -+++ b/drivers/net/pse-pd/pse_core.c -@@ -16,8 +16,12 @@ - #include - #include - -+#define PSE_PW_D_LIMIT INT_MAX -+ - static DEFINE_MUTEX(pse_list_mutex); - static LIST_HEAD(pse_controller_list); -+static DEFINE_XARRAY_ALLOC(pse_pw_d_map); -+static DEFINE_MUTEX(pse_pw_d_mutex); - - /** - * struct pse_control - a PSE control -@@ -38,6 +42,18 @@ struct pse_control { - struct phy_device *attached_phydev; - }; - -+/** -+ * struct pse_power_domain - a PSE power domain -+ * @id: ID of the power domain -+ * @supply: Power supply the Power Domain -+ * @refcnt: Number of gets of this pse_power_domain -+ */ -+struct pse_power_domain { -+ int id; -+ struct regulator *supply; -+ struct kref refcnt; -+}; -+ - static int of_load_single_pse_pi_pairset(struct device_node *node, - struct pse_pi *pi, - int pairset_num) -@@ -485,6 +501,125 @@ devm_pse_pi_regulator_register(struct ps - return 0; - } - -+static void __pse_pw_d_release(struct kref *kref) -+{ -+ struct pse_power_domain *pw_d = container_of(kref, -+ struct pse_power_domain, -+ refcnt); -+ -+ regulator_put(pw_d->supply); -+ xa_erase(&pse_pw_d_map, pw_d->id); -+ mutex_unlock(&pse_pw_d_mutex); -+} -+ -+/** -+ * pse_flush_pw_ds - flush all PSE power domains of a PSE -+ * @pcdev: a pointer to the initialized PSE controller device -+ */ -+static void pse_flush_pw_ds(struct pse_controller_dev *pcdev) -+{ -+ struct pse_power_domain *pw_d; -+ int i; -+ -+ for (i = 0; i < pcdev->nr_lines; i++) { -+ if (!pcdev->pi[i].pw_d) -+ continue; -+ -+ pw_d = xa_load(&pse_pw_d_map, pcdev->pi[i].pw_d->id); -+ if (!pw_d) -+ continue; -+ -+ kref_put_mutex(&pw_d->refcnt, __pse_pw_d_release, -+ &pse_pw_d_mutex); -+ } -+} -+ -+/** -+ * devm_pse_alloc_pw_d - allocate a new PSE power domain for a device -+ * @dev: device that is registering this PSE power domain -+ * -+ * Return: Pointer to the newly allocated PSE power domain or error pointers -+ */ -+static struct pse_power_domain *devm_pse_alloc_pw_d(struct device *dev) -+{ -+ struct pse_power_domain *pw_d; -+ int index, ret; -+ -+ pw_d = devm_kzalloc(dev, sizeof(*pw_d), GFP_KERNEL); -+ if (!pw_d) -+ return ERR_PTR(-ENOMEM); -+ -+ ret = xa_alloc(&pse_pw_d_map, &index, pw_d, XA_LIMIT(1, PSE_PW_D_LIMIT), -+ GFP_KERNEL); -+ if (ret) -+ return ERR_PTR(ret); -+ -+ kref_init(&pw_d->refcnt); -+ pw_d->id = index; -+ return pw_d; -+} -+ -+/** -+ * pse_register_pw_ds - register the PSE power domains for a PSE -+ * @pcdev: a pointer to the PSE controller device -+ * -+ * Return: 0 on success and failure value on error -+ */ -+static int pse_register_pw_ds(struct pse_controller_dev *pcdev) -+{ -+ int i, ret = 0; -+ -+ mutex_lock(&pse_pw_d_mutex); -+ for (i = 0; i < pcdev->nr_lines; i++) { -+ struct regulator_dev *rdev = pcdev->pi[i].rdev; -+ struct pse_power_domain *pw_d; -+ struct regulator *supply; -+ bool present = false; -+ unsigned long index; -+ -+ /* No regulator or regulator parent supply registered. -+ * We need a regulator parent to register a PSE power domain -+ */ -+ if (!rdev || !rdev->supply) -+ continue; -+ -+ xa_for_each(&pse_pw_d_map, index, pw_d) { -+ /* Power supply already registered as a PSE power -+ * domain. -+ */ -+ if (regulator_is_equal(pw_d->supply, rdev->supply)) { -+ present = true; -+ pcdev->pi[i].pw_d = pw_d; -+ break; -+ } -+ } -+ if (present) { -+ kref_get(&pw_d->refcnt); -+ continue; -+ } -+ -+ pw_d = devm_pse_alloc_pw_d(pcdev->dev); -+ if (IS_ERR(pw_d)) { -+ ret = PTR_ERR(pw_d); -+ goto out; -+ } -+ -+ supply = regulator_get(&rdev->dev, rdev->supply_name); -+ if (IS_ERR(supply)) { -+ xa_erase(&pse_pw_d_map, pw_d->id); -+ ret = PTR_ERR(supply); -+ goto out; -+ } -+ -+ pw_d->supply = supply; -+ pcdev->pi[i].pw_d = pw_d; -+ } -+ -+out: -+ mutex_unlock(&pse_pw_d_mutex); -+ return ret; -+} -+ - /** - * pse_controller_register - register a PSE controller device - * @pcdev: a pointer to the initialized PSE controller device -@@ -544,6 +679,10 @@ int pse_controller_register(struct pse_c - return ret; - } - -+ ret = pse_register_pw_ds(pcdev); -+ if (ret) -+ return ret; -+ - mutex_lock(&pse_list_mutex); - list_add(&pcdev->list, &pse_controller_list); - mutex_unlock(&pse_list_mutex); -@@ -558,6 +697,7 @@ EXPORT_SYMBOL_GPL(pse_controller_registe - */ - void pse_controller_unregister(struct pse_controller_dev *pcdev) - { -+ pse_flush_pw_ds(pcdev); - pse_release_pis(pcdev); - mutex_lock(&pse_list_mutex); - list_del(&pcdev->list); ---- a/include/linux/pse-pd/pse.h -+++ b/include/linux/pse-pd/pse.h -@@ -222,12 +222,14 @@ struct pse_pi_pairset { - * @np: device node pointer of the PSE PI node - * @rdev: regulator represented by the PSE PI - * @admin_state_enabled: PI enabled state -+ * @pw_d: Power domain of the PSE PI - */ - struct pse_pi { - struct pse_pi_pairset pairset[2]; - struct device_node *np; - struct regulator_dev *rdev; - bool admin_state_enabled; -+ struct pse_power_domain *pw_d; - }; - - /** diff --git a/target/linux/generic/backport-6.18/626-14-v6.17-net-pse-pd-ethtool-Add-support-for-power-domains-index.patch b/target/linux/generic/backport-6.18/626-14-v6.17-net-pse-pd-ethtool-Add-support-for-power-domains-index.patch deleted file mode 100644 index 1124882a6a..0000000000 --- a/target/linux/generic/backport-6.18/626-14-v6.17-net-pse-pd-ethtool-Add-support-for-power-domains-index.patch +++ /dev/null @@ -1,78 +0,0 @@ -# ADAPTED FOR OPENWRT 6.12.67 - Documentation changes removed -# Original commit: 1176978ed851 -From 1176978ed851952652ddea3685e2f71a0e5d61ff Mon Sep 17 00:00:00 2001 -From: "Kory Maincent (Dent Project)" -Date: Tue, 17 Jun 2025 14:12:04 +0200 -Subject: [PATCH] net: ethtool: Add support for new power domains index - description - -Report the index of the newly introduced PSE power domain to the user, -enabling improved management of the power budget for PSE devices. - -Signed-off-by: Kory Maincent (Dent Project) -Reviewed-by: Oleksij Rempel -Link: https://patch.msgid.link/20250617-feature_poe_port_prio-v14-5-78a1a645e2ee@bootlin.com -Signed-off-by: Jakub Kicinski -Signed-off-by: Carlo Szelinsky ---- - Documentation/netlink/specs/ethtool.yaml | 5 +++++ - Documentation/networking/ethtool-netlink.rst | 4 ++++ - drivers/net/pse-pd/pse_core.c | 3 +++ - include/linux/pse-pd/pse.h | 2 ++ - include/uapi/linux/ethtool_netlink_generated.h | 1 + - net/ethtool/pse-pd.c | 7 +++++++ - 6 files changed, 22 insertions(+) - ---- a/drivers/net/pse-pd/pse_core.c -+++ b/drivers/net/pse-pd/pse_core.c -@@ -1098,6 +1098,9 @@ int pse_ethtool_get_status(struct pse_co - pcdev = psec->pcdev; - ops = pcdev->ops; - mutex_lock(&pcdev->lock); -+ if (pcdev->pi[psec->id].pw_d) -+ status->pw_d_id = pcdev->pi[psec->id].pw_d->id; -+ - ret = ops->pi_get_admin_state(pcdev, psec->id, &admin_state); - if (ret) - goto out; ---- a/include/linux/pse-pd/pse.h -+++ b/include/linux/pse-pd/pse.h -@@ -114,6 +114,7 @@ struct pse_pw_limit_ranges { - /** - * struct ethtool_pse_control_status - PSE control/channel status. - * -+ * @pw_d_id: PSE power domain index. - * @podl_admin_state: operational state of the PoDL PSE - * functions. IEEE 802.3-2018 30.15.1.1.2 aPoDLPSEAdminState - * @podl_pw_status: power detection status of the PoDL PSE. -@@ -135,6 +136,7 @@ struct pse_pw_limit_ranges { - * ranges - */ - struct ethtool_pse_control_status { -+ u32 pw_d_id; - enum ethtool_podl_pse_admin_state podl_admin_state; - enum ethtool_podl_pse_pw_d_status podl_pw_status; - enum ethtool_c33_pse_admin_state c33_admin_state; ---- a/net/ethtool/pse-pd.c -+++ b/net/ethtool/pse-pd.c -@@ -83,6 +83,8 @@ static int pse_reply_size(const struct e - const struct ethtool_pse_control_status *st = &data->status; - int len = 0; - -+ if (st->pw_d_id) -+ len += nla_total_size(sizeof(u32)); /* _PSE_PW_D_ID */ - if (st->podl_admin_state > 0) - len += nla_total_size(sizeof(u32)); /* _PODL_PSE_ADMIN_STATE */ - if (st->podl_pw_status > 0) -@@ -148,6 +150,11 @@ static int pse_fill_reply(struct sk_buff - const struct pse_reply_data *data = PSE_REPDATA(reply_base); - const struct ethtool_pse_control_status *st = &data->status; - -+ if (st->pw_d_id && -+ nla_put_u32(skb, ETHTOOL_A_PSE_PW_D_ID, -+ st->pw_d_id)) -+ return -EMSGSIZE; -+ - if (st->podl_admin_state > 0 && - nla_put_u32(skb, ETHTOOL_A_PODL_PSE_ADMIN_STATE, - st->podl_admin_state)) diff --git a/target/linux/generic/backport-6.18/626-15-v6.17-net-pse-pd-Add-helper-to-report-hw-enable-status.patch b/target/linux/generic/backport-6.18/626-15-v6.17-net-pse-pd-Add-helper-to-report-hw-enable-status.patch deleted file mode 100644 index ed51289816..0000000000 --- a/target/linux/generic/backport-6.18/626-15-v6.17-net-pse-pd-Add-helper-to-report-hw-enable-status.patch +++ /dev/null @@ -1,74 +0,0 @@ -From c394e757dedd9cf947f9ac470d615d28fd2b07d1 Mon Sep 17 00:00:00 2001 -From: "Kory Maincent (Dent Project)" -Date: Tue, 17 Jun 2025 14:12:05 +0200 -Subject: [PATCH] net: pse-pd: Add helper to report hardware enable status of - the PI - -Refactor code by introducing a helper function to retrieve the hardware -enabled state of the PI, avoiding redundant implementations in the -future. - -Signed-off-by: Kory Maincent (Dent Project) -Reviewed-by: Oleksij Rempel -Link: https://patch.msgid.link/20250617-feature_poe_port_prio-v14-6-78a1a645e2ee@bootlin.com -Signed-off-by: Jakub Kicinski -Signed-off-by: Carlo Szelinsky ---- - drivers/net/pse-pd/pse_core.c | 36 +++++++++++++++++++++++++---------- - 1 file changed, 26 insertions(+), 10 deletions(-) - ---- a/drivers/net/pse-pd/pse_core.c -+++ b/drivers/net/pse-pd/pse_core.c -@@ -272,10 +272,34 @@ static struct net_device *pse_control_ge - return psec->attached_phydev->attached_dev; - } - -+/** -+ * pse_pi_is_hw_enabled - Is PI enabled at the hardware level -+ * @pcdev: a pointer to the PSE controller device -+ * @id: Index of the PI -+ * -+ * Return: 1 if the PI is enabled at the hardware level, 0 if not, and -+ * a failure value on error -+ */ -+static int pse_pi_is_hw_enabled(struct pse_controller_dev *pcdev, int id) -+{ -+ struct pse_admin_state admin_state = {0}; -+ int ret; -+ -+ ret = pcdev->ops->pi_get_admin_state(pcdev, id, &admin_state); -+ if (ret < 0) -+ return ret; -+ -+ /* PI is well enabled at the hardware level */ -+ if (admin_state.podl_admin_state == ETHTOOL_PODL_PSE_ADMIN_STATE_ENABLED || -+ admin_state.c33_admin_state == ETHTOOL_C33_PSE_ADMIN_STATE_ENABLED) -+ return 1; -+ -+ return 0; -+} -+ - static int pse_pi_is_enabled(struct regulator_dev *rdev) - { - struct pse_controller_dev *pcdev = rdev_get_drvdata(rdev); -- struct pse_admin_state admin_state = {0}; - const struct pse_controller_ops *ops; - int id, ret; - -@@ -285,15 +309,7 @@ static int pse_pi_is_enabled(struct regu - - id = rdev_get_id(rdev); - mutex_lock(&pcdev->lock); -- ret = ops->pi_get_admin_state(pcdev, id, &admin_state); -- if (ret) -- goto out; -- -- if (admin_state.podl_admin_state == ETHTOOL_PODL_PSE_ADMIN_STATE_ENABLED || -- admin_state.c33_admin_state == ETHTOOL_C33_PSE_ADMIN_STATE_ENABLED) -- ret = 1; -- --out: -+ ret = pse_pi_is_hw_enabled(pcdev, id); - mutex_unlock(&pcdev->lock); - - return ret; diff --git a/target/linux/generic/backport-6.18/626-16-v6.17-net-pse-pd-Add-support-for-budget-evaluation-strategies.patch b/target/linux/generic/backport-6.18/626-16-v6.17-net-pse-pd-Add-support-for-budget-evaluation-strategies.patch deleted file mode 100644 index c95d8f0fee..0000000000 --- a/target/linux/generic/backport-6.18/626-16-v6.17-net-pse-pd-Add-support-for-budget-evaluation-strategies.patch +++ /dev/null @@ -1,1104 +0,0 @@ -From ffef61d6d27374542f1bce4452200d9bdd2e1edd Mon Sep 17 00:00:00 2001 -From: "Kory Maincent (Dent Project)" -Date: Tue, 17 Jun 2025 14:12:06 +0200 -Subject: [PATCH] net: pse-pd: Add support for budget evaluation strategies - -ADAPTED FOR OPENWRT 6.12.67 - Documentation and ethtool_netlink_generated.h changes removed - -This patch introduces the ability to configure the PSE PI budget evaluation -strategies. Budget evaluation strategies is utilized by PSE controllers to -determine which ports to turn off first in scenarios such as power budget -exceedance. - -The pis_prio_max value is used to define the maximum priority level -supported by the controller. Both the current priority and the maximum -priority are exposed to the user through the pse_ethtool_get_status call. - -This patch add support for two mode of budget evaluation strategies. -1. Static Method: - This method involves distributing power based on PD classification. - -2. Dynamic Method: - Budget evaluation strategy based on the current consumption per ports - compared to the total power budget. - -Signed-off-by: Kory Maincent (Dent Project) -Acked-by: Oleksij Rempel -Link: https://patch.msgid.link/20250617-feature_poe_port_prio-v14-7-78a1a645e2ee@bootlin.com -Signed-off-by: Jakub Kicinski -Signed-off-by: Carlo Szelinsky ---- - drivers/net/pse-pd/pse_core.c | 729 +++++++++++++++++++++++++++++++++- - include/linux/pse-pd/pse.h | 76 ++++ - 2 files changed, 791 insertions(+), 14 deletions(-) - ---- a/drivers/net/pse-pd/pse_core.c -+++ b/drivers/net/pse-pd/pse_core.c -@@ -47,11 +47,14 @@ struct pse_control { - * @id: ID of the power domain - * @supply: Power supply the Power Domain - * @refcnt: Number of gets of this pse_power_domain -+ * @budget_eval_strategy: Current power budget evaluation strategy of the -+ * power domain - */ - struct pse_power_domain { - int id; - struct regulator *supply; - struct kref refcnt; -+ u32 budget_eval_strategy; - }; - - static int of_load_single_pse_pi_pairset(struct device_node *node, -@@ -297,6 +300,115 @@ static int pse_pi_is_hw_enabled(struct p - return 0; - } - -+/** -+ * pse_pi_is_admin_enable_pending - Check if PI is in admin enable pending state -+ * which mean the power is not yet being -+ * delivered -+ * @pcdev: a pointer to the PSE controller device -+ * @id: Index of the PI -+ * -+ * Detects if a PI is enabled in software with a PD detected, but the hardware -+ * admin state hasn't been applied yet. -+ * -+ * This function is used in the power delivery and retry mechanisms to determine -+ * which PIs need to have power delivery attempted again. -+ * -+ * Return: true if the PI has admin enable flag set in software but not yet -+ * reflected in the hardware admin state, false otherwise. -+ */ -+static bool -+pse_pi_is_admin_enable_pending(struct pse_controller_dev *pcdev, int id) -+{ -+ int ret; -+ -+ /* PI not enabled or nothing is plugged */ -+ if (!pcdev->pi[id].admin_state_enabled || -+ !pcdev->pi[id].isr_pd_detected) -+ return false; -+ -+ ret = pse_pi_is_hw_enabled(pcdev, id); -+ /* PSE PI is already enabled at hardware level */ -+ if (ret == 1) -+ return false; -+ -+ return true; -+} -+ -+static int _pse_pi_delivery_power_sw_pw_ctrl(struct pse_controller_dev *pcdev, -+ int id, -+ struct netlink_ext_ack *extack); -+ -+/** -+ * pse_pw_d_retry_power_delivery - Retry power delivery for pending ports in a -+ * PSE power domain -+ * @pcdev: a pointer to the PSE controller device -+ * @pw_d: a pointer to the PSE power domain -+ * -+ * Scans all ports in the specified power domain and attempts to enable power -+ * delivery to any ports that have admin enable state set but don't yet have -+ * hardware power enabled. Used when there are changes in connection status, -+ * admin state, or priority that might allow previously unpowered ports to -+ * receive power, especially in over-budget conditions. -+ */ -+static void pse_pw_d_retry_power_delivery(struct pse_controller_dev *pcdev, -+ struct pse_power_domain *pw_d) -+{ -+ int i, ret = 0; -+ -+ for (i = 0; i < pcdev->nr_lines; i++) { -+ int prio_max = pcdev->nr_lines; -+ struct netlink_ext_ack extack; -+ -+ if (pcdev->pi[i].pw_d != pw_d) -+ continue; -+ -+ if (!pse_pi_is_admin_enable_pending(pcdev, i)) -+ continue; -+ -+ /* Do not try to enable PI with a lower prio (higher value) -+ * than one which already can't be enabled. -+ */ -+ if (pcdev->pi[i].prio > prio_max) -+ continue; -+ -+ ret = _pse_pi_delivery_power_sw_pw_ctrl(pcdev, i, &extack); -+ if (ret == -ERANGE) -+ prio_max = pcdev->pi[i].prio; -+ } -+} -+ -+/** -+ * pse_pw_d_is_sw_pw_control - Determine if power control is software managed -+ * @pcdev: a pointer to the PSE controller device -+ * @pw_d: a pointer to the PSE power domain -+ * -+ * This function determines whether the power control for a specific power -+ * domain is managed by software in the interrupt handler rather than directly -+ * by hardware. -+ * -+ * Software power control is active in the following cases: -+ * - When the budget evaluation strategy is set to static -+ * - When the budget evaluation strategy is disabled but the PSE controller -+ * has an interrupt handler that can report if a Powered Device is connected -+ * -+ * Return: true if the power control of the power domain is managed by software, -+ * false otherwise -+ */ -+static bool pse_pw_d_is_sw_pw_control(struct pse_controller_dev *pcdev, -+ struct pse_power_domain *pw_d) -+{ -+ if (!pw_d) -+ return false; -+ -+ if (pw_d->budget_eval_strategy == PSE_BUDGET_EVAL_STRAT_STATIC) -+ return true; -+ if (pw_d->budget_eval_strategy == PSE_BUDGET_EVAL_STRAT_DISABLED && -+ pcdev->ops->pi_enable && pcdev->irq) -+ return true; -+ -+ return false; -+} -+ - static int pse_pi_is_enabled(struct regulator_dev *rdev) - { - struct pse_controller_dev *pcdev = rdev_get_drvdata(rdev); -@@ -309,17 +421,252 @@ static int pse_pi_is_enabled(struct regu - - id = rdev_get_id(rdev); - mutex_lock(&pcdev->lock); -+ if (pse_pw_d_is_sw_pw_control(pcdev, pcdev->pi[id].pw_d)) { -+ ret = pcdev->pi[id].admin_state_enabled; -+ goto out; -+ } -+ - ret = pse_pi_is_hw_enabled(pcdev, id); -+ -+out: - mutex_unlock(&pcdev->lock); - - return ret; - } - -+/** -+ * pse_pi_deallocate_pw_budget - Deallocate power budget of the PI -+ * @pi: a pointer to the PSE PI -+ */ -+static void pse_pi_deallocate_pw_budget(struct pse_pi *pi) -+{ -+ if (!pi->pw_d || !pi->pw_allocated_mW) -+ return; -+ -+ regulator_free_power_budget(pi->pw_d->supply, pi->pw_allocated_mW); -+ pi->pw_allocated_mW = 0; -+} -+ -+/** -+ * _pse_pi_disable - Call disable operation. Assumes the PSE lock has been -+ * acquired. -+ * @pcdev: a pointer to the PSE -+ * @id: index of the PSE control -+ * -+ * Return: 0 on success and failure value on error -+ */ -+static int _pse_pi_disable(struct pse_controller_dev *pcdev, int id) -+{ -+ const struct pse_controller_ops *ops = pcdev->ops; -+ int ret; -+ -+ if (!ops->pi_disable) -+ return -EOPNOTSUPP; -+ -+ ret = ops->pi_disable(pcdev, id); -+ if (ret) -+ return ret; -+ -+ pse_pi_deallocate_pw_budget(&pcdev->pi[id]); -+ -+ if (pse_pw_d_is_sw_pw_control(pcdev, pcdev->pi[id].pw_d)) -+ pse_pw_d_retry_power_delivery(pcdev, pcdev->pi[id].pw_d); -+ -+ return 0; -+} -+ -+/** -+ * pse_disable_pi_pol - Disable a PI on a power budget policy -+ * @pcdev: a pointer to the PSE -+ * @id: index of the PSE PI -+ * -+ * Return: 0 on success and failure value on error -+ */ -+static int pse_disable_pi_pol(struct pse_controller_dev *pcdev, int id) -+{ -+ unsigned long notifs = ETHTOOL_PSE_EVENT_OVER_BUDGET; -+ struct pse_ntf ntf = {}; -+ int ret; -+ -+ dev_dbg(pcdev->dev, "Disabling PI %d to free power budget\n", id); -+ -+ ret = _pse_pi_disable(pcdev, id); -+ if (ret) -+ notifs |= ETHTOOL_PSE_EVENT_SW_PW_CONTROL_ERROR; -+ -+ ntf.notifs = notifs; -+ ntf.id = id; -+ kfifo_in_spinlocked(&pcdev->ntf_fifo, &ntf, 1, &pcdev->ntf_fifo_lock); -+ schedule_work(&pcdev->ntf_work); -+ -+ return ret; -+} -+ -+/** -+ * pse_disable_pi_prio - Disable all PIs of a given priority inside a PSE -+ * power domain -+ * @pcdev: a pointer to the PSE -+ * @pw_d: a pointer to the PSE power domain -+ * @prio: priority -+ * -+ * Return: 0 on success and failure value on error -+ */ -+static int pse_disable_pi_prio(struct pse_controller_dev *pcdev, -+ struct pse_power_domain *pw_d, -+ int prio) -+{ -+ int i; -+ -+ for (i = 0; i < pcdev->nr_lines; i++) { -+ int ret; -+ -+ if (pcdev->pi[i].prio != prio || -+ pcdev->pi[i].pw_d != pw_d || -+ pse_pi_is_hw_enabled(pcdev, i) <= 0) -+ continue; -+ -+ ret = pse_disable_pi_pol(pcdev, i); -+ if (ret) -+ return ret; -+ } -+ -+ return 0; -+} -+ -+/** -+ * pse_pi_allocate_pw_budget_static_prio - Allocate power budget for the PI -+ * when the budget eval strategy is -+ * static -+ * @pcdev: a pointer to the PSE -+ * @id: index of the PSE control -+ * @pw_req: power requested in mW -+ * @extack: extack for error reporting -+ * -+ * Allocates power using static budget evaluation strategy, where allocation -+ * is based on PD classification. When insufficient budget is available, -+ * lower-priority ports (higher priority numbers) are turned off first. -+ * -+ * Return: 0 on success and failure value on error -+ */ -+static int -+pse_pi_allocate_pw_budget_static_prio(struct pse_controller_dev *pcdev, int id, -+ int pw_req, struct netlink_ext_ack *extack) -+{ -+ struct pse_pi *pi = &pcdev->pi[id]; -+ int ret, _prio; -+ -+ _prio = pcdev->nr_lines; -+ while (regulator_request_power_budget(pi->pw_d->supply, pw_req) == -ERANGE) { -+ if (_prio <= pi->prio) { -+ NL_SET_ERR_MSG_FMT(extack, -+ "PI %d: not enough power budget available", -+ id); -+ return -ERANGE; -+ } -+ -+ ret = pse_disable_pi_prio(pcdev, pi->pw_d, _prio); -+ if (ret < 0) -+ return ret; -+ -+ _prio--; -+ } -+ -+ pi->pw_allocated_mW = pw_req; -+ return 0; -+} -+ -+/** -+ * pse_pi_allocate_pw_budget - Allocate power budget for the PI -+ * @pcdev: a pointer to the PSE -+ * @id: index of the PSE control -+ * @pw_req: power requested in mW -+ * @extack: extack for error reporting -+ * -+ * Return: 0 on success and failure value on error -+ */ -+static int pse_pi_allocate_pw_budget(struct pse_controller_dev *pcdev, int id, -+ int pw_req, struct netlink_ext_ack *extack) -+{ -+ struct pse_pi *pi = &pcdev->pi[id]; -+ -+ if (!pi->pw_d) -+ return 0; -+ -+ /* PSE_BUDGET_EVAL_STRAT_STATIC */ -+ if (pi->pw_d->budget_eval_strategy == PSE_BUDGET_EVAL_STRAT_STATIC) -+ return pse_pi_allocate_pw_budget_static_prio(pcdev, id, pw_req, -+ extack); -+ -+ return 0; -+} -+ -+/** -+ * _pse_pi_delivery_power_sw_pw_ctrl - Enable PSE PI in case of software power -+ * control. Assumes the PSE lock has been -+ * acquired. -+ * @pcdev: a pointer to the PSE -+ * @id: index of the PSE control -+ * @extack: extack for error reporting -+ * -+ * Return: 0 on success and failure value on error -+ */ -+static int _pse_pi_delivery_power_sw_pw_ctrl(struct pse_controller_dev *pcdev, -+ int id, -+ struct netlink_ext_ack *extack) -+{ -+ const struct pse_controller_ops *ops = pcdev->ops; -+ struct pse_pi *pi = &pcdev->pi[id]; -+ int ret, pw_req; -+ -+ if (!ops->pi_get_pw_req) { -+ /* No power allocation management */ -+ ret = ops->pi_enable(pcdev, id); -+ if (ret) -+ NL_SET_ERR_MSG_FMT(extack, -+ "PI %d: enable error %d", -+ id, ret); -+ return ret; -+ } -+ -+ ret = ops->pi_get_pw_req(pcdev, id); -+ if (ret < 0) -+ return ret; -+ -+ pw_req = ret; -+ -+ /* Compare requested power with port power limit and use the lowest -+ * one. -+ */ -+ if (ops->pi_get_pw_limit) { -+ ret = ops->pi_get_pw_limit(pcdev, id); -+ if (ret < 0) -+ return ret; -+ -+ if (ret < pw_req) -+ pw_req = ret; -+ } -+ -+ ret = pse_pi_allocate_pw_budget(pcdev, id, pw_req, extack); -+ if (ret) -+ return ret; -+ -+ ret = ops->pi_enable(pcdev, id); -+ if (ret) { -+ pse_pi_deallocate_pw_budget(pi); -+ NL_SET_ERR_MSG_FMT(extack, -+ "PI %d: enable error %d", -+ id, ret); -+ return ret; -+ } -+ -+ return 0; -+} -+ - static int pse_pi_enable(struct regulator_dev *rdev) - { - struct pse_controller_dev *pcdev = rdev_get_drvdata(rdev); - const struct pse_controller_ops *ops; -- int id, ret; -+ int id, ret = 0; - - ops = pcdev->ops; - if (!ops->pi_enable) -@@ -327,6 +674,23 @@ static int pse_pi_enable(struct regulato - - id = rdev_get_id(rdev); - mutex_lock(&pcdev->lock); -+ if (pse_pw_d_is_sw_pw_control(pcdev, pcdev->pi[id].pw_d)) { -+ /* Manage enabled status by software. -+ * Real enable process will happen if a port is connected. -+ */ -+ if (pcdev->pi[id].isr_pd_detected) { -+ struct netlink_ext_ack extack; -+ -+ ret = _pse_pi_delivery_power_sw_pw_ctrl(pcdev, id, &extack); -+ } -+ if (!ret || ret == -ERANGE) { -+ pcdev->pi[id].admin_state_enabled = 1; -+ ret = 0; -+ } -+ mutex_unlock(&pcdev->lock); -+ return ret; -+ } -+ - ret = ops->pi_enable(pcdev, id); - if (!ret) - pcdev->pi[id].admin_state_enabled = 1; -@@ -338,21 +702,18 @@ static int pse_pi_enable(struct regulato - static int pse_pi_disable(struct regulator_dev *rdev) - { - struct pse_controller_dev *pcdev = rdev_get_drvdata(rdev); -- const struct pse_controller_ops *ops; -+ struct pse_pi *pi; - int id, ret; - -- ops = pcdev->ops; -- if (!ops->pi_disable) -- return -EOPNOTSUPP; -- - id = rdev_get_id(rdev); -+ pi = &pcdev->pi[id]; - mutex_lock(&pcdev->lock); -- ret = ops->pi_disable(pcdev, id); -+ ret = _pse_pi_disable(pcdev, id); - if (!ret) -- pcdev->pi[id].admin_state_enabled = 0; -- mutex_unlock(&pcdev->lock); -+ pi->admin_state_enabled = 0; - -- return ret; -+ mutex_unlock(&pcdev->lock); -+ return 0; - } - - static int _pse_pi_get_voltage(struct regulator_dev *rdev) -@@ -628,6 +989,11 @@ static int pse_register_pw_ds(struct pse - } - - pw_d->supply = supply; -+ if (pcdev->supp_budget_eval_strategies) -+ pw_d->budget_eval_strategy = pcdev->supp_budget_eval_strategies; -+ else -+ pw_d->budget_eval_strategy = PSE_BUDGET_EVAL_STRAT_DISABLED; -+ kref_init(&pw_d->refcnt); - pcdev->pi[i].pw_d = pw_d; - } - -@@ -637,6 +1003,34 @@ out: - } - - /** -+ * pse_send_ntf_worker - Worker to send PSE notifications -+ * @work: work object -+ * -+ * Manage and send PSE netlink notifications using a workqueue to avoid -+ * deadlock between pcdev_lock and pse_list_mutex. -+ */ -+static void pse_send_ntf_worker(struct work_struct *work) -+{ -+ struct pse_controller_dev *pcdev; -+ struct pse_ntf ntf; -+ -+ pcdev = container_of(work, struct pse_controller_dev, ntf_work); -+ -+ while (kfifo_out(&pcdev->ntf_fifo, &ntf, 1)) { -+ struct net_device *netdev; -+ struct pse_control *psec; -+ -+ psec = pse_control_find_by_id(pcdev, ntf.id); -+ rtnl_lock(); -+ netdev = pse_control_get_netdev(psec); -+ if (netdev) -+ ethnl_pse_send_ntf(netdev, ntf.notifs); -+ rtnl_unlock(); -+ pse_control_put(psec); -+ } -+} -+ -+/** - * pse_controller_register - register a PSE controller device - * @pcdev: a pointer to the initialized PSE controller device - * -@@ -649,6 +1043,13 @@ int pse_controller_register(struct pse_c - - mutex_init(&pcdev->lock); - INIT_LIST_HEAD(&pcdev->pse_control_head); -+ spin_lock_init(&pcdev->ntf_fifo_lock); -+ ret = kfifo_alloc(&pcdev->ntf_fifo, pcdev->nr_lines, GFP_KERNEL); -+ if (ret) { -+ dev_err(pcdev->dev, "failed to allocate kfifo notifications\n"); -+ return ret; -+ } -+ INIT_WORK(&pcdev->ntf_work, pse_send_ntf_worker); - - if (!pcdev->nr_lines) - pcdev->nr_lines = 1; -@@ -715,6 +1116,10 @@ void pse_controller_unregister(struct ps - { - pse_flush_pw_ds(pcdev); - pse_release_pis(pcdev); -+ if (pcdev->irq) -+ disable_irq(pcdev->irq); -+ cancel_work_sync(&pcdev->ntf_work); -+ kfifo_free(&pcdev->ntf_fifo); - mutex_lock(&pse_list_mutex); - list_del(&pcdev->list); - mutex_unlock(&pse_list_mutex); -@@ -787,6 +1192,52 @@ static unsigned long pse_to_regulator_no - } - - /** -+ * pse_set_config_isr - Set PSE control config according to the PSE -+ * notifications -+ * @pcdev: a pointer to the PSE -+ * @id: index of the PSE control -+ * @notifs: PSE event notifications -+ * -+ * Return: 0 on success and failure value on error -+ */ -+static int pse_set_config_isr(struct pse_controller_dev *pcdev, int id, -+ unsigned long notifs) -+{ -+ int ret = 0; -+ -+ if (notifs & PSE_BUDGET_EVAL_STRAT_DYNAMIC) -+ return 0; -+ -+ if ((notifs & ETHTOOL_C33_PSE_EVENT_DISCONNECTION) && -+ ((notifs & ETHTOOL_C33_PSE_EVENT_DETECTION) || -+ (notifs & ETHTOOL_C33_PSE_EVENT_CLASSIFICATION))) { -+ dev_dbg(pcdev->dev, -+ "PI %d: error, connection and disconnection reported simultaneously", -+ id); -+ return -EINVAL; -+ } -+ -+ if (notifs & ETHTOOL_C33_PSE_EVENT_CLASSIFICATION) { -+ struct netlink_ext_ack extack; -+ -+ pcdev->pi[id].isr_pd_detected = true; -+ if (pcdev->pi[id].admin_state_enabled) { -+ ret = _pse_pi_delivery_power_sw_pw_ctrl(pcdev, id, -+ &extack); -+ if (ret == -ERANGE) -+ ret = 0; -+ } -+ } else if (notifs & ETHTOOL_C33_PSE_EVENT_DISCONNECTION) { -+ if (pcdev->pi[id].admin_state_enabled && -+ pcdev->pi[id].isr_pd_detected) -+ ret = _pse_pi_disable(pcdev, id); -+ pcdev->pi[id].isr_pd_detected = false; -+ } -+ -+ return ret; -+} -+ -+/** - * pse_isr - IRQ handler for PSE - * @irq: irq number - * @data: pointer to user interrupt structure -@@ -808,36 +1259,42 @@ static irqreturn_t pse_isr(int irq, void - memset(h->notifs, 0, pcdev->nr_lines * sizeof(*h->notifs)); - mutex_lock(&pcdev->lock); - ret = desc->map_event(irq, pcdev, h->notifs, ¬ifs_mask); -- mutex_unlock(&pcdev->lock); -- if (ret || !notifs_mask) -+ if (ret || !notifs_mask) { -+ mutex_unlock(&pcdev->lock); - return IRQ_NONE; -+ } - - for_each_set_bit(i, ¬ifs_mask, pcdev->nr_lines) { - unsigned long notifs, rnotifs; -- struct net_device *netdev; -- struct pse_control *psec; -+ struct pse_ntf ntf = {}; - - /* Do nothing PI not described */ - if (!pcdev->pi[i].rdev) - continue; - - notifs = h->notifs[i]; -+ if (pse_pw_d_is_sw_pw_control(pcdev, pcdev->pi[i].pw_d)) { -+ ret = pse_set_config_isr(pcdev, i, notifs); -+ if (ret) -+ notifs |= ETHTOOL_PSE_EVENT_SW_PW_CONTROL_ERROR; -+ } -+ - dev_dbg(h->pcdev->dev, - "Sending PSE notification EVT 0x%lx\n", notifs); - -- psec = pse_control_find_by_id(pcdev, i); -- rtnl_lock(); -- netdev = pse_control_get_netdev(psec); -- if (netdev) -- ethnl_pse_send_ntf(netdev, notifs); -- rtnl_unlock(); -- pse_control_put(psec); -+ ntf.notifs = notifs; -+ ntf.id = i; -+ kfifo_in_spinlocked(&pcdev->ntf_fifo, &ntf, 1, -+ &pcdev->ntf_fifo_lock); -+ schedule_work(&pcdev->ntf_work); - - rnotifs = pse_to_regulator_notifs(notifs); - regulator_notifier_call_chain(pcdev->pi[i].rdev, rnotifs, - NULL); - } - -+ mutex_unlock(&pcdev->lock); -+ - return IRQ_HANDLED; - } - -@@ -960,6 +1417,20 @@ pse_control_get_internal(struct pse_cont - goto free_psec; - } - -+ if (!pcdev->ops->pi_get_admin_state) { -+ ret = -EOPNOTSUPP; -+ goto free_psec; -+ } -+ -+ /* Initialize admin_state_enabled before the regulator_get. This -+ * aims to have the right value reported in the first is_enabled -+ * call in case of control managed by software. -+ */ -+ ret = pse_pi_is_hw_enabled(pcdev, index); -+ if (ret < 0) -+ goto free_psec; -+ -+ pcdev->pi[index].admin_state_enabled = ret; - psec->ps = devm_regulator_get_exclusive(pcdev->dev, - rdev_get_name(pcdev->pi[index].rdev)); - if (IS_ERR(psec->ps)) { -@@ -967,12 +1438,6 @@ pse_control_get_internal(struct pse_cont - goto put_module; - } - -- ret = regulator_is_enabled(psec->ps); -- if (ret < 0) -- goto regulator_put; -- -- pcdev->pi[index].admin_state_enabled = ret; -- - psec->pcdev = pcdev; - list_add(&psec->list, &pcdev->pse_control_head); - psec->id = index; -@@ -981,8 +1446,6 @@ pse_control_get_internal(struct pse_cont - - return psec; - --regulator_put: -- devm_regulator_put(psec->ps); - put_module: - module_put(pcdev->owner); - free_psec: -@@ -1094,6 +1557,35 @@ out: - EXPORT_SYMBOL_GPL(of_pse_control_get); - - /** -+ * pse_get_sw_admin_state - Convert the software admin state to c33 or podl -+ * admin state value used in the standard -+ * @psec: PSE control pointer -+ * @admin_state: a pointer to the admin_state structure -+ */ -+static void pse_get_sw_admin_state(struct pse_control *psec, -+ struct pse_admin_state *admin_state) -+{ -+ struct pse_pi *pi = &psec->pcdev->pi[psec->id]; -+ -+ if (pse_has_podl(psec)) { -+ if (pi->admin_state_enabled) -+ admin_state->podl_admin_state = -+ ETHTOOL_PODL_PSE_ADMIN_STATE_ENABLED; -+ else -+ admin_state->podl_admin_state = -+ ETHTOOL_PODL_PSE_ADMIN_STATE_DISABLED; -+ } -+ if (pse_has_c33(psec)) { -+ if (pi->admin_state_enabled) -+ admin_state->c33_admin_state = -+ ETHTOOL_C33_PSE_ADMIN_STATE_ENABLED; -+ else -+ admin_state->c33_admin_state = -+ ETHTOOL_C33_PSE_ADMIN_STATE_DISABLED; -+ } -+} -+ -+/** - * pse_ethtool_get_status - get status of PSE control - * @psec: PSE control pointer - * @extack: extack for reporting useful error messages -@@ -1109,19 +1601,46 @@ int pse_ethtool_get_status(struct pse_co - struct pse_pw_status pw_status = {0}; - const struct pse_controller_ops *ops; - struct pse_controller_dev *pcdev; -+ struct pse_pi *pi; - int ret; - - pcdev = psec->pcdev; - ops = pcdev->ops; -+ -+ pi = &pcdev->pi[psec->id]; - mutex_lock(&pcdev->lock); -- if (pcdev->pi[psec->id].pw_d) -- status->pw_d_id = pcdev->pi[psec->id].pw_d->id; -+ if (pi->pw_d) { -+ status->pw_d_id = pi->pw_d->id; -+ if (pse_pw_d_is_sw_pw_control(pcdev, pi->pw_d)) { -+ pse_get_sw_admin_state(psec, &admin_state); -+ } else { -+ ret = ops->pi_get_admin_state(pcdev, psec->id, -+ &admin_state); -+ if (ret) -+ goto out; -+ } -+ status->podl_admin_state = admin_state.podl_admin_state; -+ status->c33_admin_state = admin_state.c33_admin_state; - -- ret = ops->pi_get_admin_state(pcdev, psec->id, &admin_state); -- if (ret) -- goto out; -- status->podl_admin_state = admin_state.podl_admin_state; -- status->c33_admin_state = admin_state.c33_admin_state; -+ switch (pi->pw_d->budget_eval_strategy) { -+ case PSE_BUDGET_EVAL_STRAT_STATIC: -+ status->prio_max = pcdev->nr_lines - 1; -+ status->prio = pi->prio; -+ break; -+ case PSE_BUDGET_EVAL_STRAT_DYNAMIC: -+ status->prio_max = pcdev->pis_prio_max; -+ if (ops->pi_get_prio) { -+ ret = ops->pi_get_prio(pcdev, psec->id); -+ if (ret < 0) -+ goto out; -+ -+ status->prio = ret; -+ } -+ break; -+ default: -+ break; -+ } -+ } - - ret = ops->pi_get_pw_status(pcdev, psec->id, &pw_status); - if (ret) -@@ -1271,6 +1790,52 @@ int pse_ethtool_set_config(struct pse_co - EXPORT_SYMBOL_GPL(pse_ethtool_set_config); - - /** -+ * pse_pi_update_pw_budget - Update PSE power budget allocated with new -+ * power in mW -+ * @pcdev: a pointer to the PSE controller device -+ * @id: index of the PSE PI -+ * @pw_req: power requested -+ * @extack: extack for reporting useful error messages -+ * -+ * Return: Previous power allocated on success and failure value on error -+ */ -+static int pse_pi_update_pw_budget(struct pse_controller_dev *pcdev, int id, -+ const unsigned int pw_req, -+ struct netlink_ext_ack *extack) -+{ -+ struct pse_pi *pi = &pcdev->pi[id]; -+ int previous_pw_allocated; -+ int pw_diff, ret = 0; -+ -+ /* We don't want pw_allocated_mW value change in the middle of an -+ * power budget update -+ */ -+ mutex_lock(&pcdev->lock); -+ previous_pw_allocated = pi->pw_allocated_mW; -+ pw_diff = pw_req - previous_pw_allocated; -+ if (!pw_diff) { -+ goto out; -+ } else if (pw_diff > 0) { -+ ret = regulator_request_power_budget(pi->pw_d->supply, pw_diff); -+ if (ret) { -+ NL_SET_ERR_MSG_FMT(extack, -+ "PI %d: not enough power budget available", -+ id); -+ goto out; -+ } -+ -+ } else { -+ regulator_free_power_budget(pi->pw_d->supply, -pw_diff); -+ } -+ pi->pw_allocated_mW = pw_req; -+ ret = previous_pw_allocated; -+ -+out: -+ mutex_unlock(&pcdev->lock); -+ return ret; -+} -+ -+/** - * pse_ethtool_set_pw_limit - set PSE control power limit - * @psec: PSE control pointer - * @extack: extack for reporting useful error messages -@@ -1282,7 +1847,7 @@ int pse_ethtool_set_pw_limit(struct pse_ - struct netlink_ext_ack *extack, - const unsigned int pw_limit) - { -- int uV, uA, ret; -+ int uV, uA, ret, previous_pw_allocated = 0; - s64 tmp_64; - - if (pw_limit > MAX_PI_PW) -@@ -1306,10 +1871,100 @@ int pse_ethtool_set_pw_limit(struct pse_ - /* uA = mW * 1000000000 / uV */ - uA = DIV_ROUND_CLOSEST_ULL(tmp_64, uV); - -- return regulator_set_current_limit(psec->ps, 0, uA); -+ /* Update power budget only in software power control case and -+ * if a Power Device is powered. -+ */ -+ if (pse_pw_d_is_sw_pw_control(psec->pcdev, -+ psec->pcdev->pi[psec->id].pw_d) && -+ psec->pcdev->pi[psec->id].admin_state_enabled && -+ psec->pcdev->pi[psec->id].isr_pd_detected) { -+ ret = pse_pi_update_pw_budget(psec->pcdev, psec->id, -+ pw_limit, extack); -+ if (ret < 0) -+ return ret; -+ previous_pw_allocated = ret; -+ } -+ -+ ret = regulator_set_current_limit(psec->ps, 0, uA); -+ if (ret < 0 && previous_pw_allocated) { -+ pse_pi_update_pw_budget(psec->pcdev, psec->id, -+ previous_pw_allocated, extack); -+ } -+ -+ return ret; - } - EXPORT_SYMBOL_GPL(pse_ethtool_set_pw_limit); - -+/** -+ * pse_ethtool_set_prio - Set PSE PI priority according to the budget -+ * evaluation strategy -+ * @psec: PSE control pointer -+ * @extack: extack for reporting useful error messages -+ * @prio: priovity value -+ * -+ * Return: 0 on success and failure value on error -+ */ -+int pse_ethtool_set_prio(struct pse_control *psec, -+ struct netlink_ext_ack *extack, -+ unsigned int prio) -+{ -+ struct pse_controller_dev *pcdev = psec->pcdev; -+ const struct pse_controller_ops *ops; -+ int ret = 0; -+ -+ if (!pcdev->pi[psec->id].pw_d) { -+ NL_SET_ERR_MSG(extack, "no power domain attached"); -+ return -EOPNOTSUPP; -+ } -+ -+ /* We don't want priority change in the middle of an -+ * enable/disable call or a priority mode change -+ */ -+ mutex_lock(&pcdev->lock); -+ switch (pcdev->pi[psec->id].pw_d->budget_eval_strategy) { -+ case PSE_BUDGET_EVAL_STRAT_STATIC: -+ if (prio >= pcdev->nr_lines) { -+ NL_SET_ERR_MSG_FMT(extack, -+ "priority %d exceed priority max %d", -+ prio, pcdev->nr_lines); -+ ret = -ERANGE; -+ goto out; -+ } -+ -+ pcdev->pi[psec->id].prio = prio; -+ pse_pw_d_retry_power_delivery(pcdev, pcdev->pi[psec->id].pw_d); -+ break; -+ -+ case PSE_BUDGET_EVAL_STRAT_DYNAMIC: -+ ops = psec->pcdev->ops; -+ if (!ops->pi_set_prio) { -+ NL_SET_ERR_MSG(extack, -+ "pse driver does not support setting port priority"); -+ ret = -EOPNOTSUPP; -+ goto out; -+ } -+ -+ if (prio > pcdev->pis_prio_max) { -+ NL_SET_ERR_MSG_FMT(extack, -+ "priority %d exceed priority max %d", -+ prio, pcdev->pis_prio_max); -+ ret = -ERANGE; -+ goto out; -+ } -+ -+ ret = ops->pi_set_prio(pcdev, psec->id, prio); -+ break; -+ -+ default: -+ ret = -EOPNOTSUPP; -+ } -+ -+out: -+ mutex_unlock(&pcdev->lock); -+ return ret; -+} -+EXPORT_SYMBOL_GPL(pse_ethtool_set_prio); -+ - bool pse_has_podl(struct pse_control *psec) - { - return psec->pcdev->types & ETHTOOL_PSE_PODL; ---- a/include/linux/pse-pd/pse.h -+++ b/include/linux/pse-pd/pse.h -@@ -6,6 +6,8 @@ - #define _LINUX_PSE_CONTROLLER_H - - #include -+#include -+#include - #include - #include - #include -@@ -134,6 +136,9 @@ struct pse_pw_limit_ranges { - * is in charge of the memory allocation - * @c33_pw_limit_nb_ranges: number of supported power limit configuration - * ranges -+ * @prio_max: max priority allowed for the c33_prio variable value. -+ * @prio: priority of the PSE. Managed by PSE core in case of static budget -+ * evaluation strategy. - */ - struct ethtool_pse_control_status { - u32 pw_d_id; -@@ -147,6 +152,8 @@ struct ethtool_pse_control_status { - u32 c33_avail_pw_limit; - struct ethtool_c33_pse_pw_limit_range *c33_pw_limit_ranges; - u32 c33_pw_limit_nb_ranges; -+ u32 prio_max; -+ u32 prio; - }; - - /** -@@ -170,6 +177,11 @@ struct ethtool_pse_control_status { - * range. The driver is in charge of the memory - * allocation and should return the number of - * ranges. -+ * @pi_get_prio: Get the PSE PI priority. -+ * @pi_set_prio: Configure the PSE PI priority. -+ * @pi_get_pw_req: Get the power requested by a PD before enabling the PSE PI. -+ * This is only relevant when an interrupt is registered using -+ * devm_pse_irq_helper helper. - */ - struct pse_controller_ops { - int (*setup_pi_matrix)(struct pse_controller_dev *pcdev); -@@ -190,6 +202,10 @@ struct pse_controller_ops { - int id, int max_mW); - int (*pi_get_pw_limit_ranges)(struct pse_controller_dev *pcdev, int id, - struct pse_pw_limit_ranges *pw_limit_ranges); -+ int (*pi_get_prio)(struct pse_controller_dev *pcdev, int id); -+ int (*pi_set_prio)(struct pse_controller_dev *pcdev, int id, -+ unsigned int prio); -+ int (*pi_get_pw_req)(struct pse_controller_dev *pcdev, int id); - }; - - struct module; -@@ -225,6 +241,13 @@ struct pse_pi_pairset { - * @rdev: regulator represented by the PSE PI - * @admin_state_enabled: PI enabled state - * @pw_d: Power domain of the PSE PI -+ * @prio: Priority of the PSE PI. Used in static budget evaluation strategy -+ * @isr_pd_detected: PSE PI detection status managed by the interruption -+ * handler. This variable is relevant when the power enabled -+ * management is managed in software like the static -+ * budget evaluation strategy. -+ * @pw_allocated_mW: Power allocated to a PSE PI to manage power budget in -+ * static budget evaluation strategy. - */ - struct pse_pi { - struct pse_pi_pairset pairset[2]; -@@ -232,6 +255,20 @@ struct pse_pi { - struct regulator_dev *rdev; - bool admin_state_enabled; - struct pse_power_domain *pw_d; -+ int prio; -+ bool isr_pd_detected; -+ int pw_allocated_mW; -+}; -+ -+/** -+ * struct pse_ntf - PSE notification element -+ * -+ * @id: ID of the PSE control -+ * @notifs: PSE notifications to be reported -+ */ -+struct pse_ntf { -+ int id; -+ unsigned long notifs; - }; - - /** -@@ -249,6 +286,12 @@ struct pse_pi { - * @pi: table of PSE PIs described in this controller device - * @no_of_pse_pi: flag set if the pse_pis devicetree node is not used - * @irq: PSE interrupt -+ * @pis_prio_max: Maximum value allowed for the PSE PIs priority -+ * @supp_budget_eval_strategies: budget evaluation strategies supported -+ * by the PSE -+ * @ntf_work: workqueue for PSE notification management -+ * @ntf_fifo: PSE notifications FIFO -+ * @ntf_fifo_lock: protect @ntf_fifo writer - */ - struct pse_controller_dev { - const struct pse_controller_ops *ops; -@@ -263,6 +306,29 @@ struct pse_controller_dev { - struct pse_pi *pi; - bool no_of_pse_pi; - int irq; -+ unsigned int pis_prio_max; -+ u32 supp_budget_eval_strategies; -+ struct work_struct ntf_work; -+ DECLARE_KFIFO_PTR(ntf_fifo, struct pse_ntf); -+ spinlock_t ntf_fifo_lock; /* Protect @ntf_fifo writer */ -+}; -+ -+/** -+ * enum pse_budget_eval_strategies - PSE budget evaluation strategies. -+ * @PSE_BUDGET_EVAL_STRAT_DISABLED: Budget evaluation strategy disabled. -+ * @PSE_BUDGET_EVAL_STRAT_STATIC: PSE static budget evaluation strategy. -+ * Budget evaluation strategy based on the power requested during PD -+ * classification. This strategy is managed by the PSE core. -+ * @PSE_BUDGET_EVAL_STRAT_DYNAMIC: PSE dynamic budget evaluation -+ * strategy. Budget evaluation strategy based on the current consumption -+ * per ports compared to the total power budget. This mode is managed by -+ * the PSE controller. -+ */ -+ -+enum pse_budget_eval_strategies { -+ PSE_BUDGET_EVAL_STRAT_DISABLED = 1 << 0, -+ PSE_BUDGET_EVAL_STRAT_STATIC = 1 << 1, -+ PSE_BUDGET_EVAL_STRAT_DYNAMIC = 1 << 2, - }; - - #if IS_ENABLED(CONFIG_PSE_CONTROLLER) -@@ -287,6 +353,9 @@ int pse_ethtool_set_config(struct pse_co - int pse_ethtool_set_pw_limit(struct pse_control *psec, - struct netlink_ext_ack *extack, - const unsigned int pw_limit); -+int pse_ethtool_set_prio(struct pse_control *psec, -+ struct netlink_ext_ack *extack, -+ unsigned int prio); - int pse_ethtool_get_pw_limit(struct pse_control *psec, - struct netlink_ext_ack *extack); - -@@ -331,6 +400,13 @@ static inline int pse_ethtool_get_pw_lim - { - return -EOPNOTSUPP; - } -+ -+static inline int pse_ethtool_set_prio(struct pse_control *psec, -+ struct netlink_ext_ack *extack, -+ unsigned int prio) -+{ -+ return -EOPNOTSUPP; -+} - - static inline bool pse_has_podl(struct pse_control *psec) - { diff --git a/target/linux/generic/backport-6.18/626-16b-v6.17-regulator-Add-support-for-power-budget.patch b/target/linux/generic/backport-6.18/626-16b-v6.17-regulator-Add-support-for-power-budget.patch deleted file mode 100644 index b77f96db8e..0000000000 --- a/target/linux/generic/backport-6.18/626-16b-v6.17-regulator-Add-support-for-power-budget.patch +++ /dev/null @@ -1,257 +0,0 @@ -From 42d7c87b4e1251f36eceac987e74623e7cda8577 Mon Sep 17 00:00:00 2001 -From: Kory Maincent -Date: Wed, 15 Jan 2025 15:41:57 +0100 -Subject: [PATCH] regulator: Add support for power budget - -Introduce power budget management for the regulator device. Enable tracking -of available power capacity by providing helpers to request and release -power budget allocations. - -Signed-off-by: Kory Maincent -Link: https://patch.msgid.link/20250115-feature_regulator_pw_budget-v2-1-0a44b949e6bc@bootlin.com -Signed-off-by: Mark Brown -Signed-off-by: Bevan Weiss ---- - drivers/regulator/core.c | 114 +++++++++++++++++++++++++++++ - drivers/regulator/of_regulator.c | 3 + - include/linux/regulator/consumer.h | 21 ++++++ - include/linux/regulator/driver.h | 2 + - include/linux/regulator/machine.h | 2 + - 5 files changed, 142 insertions(+) - ---- a/drivers/regulator/core.c -+++ b/drivers/regulator/core.c -@@ -916,6 +916,26 @@ static ssize_t bypass_show(struct device - } - static DEVICE_ATTR_RO(bypass); - -+static ssize_t power_budget_milliwatt_show(struct device *dev, -+ struct device_attribute *attr, -+ char *buf) -+{ -+ struct regulator_dev *rdev = dev_get_drvdata(dev); -+ -+ return sprintf(buf, "%d\n", rdev->constraints->pw_budget_mW); -+} -+static DEVICE_ATTR_RO(power_budget_milliwatt); -+ -+static ssize_t power_requested_milliwatt_show(struct device *dev, -+ struct device_attribute *attr, -+ char *buf) -+{ -+ struct regulator_dev *rdev = dev_get_drvdata(dev); -+ -+ return sprintf(buf, "%d\n", rdev->pw_requested_mW); -+} -+static DEVICE_ATTR_RO(power_requested_milliwatt); -+ - #define REGULATOR_ERROR_ATTR(name, bit) \ - static ssize_t name##_show(struct device *dev, struct device_attribute *attr, \ - char *buf) \ -@@ -1148,6 +1168,10 @@ static void print_constraints_debug(stru - if (constraints->valid_modes_mask & REGULATOR_MODE_STANDBY) - count += scnprintf(buf + count, len - count, "standby "); - -+ if (constraints->pw_budget_mW) -+ count += scnprintf(buf + count, len - count, "%d mW budget", -+ constraints->pw_budget_mW); -+ - if (!count) - count = scnprintf(buf, len, "no parameters"); - else -@@ -1636,6 +1660,9 @@ static int set_machine_constraints(struc - rdev->last_off = ktime_get(); - } - -+ if (!rdev->constraints->pw_budget_mW) -+ rdev->constraints->pw_budget_mW = INT_MAX; -+ - print_constraints(rdev); - return 0; - } -@@ -4651,6 +4678,87 @@ int regulator_get_current_limit(struct r - EXPORT_SYMBOL_GPL(regulator_get_current_limit); - - /** -+ * regulator_get_unclaimed_power_budget - get regulator unclaimed power budget -+ * @regulator: regulator source -+ * -+ * Return: Unclaimed power budget of the regulator in mW. -+ */ -+int regulator_get_unclaimed_power_budget(struct regulator *regulator) -+{ -+ return regulator->rdev->constraints->pw_budget_mW - -+ regulator->rdev->pw_requested_mW; -+} -+EXPORT_SYMBOL_GPL(regulator_get_unclaimed_power_budget); -+ -+/** -+ * regulator_request_power_budget - request power budget on a regulator -+ * @regulator: regulator source -+ * @pw_req: Power requested -+ * -+ * Return: 0 on success or a negative error number on failure. -+ */ -+int regulator_request_power_budget(struct regulator *regulator, -+ unsigned int pw_req) -+{ -+ struct regulator_dev *rdev = regulator->rdev; -+ int ret = 0, pw_tot_req; -+ -+ regulator_lock(rdev); -+ if (rdev->supply) { -+ ret = regulator_request_power_budget(rdev->supply, pw_req); -+ if (ret < 0) -+ goto out; -+ } -+ -+ pw_tot_req = rdev->pw_requested_mW + pw_req; -+ if (pw_tot_req > rdev->constraints->pw_budget_mW) { -+ rdev_warn(rdev, "power requested %d mW out of budget %d mW", -+ pw_req, -+ rdev->constraints->pw_budget_mW - rdev->pw_requested_mW); -+ regulator_notifier_call_chain(rdev, -+ REGULATOR_EVENT_OVER_CURRENT_WARN, -+ NULL); -+ ret = -ERANGE; -+ goto out; -+ } -+ -+ rdev->pw_requested_mW = pw_tot_req; -+out: -+ regulator_unlock(rdev); -+ return ret; -+} -+EXPORT_SYMBOL_GPL(regulator_request_power_budget); -+ -+/** -+ * regulator_free_power_budget - free power budget on a regulator -+ * @regulator: regulator source -+ * @pw: Power to be released. -+ * -+ * Return: Power budget of the regulator in mW. -+ */ -+void regulator_free_power_budget(struct regulator *regulator, -+ unsigned int pw) -+{ -+ struct regulator_dev *rdev = regulator->rdev; -+ int pw_tot_req; -+ -+ regulator_lock(rdev); -+ if (rdev->supply) -+ regulator_free_power_budget(rdev->supply, pw); -+ -+ pw_tot_req = rdev->pw_requested_mW - pw; -+ if (pw_tot_req >= 0) -+ rdev->pw_requested_mW = pw_tot_req; -+ else -+ rdev_warn(rdev, -+ "too much power freed %d mW (already requested %d mW)", -+ pw, rdev->pw_requested_mW); -+ -+ regulator_unlock(rdev); -+} -+EXPORT_SYMBOL_GPL(regulator_free_power_budget); -+ -+/** - * regulator_set_mode - set regulator operating mode - * @regulator: regulator source - * @mode: operating mode - one of the REGULATOR_MODE constants -@@ -5288,6 +5396,8 @@ static struct attribute *regulator_dev_a - &dev_attr_suspend_standby_mode.attr, - &dev_attr_suspend_mem_mode.attr, - &dev_attr_suspend_disk_mode.attr, -+ &dev_attr_power_budget_milliwatt.attr, -+ &dev_attr_power_requested_milliwatt.attr, - NULL - }; - -@@ -5369,6 +5479,10 @@ static umode_t regulator_attr_is_visible - attr == &dev_attr_suspend_disk_mode.attr) - return ops->set_suspend_mode ? mode : 0; - -+ if (attr == &dev_attr_power_budget_milliwatt.attr || -+ attr == &dev_attr_power_requested_milliwatt.attr) -+ return rdev->constraints->pw_budget_mW != INT_MAX ? mode : 0; -+ - return mode; - } - ---- a/drivers/regulator/of_regulator.c -+++ b/drivers/regulator/of_regulator.c -@@ -125,6 +125,9 @@ static int of_get_regulation_constraints - if (constraints->min_uA != constraints->max_uA) - constraints->valid_ops_mask |= REGULATOR_CHANGE_CURRENT; - -+ if (!of_property_read_u32(np, "regulator-power-budget-milliwatt", &pval)) -+ constraints->pw_budget_mW = pval; -+ - constraints->boot_on = of_property_read_bool(np, "regulator-boot-on"); - constraints->always_on = of_property_read_bool(np, "regulator-always-on"); - if (!constraints->always_on) /* status change should be possible. */ ---- a/include/linux/regulator/consumer.h -+++ b/include/linux/regulator/consumer.h -@@ -235,6 +235,11 @@ int regulator_sync_voltage(struct regula - int regulator_set_current_limit(struct regulator *regulator, - int min_uA, int max_uA); - int regulator_get_current_limit(struct regulator *regulator); -+int regulator_get_unclaimed_power_budget(struct regulator *regulator); -+int regulator_request_power_budget(struct regulator *regulator, -+ unsigned int pw_req); -+void regulator_free_power_budget(struct regulator *regulator, -+ unsigned int pw); - - int regulator_set_mode(struct regulator *regulator, unsigned int mode); - unsigned int regulator_get_mode(struct regulator *regulator); -@@ -534,6 +539,22 @@ static inline int regulator_get_current_ - return 0; - } - -+static inline int regulator_get_unclaimed_power_budget(struct regulator *regulator) -+{ -+ return INT_MAX; -+} -+ -+static inline int regulator_request_power_budget(struct regulator *regulator, -+ unsigned int pw_req) -+{ -+ return -EOPNOTSUPP; -+} -+ -+static inline void regulator_free_power_budget(struct regulator *regulator, -+ unsigned int pw) -+{ -+} -+ - static inline int regulator_set_mode(struct regulator *regulator, - unsigned int mode) - { ---- a/include/linux/regulator/driver.h -+++ b/include/linux/regulator/driver.h -@@ -649,6 +649,8 @@ struct regulator_dev { - int cached_err; - bool use_cached_err; - spinlock_t err_lock; -+ -+ int pw_requested_mW; - }; - - /* ---- a/include/linux/regulator/machine.h -+++ b/include/linux/regulator/machine.h -@@ -113,6 +113,7 @@ struct notification_limit { - * @min_uA: Smallest current consumers may set. - * @max_uA: Largest current consumers may set. - * @ilim_uA: Maximum input current. -+ * @pw_budget_mW: Power budget for the regulator in mW. - * @system_load: Load that isn't captured by any consumer requests. - * - * @over_curr_limits: Limits for acting on over current. -@@ -185,6 +186,7 @@ struct regulation_constraints { - int max_uA; - int ilim_uA; - -+ int pw_budget_mW; - int system_load; - - /* used for coupled regulators */ diff --git a/target/linux/generic/backport-6.18/626-17-v6.17-net-pse-pd-pd692x0-Add-PSE-PI-priority-feature.patch b/target/linux/generic/backport-6.18/626-17-v6.17-net-pse-pd-pd692x0-Add-PSE-PI-priority-feature.patch deleted file mode 100644 index 6e1f2d63c9..0000000000 --- a/target/linux/generic/backport-6.18/626-17-v6.17-net-pse-pd-pd692x0-Add-PSE-PI-priority-feature.patch +++ /dev/null @@ -1,326 +0,0 @@ -From 359754013e6a7fc81af6735ebbfedd4a01999f68 Mon Sep 17 00:00:00 2001 -From: "Kory Maincent (Dent Project)" -Date: Tue, 17 Jun 2025 14:12:08 +0200 -Subject: [PATCH] net: pse-pd: pd692x0: Add support for PSE PI priority feature - -This patch extends the PSE callbacks by adding support for the newly -introduced pi_set_prio() callback, enabling the configuration of PSE PI -priorities. The current port priority is now also included in the status -information returned to users. - -Signed-off-by: Kory Maincent (Dent Project) -Reviewed-by: Oleksij Rempel -Link: https://patch.msgid.link/20250617-feature_poe_port_prio-v14-9-78a1a645e2ee@bootlin.com -Signed-off-by: Jakub Kicinski -Signed-off-by: Carlo Szelinsky ---- - drivers/net/pse-pd/pd692x0.c | 205 +++++++++++++++++++++++++++++++++++ - 1 file changed, 205 insertions(+) - ---- a/drivers/net/pse-pd/pd692x0.c -+++ b/drivers/net/pse-pd/pd692x0.c -@@ -12,6 +12,8 @@ - #include - #include - #include -+#include -+#include - - #define PD692X0_PSE_NAME "pd692x0_pse" - -@@ -76,6 +78,8 @@ enum { - PD692X0_MSG_GET_PORT_CLASS, - PD692X0_MSG_GET_PORT_MEAS, - PD692X0_MSG_GET_PORT_PARAM, -+ PD692X0_MSG_GET_POWER_BANK, -+ PD692X0_MSG_SET_POWER_BANK, - - /* add new message above here */ - PD692X0_MSG_CNT -@@ -95,6 +99,8 @@ struct pd692x0_priv { - unsigned long last_cmd_key_time; - - enum ethtool_c33_pse_admin_state admin_state[PD692X0_MAX_PIS]; -+ struct regulator_dev *manager_reg[PD692X0_MAX_MANAGERS]; -+ int manager_pw_budget[PD692X0_MAX_MANAGERS]; - }; - - /* Template list of communication messages. The non-null bytes defined here -@@ -170,6 +176,16 @@ static const struct pd692x0_msg pd692x0_ - .data = {0x4e, 0x4e, 0x4e, 0x4e, - 0x4e, 0x4e, 0x4e, 0x4e}, - }, -+ [PD692X0_MSG_GET_POWER_BANK] = { -+ .key = PD692X0_KEY_REQ, -+ .sub = {0x07, 0x0b, 0x57}, -+ .data = { 0, 0x4e, 0x4e, 0x4e, -+ 0x4e, 0x4e, 0x4e, 0x4e}, -+ }, -+ [PD692X0_MSG_SET_POWER_BANK] = { -+ .key = PD692X0_KEY_CMD, -+ .sub = {0x07, 0x0b, 0x57}, -+ }, - }; - - static u8 pd692x0_build_msg(struct pd692x0_msg *msg, u8 echo) -@@ -739,6 +755,29 @@ pd692x0_pi_get_actual_pw(struct pse_cont - return (buf.data[0] << 4 | buf.data[1]) * 100; - } - -+static int -+pd692x0_pi_get_prio(struct pse_controller_dev *pcdev, int id) -+{ -+ struct pd692x0_priv *priv = to_pd692x0_priv(pcdev); -+ struct pd692x0_msg msg, buf = {0}; -+ int ret; -+ -+ ret = pd692x0_fw_unavailable(priv); -+ if (ret) -+ return ret; -+ -+ msg = pd692x0_msg_template_list[PD692X0_MSG_GET_PORT_PARAM]; -+ msg.sub[2] = id; -+ ret = pd692x0_sendrecv_msg(priv, &msg, &buf); -+ if (ret < 0) -+ return ret; -+ if (!buf.data[2] || buf.data[2] > pcdev->pis_prio_max + 1) -+ return -ERANGE; -+ -+ /* PSE core priority start at 0 */ -+ return buf.data[2] - 1; -+} -+ - static struct pd692x0_msg_ver pd692x0_get_sw_version(struct pd692x0_priv *priv) - { - struct device *dev = &priv->client->dev; -@@ -766,6 +805,7 @@ static struct pd692x0_msg_ver pd692x0_ge - - struct pd692x0_manager { - struct device_node *port_node[PD692X0_MAX_MANAGER_PORTS]; -+ struct device_node *node; - int nports; - }; - -@@ -857,6 +897,8 @@ pd692x0_of_get_managers(struct pd692x0_p - if (ret) - goto out; - -+ of_node_get(node); -+ manager[manager_id].node = node; - nmanagers++; - } - -@@ -869,6 +911,8 @@ out: - of_node_put(manager[i].port_node[j]); - manager[i].port_node[j] = NULL; - } -+ of_node_put(manager[i].node); -+ manager[i].node = NULL; - } - - of_node_put(node); -@@ -876,6 +920,130 @@ out: - return ret; - } - -+static const struct regulator_ops dummy_ops; -+ -+static struct regulator_dev * -+pd692x0_register_manager_regulator(struct device *dev, char *reg_name, -+ struct device_node *node) -+{ -+ struct regulator_init_data *rinit_data; -+ struct regulator_config rconfig = {0}; -+ struct regulator_desc *rdesc; -+ struct regulator_dev *rdev; -+ -+ rinit_data = devm_kzalloc(dev, sizeof(*rinit_data), -+ GFP_KERNEL); -+ if (!rinit_data) -+ return ERR_PTR(-ENOMEM); -+ -+ rdesc = devm_kzalloc(dev, sizeof(*rdesc), GFP_KERNEL); -+ if (!rdesc) -+ return ERR_PTR(-ENOMEM); -+ -+ rdesc->name = reg_name; -+ rdesc->type = REGULATOR_VOLTAGE; -+ rdesc->ops = &dummy_ops; -+ rdesc->owner = THIS_MODULE; -+ -+ rinit_data->supply_regulator = "vmain"; -+ -+ rconfig.dev = dev; -+ rconfig.init_data = rinit_data; -+ rconfig.of_node = node; -+ -+ rdev = devm_regulator_register(dev, rdesc, &rconfig); -+ if (IS_ERR(rdev)) { -+ dev_err_probe(dev, PTR_ERR(rdev), -+ "Failed to register regulator\n"); -+ return rdev; -+ } -+ -+ return rdev; -+} -+ -+static int -+pd692x0_register_managers_regulator(struct pd692x0_priv *priv, -+ const struct pd692x0_manager *manager, -+ int nmanagers) -+{ -+ struct device *dev = &priv->client->dev; -+ size_t reg_name_len; -+ int i; -+ -+ /* Each regulator name len is dev name + 12 char + -+ * int max digit number (10) + 1 -+ */ -+ reg_name_len = strlen(dev_name(dev)) + 23; -+ -+ for (i = 0; i < nmanagers; i++) { -+ struct regulator_dev *rdev; -+ char *reg_name; -+ -+ reg_name = devm_kzalloc(dev, reg_name_len, GFP_KERNEL); -+ if (!reg_name) -+ return -ENOMEM; -+ snprintf(reg_name, 26, "pse-%s-manager%d", dev_name(dev), i); -+ rdev = pd692x0_register_manager_regulator(dev, reg_name, -+ manager[i].node); -+ if (IS_ERR(rdev)) -+ return PTR_ERR(rdev); -+ -+ priv->manager_reg[i] = rdev; -+ } -+ -+ return 0; -+} -+ -+static int -+pd692x0_conf_manager_power_budget(struct pd692x0_priv *priv, int id, int pw) -+{ -+ struct pd692x0_msg msg, buf; -+ int ret, pw_mW = pw / 1000; -+ -+ msg = pd692x0_msg_template_list[PD692X0_MSG_GET_POWER_BANK]; -+ msg.data[0] = id; -+ ret = pd692x0_sendrecv_msg(priv, &msg, &buf); -+ if (ret < 0) -+ return ret; -+ -+ msg = pd692x0_msg_template_list[PD692X0_MSG_SET_POWER_BANK]; -+ msg.data[0] = id; -+ msg.data[1] = pw_mW >> 8; -+ msg.data[2] = pw_mW & 0xff; -+ msg.data[3] = buf.sub[2]; -+ msg.data[4] = buf.data[0]; -+ msg.data[5] = buf.data[1]; -+ msg.data[6] = buf.data[2]; -+ msg.data[7] = buf.data[3]; -+ return pd692x0_sendrecv_msg(priv, &msg, &buf); -+} -+ -+static int -+pd692x0_configure_managers(struct pd692x0_priv *priv, int nmanagers) -+{ -+ int i, ret; -+ -+ for (i = 0; i < nmanagers; i++) { -+ struct regulator *supply = priv->manager_reg[i]->supply; -+ int pw_budget; -+ -+ pw_budget = regulator_get_unclaimed_power_budget(supply); -+ /* Max power budget per manager */ -+ if (pw_budget > 6000000) -+ pw_budget = 6000000; -+ ret = regulator_request_power_budget(supply, pw_budget); -+ if (ret < 0) -+ return ret; -+ -+ priv->manager_pw_budget[i] = pw_budget; -+ ret = pd692x0_conf_manager_power_budget(priv, i, pw_budget); -+ if (ret < 0) -+ return ret; -+ } -+ -+ return 0; -+} -+ - static int - pd692x0_set_port_matrix(const struct pse_pi_pairset *pairset, - const struct pd692x0_manager *manager, -@@ -998,6 +1166,14 @@ static int pd692x0_setup_pi_matrix(struc - return ret; - - nmanagers = ret; -+ ret = pd692x0_register_managers_regulator(priv, manager, nmanagers); -+ if (ret) -+ goto out; -+ -+ ret = pd692x0_configure_managers(priv, nmanagers); -+ if (ret) -+ goto out; -+ - ret = pd692x0_set_ports_matrix(priv, manager, nmanagers, port_matrix); - if (ret) - goto out; -@@ -1008,8 +1184,14 @@ static int pd692x0_setup_pi_matrix(struc - - out: - for (i = 0; i < nmanagers; i++) { -+ struct regulator *supply = priv->manager_reg[i]->supply; -+ -+ regulator_free_power_budget(supply, -+ priv->manager_pw_budget[i]); -+ - for (j = 0; j < manager[i].nports; j++) - of_node_put(manager[i].port_node[j]); -+ of_node_put(manager[i].node); - } - return ret; - } -@@ -1071,6 +1253,25 @@ static int pd692x0_pi_set_pw_limit(struc - return pd692x0_sendrecv_msg(priv, &msg, &buf); - } - -+static int pd692x0_pi_set_prio(struct pse_controller_dev *pcdev, int id, -+ unsigned int prio) -+{ -+ struct pd692x0_priv *priv = to_pd692x0_priv(pcdev); -+ struct pd692x0_msg msg, buf = {0}; -+ int ret; -+ -+ ret = pd692x0_fw_unavailable(priv); -+ if (ret) -+ return ret; -+ -+ msg = pd692x0_msg_template_list[PD692X0_MSG_SET_PORT_PARAM]; -+ msg.sub[2] = id; -+ /* Controller priority from 1 to 3 */ -+ msg.data[4] = prio + 1; -+ -+ return pd692x0_sendrecv_msg(priv, &msg, &buf); -+} -+ - static const struct pse_controller_ops pd692x0_ops = { - .setup_pi_matrix = pd692x0_setup_pi_matrix, - .pi_get_admin_state = pd692x0_pi_get_admin_state, -@@ -1084,6 +1285,8 @@ static const struct pse_controller_ops p - .pi_get_pw_limit = pd692x0_pi_get_pw_limit, - .pi_set_pw_limit = pd692x0_pi_set_pw_limit, - .pi_get_pw_limit_ranges = pd692x0_pi_get_pw_limit_ranges, -+ .pi_get_prio = pd692x0_pi_get_prio, -+ .pi_set_prio = pd692x0_pi_set_prio, - }; - - #define PD692X0_FW_LINE_MAX_SZ 0xff -@@ -1500,6 +1703,8 @@ static int pd692x0_i2c_probe(struct i2c_ - priv->pcdev.ops = &pd692x0_ops; - priv->pcdev.dev = dev; - priv->pcdev.types = ETHTOOL_PSE_C33; -+ priv->pcdev.supp_budget_eval_strategies = PSE_BUDGET_EVAL_STRAT_DYNAMIC; -+ priv->pcdev.pis_prio_max = 2; - ret = devm_pse_controller_register(dev, &priv->pcdev); - if (ret) - return dev_err_probe(dev, ret, diff --git a/target/linux/generic/backport-6.18/626-18-v6.17-net-pse-pd-pd692x0-Add-controller-and-manager-power.patch b/target/linux/generic/backport-6.18/626-18-v6.17-net-pse-pd-pd692x0-Add-controller-and-manager-power.patch deleted file mode 100644 index a93dca0999..0000000000 --- a/target/linux/generic/backport-6.18/626-18-v6.17-net-pse-pd-pd692x0-Add-controller-and-manager-power.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 24a4e3a05dd0eadd0c9585c411880e5dcb6be97f Mon Sep 17 00:00:00 2001 -From: "Kory Maincent (Dent Project)" -Date: Tue, 17 Jun 2025 14:12:09 +0200 -Subject: [PATCH] net: pse-pd: pd692x0: Add support for controller and manager - power supplies - -Add support for managing the VDD and VDDA power supplies for the PD692x0 -PSE controller, as well as the VAUX5 and VAUX3P3 power supplies for the -PD6920x PSE managers. - -Signed-off-by: Kory Maincent (Dent Project) -Reviewed-by: Oleksij Rempel -Link: https://patch.msgid.link/20250617-feature_poe_port_prio-v14-10-78a1a645e2ee@bootlin.com -Signed-off-by: Jakub Kicinski -Signed-off-by: Carlo Szelinsky ---- - drivers/net/pse-pd/pd692x0.c | 20 ++++++++++++++++++++ - 1 file changed, 20 insertions(+) - ---- a/drivers/net/pse-pd/pd692x0.c -+++ b/drivers/net/pse-pd/pd692x0.c -@@ -976,8 +976,10 @@ pd692x0_register_managers_regulator(stru - reg_name_len = strlen(dev_name(dev)) + 23; - - for (i = 0; i < nmanagers; i++) { -+ static const char * const regulators[] = { "vaux5", "vaux3p3" }; - struct regulator_dev *rdev; - char *reg_name; -+ int ret; - - reg_name = devm_kzalloc(dev, reg_name_len, GFP_KERNEL); - if (!reg_name) -@@ -988,6 +990,17 @@ pd692x0_register_managers_regulator(stru - if (IS_ERR(rdev)) - return PTR_ERR(rdev); - -+ /* VMAIN is described as main supply for the manager. -+ * Add other VAUX power supplies and link them to the -+ * virtual device rdev->dev. -+ */ -+ ret = devm_regulator_bulk_get_enable(&rdev->dev, -+ ARRAY_SIZE(regulators), -+ regulators); -+ if (ret) -+ return dev_err_probe(&rdev->dev, ret, -+ "Failed to enable regulators\n"); -+ - priv->manager_reg[i] = rdev; - } - -@@ -1640,6 +1653,7 @@ static const struct fw_upload_ops pd692x - - static int pd692x0_i2c_probe(struct i2c_client *client) - { -+ static const char * const regulators[] = { "vdd", "vdda" }; - struct pd692x0_msg msg, buf = {0}, zero = {0}; - struct device *dev = &client->dev; - struct pd692x0_msg_ver ver; -@@ -1647,6 +1661,12 @@ static int pd692x0_i2c_probe(struct i2c_ - struct fw_upload *fwl; - int ret; - -+ ret = devm_regulator_bulk_get_enable(dev, ARRAY_SIZE(regulators), -+ regulators); -+ if (ret) -+ return dev_err_probe(dev, ret, -+ "Failed to enable regulators\n"); -+ - if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { - dev_err(dev, "i2c check functionality failed\n"); - return -ENXIO; diff --git a/target/linux/generic/backport-6.18/626-19-v6.17-net-pse-pd-tps23881-Add-static-port-priority-feature.patch b/target/linux/generic/backport-6.18/626-19-v6.17-net-pse-pd-tps23881-Add-static-port-priority-feature.patch deleted file mode 100644 index 739233a12e..0000000000 --- a/target/linux/generic/backport-6.18/626-19-v6.17-net-pse-pd-tps23881-Add-static-port-priority-feature.patch +++ /dev/null @@ -1,392 +0,0 @@ -From 56cfc97635e9164395c9242f72746454347155ab Mon Sep 17 00:00:00 2001 -From: "Kory Maincent (Dent Project)" -Date: Tue, 17 Jun 2025 14:12:11 +0200 -Subject: [PATCH] net: pse-pd: tps23881: Add support for static port priority - feature - -This patch enhances PSE callbacks by introducing support for the static -port priority feature. It extends interrupt management to handle and report -detection, classification, and disconnection events. Additionally, it -introduces the pi_get_pw_req() callback, which provides information about -the power requested by the Powered Devices. - -Interrupt support is essential for the proper functioning of the TPS23881 -controller. Without it, after a power-on (PWON), the controller will -no longer perform detection and classification. This could lead to -potential hazards, such as connecting a non-PoE device after a PoE device, -which might result in magic smoke. - -Signed-off-by: Kory Maincent (Dent Project) -Reviewed-by: Oleksij Rempel -Link: https://patch.msgid.link/20250617-feature_poe_port_prio-v14-12-78a1a645e2ee@bootlin.com -Signed-off-by: Jakub Kicinski -Signed-off-by: Carlo Szelinsky ---- - drivers/net/pse-pd/tps23881.c | 244 +++++++++++++++++++++++++++++++--- - 1 file changed, 228 insertions(+), 16 deletions(-) - ---- a/drivers/net/pse-pd/tps23881.c -+++ b/drivers/net/pse-pd/tps23881.c -@@ -20,20 +20,30 @@ - - #define TPS23881_REG_IT 0x0 - #define TPS23881_REG_IT_MASK 0x1 -+#define TPS23881_REG_IT_DISF BIT(2) -+#define TPS23881_REG_IT_DETC BIT(3) -+#define TPS23881_REG_IT_CLASC BIT(4) - #define TPS23881_REG_IT_IFAULT BIT(5) - #define TPS23881_REG_IT_SUPF BIT(7) -+#define TPS23881_REG_DET_EVENT 0x5 - #define TPS23881_REG_FAULT 0x7 - #define TPS23881_REG_SUPF_EVENT 0xb - #define TPS23881_REG_TSD BIT(7) -+#define TPS23881_REG_DISC 0xc - #define TPS23881_REG_PW_STATUS 0x10 - #define TPS23881_REG_OP_MODE 0x12 -+#define TPS23881_REG_DISC_EN 0x13 - #define TPS23881_OP_MODE_SEMIAUTO 0xaaaa - #define TPS23881_REG_DIS_EN 0x13 - #define TPS23881_REG_DET_CLA_EN 0x14 - #define TPS23881_REG_GEN_MASK 0x17 -+#define TPS23881_REG_CLCHE BIT(2) -+#define TPS23881_REG_DECHE BIT(3) - #define TPS23881_REG_NBITACC BIT(5) - #define TPS23881_REG_INTEN BIT(7) - #define TPS23881_REG_PW_EN 0x19 -+#define TPS23881_REG_RESET 0x1a -+#define TPS23881_REG_CLRAIN BIT(7) - #define TPS23881_REG_2PAIR_POL1 0x1e - #define TPS23881_REG_PORT_MAP 0x26 - #define TPS23881_REG_PORT_POWER 0x29 -@@ -178,6 +188,7 @@ static int tps23881_pi_enable(struct pse - struct i2c_client *client = priv->client; - u8 chan; - u16 val; -+ int ret; - - if (id >= TPS23881_MAX_CHANS) - return -ERANGE; -@@ -191,7 +202,22 @@ static int tps23881_pi_enable(struct pse - BIT(chan % 4)); - } - -- return i2c_smbus_write_word_data(client, TPS23881_REG_PW_EN, val); -+ ret = i2c_smbus_write_word_data(client, TPS23881_REG_PW_EN, val); -+ if (ret) -+ return ret; -+ -+ /* Enable DC disconnect*/ -+ chan = priv->port[id].chan[0]; -+ ret = i2c_smbus_read_word_data(client, TPS23881_REG_DISC_EN); -+ if (ret < 0) -+ return ret; -+ -+ val = tps23881_set_val(ret, chan, 0, BIT(chan % 4), BIT(chan % 4)); -+ ret = i2c_smbus_write_word_data(client, TPS23881_REG_DISC_EN, val); -+ if (ret) -+ return ret; -+ -+ return 0; - } - - static int tps23881_pi_disable(struct pse_controller_dev *pcdev, int id) -@@ -224,6 +250,17 @@ static int tps23881_pi_disable(struct ps - */ - mdelay(5); - -+ /* Disable DC disconnect*/ -+ chan = priv->port[id].chan[0]; -+ ret = i2c_smbus_read_word_data(client, TPS23881_REG_DISC_EN); -+ if (ret < 0) -+ return ret; -+ -+ val = tps23881_set_val(ret, chan, 0, 0, BIT(chan % 4)); -+ ret = i2c_smbus_write_word_data(client, TPS23881_REG_DISC_EN, val); -+ if (ret) -+ return ret; -+ - /* Enable detection and classification */ - ret = i2c_smbus_read_word_data(client, TPS23881_REG_DET_CLA_EN); - if (ret < 0) -@@ -919,6 +956,47 @@ static int tps23881_setup_pi_matrix(stru - return ret; - } - -+static int tps23881_power_class_table[] = { -+ -ERANGE, -+ 4000, -+ 7000, -+ 15500, -+ 30000, -+ 15500, -+ 15500, -+ -ERANGE, -+ 45000, -+ 60000, -+ 75000, -+ 90000, -+ 15500, -+ 45000, -+ -ERANGE, -+ -ERANGE, -+}; -+ -+static int tps23881_pi_get_pw_req(struct pse_controller_dev *pcdev, int id) -+{ -+ struct tps23881_priv *priv = to_tps23881_priv(pcdev); -+ struct i2c_client *client = priv->client; -+ u8 reg, chan; -+ int ret; -+ u16 val; -+ -+ /* For a 4-pair the classification need 5ms to be completed */ -+ if (priv->port[id].is_4p) -+ mdelay(5); -+ -+ chan = priv->port[id].chan[0]; -+ reg = TPS23881_REG_DISC + (chan % 4); -+ ret = i2c_smbus_read_word_data(client, reg); -+ if (ret < 0) -+ return ret; -+ -+ val = tps23881_calc_val(ret, chan, 4, 0xf); -+ return tps23881_power_class_table[val]; -+} -+ - static const struct pse_controller_ops tps23881_ops = { - .setup_pi_matrix = tps23881_setup_pi_matrix, - .pi_enable = tps23881_pi_enable, -@@ -931,6 +1009,7 @@ static const struct pse_controller_ops t - .pi_get_pw_limit = tps23881_pi_get_pw_limit, - .pi_set_pw_limit = tps23881_pi_set_pw_limit, - .pi_get_pw_limit_ranges = tps23881_pi_get_pw_limit_ranges, -+ .pi_get_pw_req = tps23881_pi_get_pw_req, - }; - - static const char fw_parity_name[] = "ti/tps23881/tps23881-parity-14.bin"; -@@ -1088,17 +1167,113 @@ static void tps23881_irq_event_over_temp - } - } - --static void tps23881_irq_event_over_current(struct tps23881_priv *priv, -- u16 reg_val, -- unsigned long *notifs, -- unsigned long *notifs_mask) -+static int tps23881_irq_event_over_current(struct tps23881_priv *priv, -+ u16 reg_val, -+ unsigned long *notifs, -+ unsigned long *notifs_mask) - { -+ int i, ret; - u8 chans; - - chans = tps23881_irq_export_chans_helper(reg_val, 0); -+ if (!chans) -+ return 0; -+ -+ tps23881_set_notifs_helper(priv, chans, notifs, notifs_mask, -+ ETHTOOL_PSE_EVENT_OVER_CURRENT | -+ ETHTOOL_C33_PSE_EVENT_DISCONNECTION); -+ -+ /* Over Current event resets the power limit registers so we need -+ * to configured it again. -+ */ -+ for_each_set_bit(i, notifs_mask, priv->pcdev.nr_lines) { -+ if (priv->port[i].pw_pol < 0) -+ continue; -+ -+ ret = tps23881_pi_enable_manual_pol(priv, i); -+ if (ret < 0) -+ return ret; -+ -+ /* Set power policy */ -+ ret = tps23881_pi_set_pw_pol_limit(priv, i, -+ priv->port[i].pw_pol, -+ priv->port[i].is_4p); -+ if (ret < 0) -+ return ret; -+ } -+ -+ return 0; -+} -+ -+static void tps23881_irq_event_disconnection(struct tps23881_priv *priv, -+ u16 reg_val, -+ unsigned long *notifs, -+ unsigned long *notifs_mask) -+{ -+ u8 chans; -+ -+ chans = tps23881_irq_export_chans_helper(reg_val, 4); - if (chans) - tps23881_set_notifs_helper(priv, chans, notifs, notifs_mask, -- ETHTOOL_PSE_EVENT_OVER_CURRENT); -+ ETHTOOL_C33_PSE_EVENT_DISCONNECTION); -+} -+ -+static int tps23881_irq_event_detection(struct tps23881_priv *priv, -+ u16 reg_val, -+ unsigned long *notifs, -+ unsigned long *notifs_mask) -+{ -+ enum ethtool_pse_event event; -+ int reg, ret, i, val; -+ unsigned long chans; -+ -+ chans = tps23881_irq_export_chans_helper(reg_val, 0); -+ for_each_set_bit(i, &chans, TPS23881_MAX_CHANS) { -+ reg = TPS23881_REG_DISC + (i % 4); -+ ret = i2c_smbus_read_word_data(priv->client, reg); -+ if (ret < 0) -+ return ret; -+ -+ val = tps23881_calc_val(ret, i, 0, 0xf); -+ /* If detection valid */ -+ if (val == 0x4) -+ event = ETHTOOL_C33_PSE_EVENT_DETECTION; -+ else -+ event = ETHTOOL_C33_PSE_EVENT_DISCONNECTION; -+ -+ tps23881_set_notifs_helper(priv, BIT(i), notifs, -+ notifs_mask, event); -+ } -+ -+ return 0; -+} -+ -+static int tps23881_irq_event_classification(struct tps23881_priv *priv, -+ u16 reg_val, -+ unsigned long *notifs, -+ unsigned long *notifs_mask) -+{ -+ int reg, ret, val, i; -+ unsigned long chans; -+ -+ chans = tps23881_irq_export_chans_helper(reg_val, 4); -+ for_each_set_bit(i, &chans, TPS23881_MAX_CHANS) { -+ reg = TPS23881_REG_DISC + (i % 4); -+ ret = i2c_smbus_read_word_data(priv->client, reg); -+ if (ret < 0) -+ return ret; -+ -+ val = tps23881_calc_val(ret, i, 4, 0xf); -+ /* Do not report classification event for unknown class */ -+ if (!val || val == 0x8 || val == 0xf) -+ continue; -+ -+ tps23881_set_notifs_helper(priv, BIT(i), notifs, -+ notifs_mask, -+ ETHTOOL_C33_PSE_EVENT_CLASSIFICATION); -+ } -+ -+ return 0; - } - - static int tps23881_irq_event_handler(struct tps23881_priv *priv, u16 reg, -@@ -1106,7 +1281,7 @@ static int tps23881_irq_event_handler(st - unsigned long *notifs_mask) - { - struct i2c_client *client = priv->client; -- int ret; -+ int ret, val; - - /* The Supply event bit is repeated twice so we only need to read - * the one from the first byte. -@@ -1118,13 +1293,36 @@ static int tps23881_irq_event_handler(st - tps23881_irq_event_over_temp(priv, ret, notifs, notifs_mask); - } - -- if (reg & (TPS23881_REG_IT_IFAULT | TPS23881_REG_IT_IFAULT << 8)) { -+ if (reg & (TPS23881_REG_IT_IFAULT | TPS23881_REG_IT_IFAULT << 8 | -+ TPS23881_REG_IT_DISF | TPS23881_REG_IT_DISF << 8)) { - ret = i2c_smbus_read_word_data(client, TPS23881_REG_FAULT); - if (ret < 0) - return ret; -- tps23881_irq_event_over_current(priv, ret, notifs, notifs_mask); -+ ret = tps23881_irq_event_over_current(priv, ret, notifs, -+ notifs_mask); -+ if (ret) -+ return ret; -+ -+ tps23881_irq_event_disconnection(priv, ret, notifs, notifs_mask); - } - -+ if (reg & (TPS23881_REG_IT_DETC | TPS23881_REG_IT_DETC << 8 | -+ TPS23881_REG_IT_CLASC | TPS23881_REG_IT_CLASC << 8)) { -+ ret = i2c_smbus_read_word_data(client, TPS23881_REG_DET_EVENT); -+ if (ret < 0) -+ return ret; -+ -+ val = ret; -+ ret = tps23881_irq_event_detection(priv, val, notifs, -+ notifs_mask); -+ if (ret) -+ return ret; -+ -+ ret = tps23881_irq_event_classification(priv, val, notifs, -+ notifs_mask); -+ if (ret) -+ return ret; -+ } - return 0; - } - -@@ -1178,7 +1376,14 @@ static int tps23881_setup_irq(struct tps - int ret; - u16 val; - -- val = TPS23881_REG_IT_IFAULT | TPS23881_REG_IT_SUPF; -+ if (!irq) { -+ dev_err(&client->dev, "interrupt is missing"); -+ return -EINVAL; -+ } -+ -+ val = TPS23881_REG_IT_IFAULT | TPS23881_REG_IT_SUPF | -+ TPS23881_REG_IT_DETC | TPS23881_REG_IT_CLASC | -+ TPS23881_REG_IT_DISF; - val |= val << 8; - ret = i2c_smbus_write_word_data(client, TPS23881_REG_IT_MASK, val); - if (ret) -@@ -1188,11 +1393,19 @@ static int tps23881_setup_irq(struct tps - if (ret < 0) - return ret; - -- val = (u16)(ret | TPS23881_REG_INTEN | TPS23881_REG_INTEN << 8); -+ val = TPS23881_REG_INTEN | TPS23881_REG_CLCHE | TPS23881_REG_DECHE; -+ val |= val << 8; -+ val |= (u16)ret; - ret = i2c_smbus_write_word_data(client, TPS23881_REG_GEN_MASK, val); - if (ret < 0) - return ret; - -+ /* Reset interrupts registers */ -+ ret = i2c_smbus_write_word_data(client, TPS23881_REG_RESET, -+ TPS23881_REG_CLRAIN); -+ if (ret < 0) -+ return ret; -+ - return devm_pse_irq_helper(&priv->pcdev, irq, 0, &irq_desc); - } - -@@ -1270,17 +1483,16 @@ static int tps23881_i2c_probe(struct i2c - priv->pcdev.dev = dev; - priv->pcdev.types = ETHTOOL_PSE_C33; - priv->pcdev.nr_lines = TPS23881_MAX_CHANS; -+ priv->pcdev.supp_budget_eval_strategies = PSE_BUDGET_EVAL_STRAT_STATIC; - ret = devm_pse_controller_register(dev, &priv->pcdev); - if (ret) { - return dev_err_probe(dev, ret, - "failed to register PSE controller\n"); - } - -- if (client->irq) { -- ret = tps23881_setup_irq(priv, client->irq); -- if (ret) -- return ret; -- } -+ ret = tps23881_setup_irq(priv, client->irq); -+ if (ret) -+ return ret; - - return ret; - } diff --git a/target/linux/generic/backport-6.18/626-20-v6.17-net-pse-pd-pd692x0-reduce-stack-usage.patch b/target/linux/generic/backport-6.18/626-20-v6.17-net-pse-pd-pd692x0-reduce-stack-usage.patch deleted file mode 100644 index d5e1aaf9a3..0000000000 --- a/target/linux/generic/backport-6.18/626-20-v6.17-net-pse-pd-pd692x0-reduce-stack-usage.patch +++ /dev/null @@ -1,55 +0,0 @@ -From d12b3dc106090b358fb67b7c0c717a0884327ddf Mon Sep 17 00:00:00 2001 -From: Arnd Bergmann -Date: Wed, 9 Jul 2025 17:32:04 +0200 -Subject: [PATCH] net: pse-pd: pd692x0: reduce stack usage in - pd692x0_setup_pi_matrix - -The pd692x0_manager array in this function is really too big to fit on the -stack, though this never triggered a warning until a recent patch made -it slightly bigger: - -drivers/net/pse-pd/pd692x0.c: In function 'pd692x0_setup_pi_matrix': -drivers/net/pse-pd/pd692x0.c:1210:1: error: the frame size of 1584 bytes is larger than 1536 bytes [-Werror=frame-larger-than=] - -Change the function to dynamically allocate the array here. - -Fixes: 359754013e6a ("net: pse-pd: pd692x0: Add support for PSE PI priority feature") -Signed-off-by: Arnd Bergmann -Reviewed-by: Kory Maincent -Link: https://patch.msgid.link/20250709153210.1920125-1-arnd@kernel.org -Signed-off-by: Jakub Kicinski -Signed-off-by: Carlo Szelinsky ---- - drivers/net/pse-pd/pd692x0.c | 8 ++++++-- - 1 file changed, 6 insertions(+), 2 deletions(-) ---- a/drivers/net/pse-pd/pd692x0.c -+++ b/drivers/net/pse-pd/pd692x0.c -@@ -860,7 +860,7 @@ out: - - static int - pd692x0_of_get_managers(struct pd692x0_priv *priv, -- struct pd692x0_manager manager[PD692X0_MAX_MANAGERS]) -+ struct pd692x0_manager *manager) - { - struct device_node *managers_node, *node; - int ret, nmanagers, i, j; -@@ -1164,7 +1164,7 @@ pd692x0_write_ports_matrix(struct pd692x - - static int pd692x0_setup_pi_matrix(struct pse_controller_dev *pcdev) - { -- struct pd692x0_manager manager[PD692X0_MAX_MANAGERS] = {0}; -+ struct pd692x0_manager *manager __free(kfree) = NULL; - struct pd692x0_priv *priv = to_pd692x0_priv(pcdev); - struct pd692x0_matrix port_matrix[PD692X0_MAX_PIS]; - int ret, i, j, nmanagers; -@@ -1174,6 +1174,10 @@ static int pd692x0_setup_pi_matrix(struc - priv->fw_state != PD692X0_FW_COMPLETE) - return 0; - -+ manager = kcalloc(PD692X0_MAX_MANAGERS, sizeof(*manager), GFP_KERNEL); -+ if (!manager) -+ return -ENOMEM; -+ - ret = pd692x0_of_get_managers(priv, manager); - if (ret < 0) - return ret; diff --git a/target/linux/generic/backport-6.18/626-21-v6.18-net-pse-pd-pd692x0-Fix-power-budget-leak.patch b/target/linux/generic/backport-6.18/626-21-v6.18-net-pse-pd-pd692x0-Fix-power-budget-leak.patch deleted file mode 100644 index af23745947..0000000000 --- a/target/linux/generic/backport-6.18/626-21-v6.18-net-pse-pd-pd692x0-Fix-power-budget-leak.patch +++ /dev/null @@ -1,121 +0,0 @@ -From 1c67f9c54cdc70627e3f6472b89cd3d895df974c Mon Sep 17 00:00:00 2001 -From: Kory Maincent -Date: Wed, 20 Aug 2025 15:27:07 +0200 -Subject: [PATCH] net: pse-pd: pd692x0: Fix power budget leak in manager setup - error path - -Fix a resource leak where manager power budgets were freed on both -success and error paths during manager setup. Power budgets should -only be freed on error paths after regulator registration or during -driver removal. - -Refactor cleanup logic by extracting OF node cleanup and power budget -freeing into separate helper functions for better maintainability. - -Fixes: 359754013e6a ("net: pse-pd: pd692x0: Add support for PSE PI priority feature") -Signed-off-by: Kory Maincent -Link: https://patch.msgid.link/20250820132708.837255-1-kory.maincent@bootlin.com -Signed-off-by: Jakub Kicinski -Signed-off-by: Carlo Szelinsky ---- - drivers/net/pse-pd/pd692x0.c | 59 +++++++++++++++++++++++++++--------- - 1 file changed, 44 insertions(+), 15 deletions(-) - ---- a/drivers/net/pse-pd/pd692x0.c -+++ b/drivers/net/pse-pd/pd692x0.c -@@ -1162,12 +1162,44 @@ pd692x0_write_ports_matrix(struct pd692x - return 0; - } - -+static void pd692x0_of_put_managers(struct pd692x0_priv *priv, -+ struct pd692x0_manager *manager, -+ int nmanagers) -+{ -+ int i, j; -+ -+ for (i = 0; i < nmanagers; i++) { -+ for (j = 0; j < manager[i].nports; j++) -+ of_node_put(manager[i].port_node[j]); -+ of_node_put(manager[i].node); -+ } -+} -+ -+static void pd692x0_managers_free_pw_budget(struct pd692x0_priv *priv) -+{ -+ int i; -+ -+ for (i = 0; i < PD692X0_MAX_MANAGERS; i++) { -+ struct regulator *supply; -+ -+ if (!priv->manager_reg[i] || !priv->manager_pw_budget[i]) -+ continue; -+ -+ supply = priv->manager_reg[i]->supply; -+ if (!supply) -+ continue; -+ -+ regulator_free_power_budget(supply, -+ priv->manager_pw_budget[i]); -+ } -+} -+ - static int pd692x0_setup_pi_matrix(struct pse_controller_dev *pcdev) - { - struct pd692x0_manager *manager __free(kfree) = NULL; - struct pd692x0_priv *priv = to_pd692x0_priv(pcdev); - struct pd692x0_matrix port_matrix[PD692X0_MAX_PIS]; -- int ret, i, j, nmanagers; -+ int ret, nmanagers; - - /* Should we flash the port matrix */ - if (priv->fw_state != PD692X0_FW_OK && -@@ -1185,31 +1217,27 @@ static int pd692x0_setup_pi_matrix(struc - nmanagers = ret; - ret = pd692x0_register_managers_regulator(priv, manager, nmanagers); - if (ret) -- goto out; -+ goto err_of_managers; - - ret = pd692x0_configure_managers(priv, nmanagers); - if (ret) -- goto out; -+ goto err_of_managers; - - ret = pd692x0_set_ports_matrix(priv, manager, nmanagers, port_matrix); - if (ret) -- goto out; -+ goto err_managers_req_pw; - - ret = pd692x0_write_ports_matrix(priv, port_matrix); - if (ret) -- goto out; -- --out: -- for (i = 0; i < nmanagers; i++) { -- struct regulator *supply = priv->manager_reg[i]->supply; -+ goto err_managers_req_pw; - -- regulator_free_power_budget(supply, -- priv->manager_pw_budget[i]); -+ pd692x0_of_put_managers(priv, manager, nmanagers); -+ return 0; - -- for (j = 0; j < manager[i].nports; j++) -- of_node_put(manager[i].port_node[j]); -- of_node_put(manager[i].node); -- } -+err_managers_req_pw: -+ pd692x0_managers_free_pw_budget(priv); -+err_of_managers: -+ pd692x0_of_put_managers(priv, manager, nmanagers); - return ret; - } - -@@ -1748,6 +1776,7 @@ static void pd692x0_i2c_remove(struct i2 - { - struct pd692x0_priv *priv = i2c_get_clientdata(client); - -+ pd692x0_managers_free_pw_budget(priv); - firmware_upload_unregister(priv->fwl); - } - diff --git a/target/linux/generic/backport-6.18/626-22-v6.18-net-pse-pd-pd692x0-Skip-power-budget-when-undefined.patch b/target/linux/generic/backport-6.18/626-22-v6.18-net-pse-pd-pd692x0-Skip-power-budget-when-undefined.patch deleted file mode 100644 index 98da7b5080..0000000000 --- a/target/linux/generic/backport-6.18/626-22-v6.18-net-pse-pd-pd692x0-Skip-power-budget-when-undefined.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 7ef353879f714602b43f98662069f4fb86536761 Mon Sep 17 00:00:00 2001 -From: Kory Maincent -Date: Wed, 20 Aug 2025 15:33:21 +0200 -Subject: [PATCH] net: pse-pd: pd692x0: Skip power budget configuration when - undefined - -If the power supply's power budget is not defined in the device tree, -the current code still requests power and configures the PSE manager -with a 0W power limit, which is undesirable behavior. - -Skip power budget configuration entirely when the budget is zero, -avoiding unnecessary power requests and preventing invalid 0W limits -from being set on the PSE manager. - -Fixes: 359754013e6a ("net: pse-pd: pd692x0: Add support for PSE PI priority feature") -Signed-off-by: Kory Maincent -Acked-by: Oleksij Rempel -Link: https://patch.msgid.link/20250820133321.841054-1-kory.maincent@bootlin.com -Signed-off-by: Jakub Kicinski -Signed-off-by: Carlo Szelinsky ---- - drivers/net/pse-pd/pd692x0.c | 4 ++++ - 1 file changed, 4 insertions(+) - ---- a/drivers/net/pse-pd/pd692x0.c -+++ b/drivers/net/pse-pd/pd692x0.c -@@ -1041,6 +1041,10 @@ pd692x0_configure_managers(struct pd692x - int pw_budget; - - pw_budget = regulator_get_unclaimed_power_budget(supply); -+ if (!pw_budget) -+ /* Do nothing if no power budget */ -+ continue; -+ - /* Max power budget per manager */ - if (pw_budget > 6000000) - pw_budget = 6000000; diff --git a/target/linux/generic/backport-6.18/626-23-v6.18-net-pse-pd-Add-Si3474-PSE-controller-driver.patch b/target/linux/generic/backport-6.18/626-23-v6.18-net-pse-pd-Add-Si3474-PSE-controller-driver.patch deleted file mode 100644 index 2f4087facc..0000000000 --- a/target/linux/generic/backport-6.18/626-23-v6.18-net-pse-pd-Add-Si3474-PSE-controller-driver.patch +++ /dev/null @@ -1,636 +0,0 @@ -From a2317231df4b22e6634fe3d8645e7cef848acf49 Mon Sep 17 00:00:00 2001 -From: Piotr Kubik -Date: Tue, 26 Aug 2025 14:41:58 +0000 -Subject: [PATCH] net: pse-pd: Add Si3474 PSE controller driver - -Add a driver for the Skyworks Si3474 I2C Power Sourcing Equipment -controller. - -Driver supports basic features of Si3474 IC: -- get port status, -- get port power, -- get port voltage, -- enable/disable port power. - -Only 4p configurations are supported at this moment. - -Signed-off-by: Piotr Kubik -Reviewed-by: Kory Maincent -Link: https://patch.msgid.link/9b72c8cd-c8d3-4053-9c80-671b9481d166@adtran.com -Signed-off-by: Paolo Abeni -Signed-off-by: Carlo Szelinsky ---- - drivers/net/pse-pd/Kconfig | 11 + - drivers/net/pse-pd/Makefile | 1 + - drivers/net/pse-pd/si3474.c | 578 ++++++++++++++++++++++++++++++++++++ - 3 files changed, 590 insertions(+) - create mode 100644 drivers/net/pse-pd/si3474.c ---- a/drivers/net/pse-pd/Kconfig -+++ b/drivers/net/pse-pd/Kconfig -@@ -32,6 +32,17 @@ config PSE_PD692X0 - To compile this driver as a module, choose M here: the - module will be called pd692x0. - -+config PSE_SI3474 -+ tristate "Si3474 PSE controller" -+ depends on I2C -+ help -+ This module provides support for Si3474 regulator based Ethernet -+ Power Sourcing Equipment. -+ Only 4-pair PSE configurations are supported. -+ -+ To compile this driver as a module, choose M here: the -+ module will be called si3474. -+ - config PSE_TPS23881 - tristate "TPS23881 PSE controller" - depends on I2C ---- a/drivers/net/pse-pd/Makefile -+++ b/drivers/net/pse-pd/Makefile -@@ -5,4 +5,5 @@ obj-$(CONFIG_PSE_CONTROLLER) += pse_core - - obj-$(CONFIG_PSE_REGULATOR) += pse_regulator.o - obj-$(CONFIG_PSE_PD692X0) += pd692x0.o -+obj-$(CONFIG_PSE_SI3474) += si3474.o - obj-$(CONFIG_PSE_TPS23881) += tps23881.o ---- /dev/null -+++ b/drivers/net/pse-pd/si3474.c -@@ -0,0 +1,578 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* -+ * Driver for the Skyworks Si3474 PoE PSE Controller -+ * -+ * Chip Architecture & Terminology: -+ * -+ * The Si3474 is a single-chip PoE PSE controller managing 8 physical power -+ * delivery channels. Internally, it's structured into two logical "Quads". -+ * -+ * Quad 0: Manages physical channels ('ports' in datasheet) 0, 1, 2, 3 -+ * Quad 1: Manages physical channels ('ports' in datasheet) 4, 5, 6, 7 -+ * -+ * Each Quad is accessed via a separate I2C address. The base address range is -+ * set by hardware pins A1-A4, and the specific address selects Quad 0 (usually -+ * the lower/even address) or Quad 1 (usually the higher/odd address). -+ * See datasheet Table 2.2 for the address mapping. -+ * -+ * While the Quads manage channel-specific operations, the Si3474 package has -+ * several resources shared across the entire chip: -+ * - Single RESETb input pin. -+ * - Single INTb output pin (signals interrupts from *either* Quad). -+ * - Single OSS input pin (Emergency Shutdown). -+ * - Global I2C Address (0x7F) used for firmware updates. -+ * - Global status monitoring (Temperature, VDD/VPWR Undervoltage Lockout). -+ * -+ * Driver Architecture: -+ * -+ * To handle the mix of per-Quad access and shared resources correctly, this -+ * driver treats the entire Si3474 package as one logical device. The driver -+ * instance associated with the primary I2C address (Quad 0) takes ownership. -+ * It discovers and manages the I2C client for the secondary address (Quad 1). -+ * This primary instance handles shared resources like IRQ management and -+ * registers a single PSE controller device representing all logical PIs. -+ * Internal functions route I2C commands to the appropriate Quad's i2c_client -+ * based on the target channel or PI. -+ * -+ * Terminology Mapping: -+ * -+ * - "PI" (Power Interface): Refers to the logical PSE port as defined by -+ * IEEE 802.3 (typically corresponds to an RJ45 connector). This is the -+ * `id` (0-7) used in the pse_controller_ops. -+ * - "Channel": Refers to one of the 8 physical power control paths within -+ * the Si3474 chip itself (hardware channels 0-7). This terminology is -+ * used internally within the driver to avoid confusion with 'ports'. -+ * - "Quad": One of the two internal 4-channel management units within the -+ * Si3474, each accessed via its own I2C address. -+ * -+ * Relationship: -+ * - A 2-Pair PoE PI uses 1 Channel. -+ * - A 4-Pair PoE PI uses 2 Channels. -+ * -+ * ASCII Schematic: -+ * -+ * +-----------------------------------------------------+ -+ * | Si3474 Chip | -+ * | | -+ * | +---------------------+ +---------------------+ | -+ * | | Quad 0 | | Quad 1 | | -+ * | | Channels 0, 1, 2, 3 | | Channels 4, 5, 6, 7 | | -+ * | +----------^----------+ +-------^-------------+ | -+ * | I2C Addr 0 | | I2C Addr 1 | -+ * | +------------------------+ | -+ * | (Primary Driver Instance) (Managed by Primary) | -+ * | | -+ * | Shared Resources (affect whole chip): | -+ * | - Single INTb Output -> Handled by Primary | -+ * | - Single RESETb Input | -+ * | - Single OSS Input -> Handled by Primary | -+ * | - Global I2C Addr (0x7F) for Firmware Update | -+ * | - Global Status (Temp, VDD/VPWR UVLO) | -+ * +-----------------------------------------------------+ -+ * | | | | | | | | -+ * Ch0 Ch1 Ch2 Ch3 Ch4 Ch5 Ch6 Ch7 (Physical Channels) -+ * -+ * Example Mapping (Logical PI to Physical Channel(s)): -+ * * 2-Pair Mode (8 PIs): -+ * PI 0 -> Ch 0 -+ * PI 1 -> Ch 1 -+ * ... -+ * PI 7 -> Ch 7 -+ * * 4-Pair Mode (4 PIs): -+ * PI 0 -> Ch 0 + Ch 1 (Managed via Quad 0 Addr) -+ * PI 1 -> Ch 2 + Ch 3 (Managed via Quad 0 Addr) -+ * PI 2 -> Ch 4 + Ch 5 (Managed via Quad 1 Addr) -+ * PI 3 -> Ch 6 + Ch 7 (Managed via Quad 1 Addr) -+ * (Note: Actual mapping depends on Device Tree and PORT_REMAP config) -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#define SI3474_MAX_CHANS 8 -+ -+#define MANUFACTURER_ID 0x08 -+#define IC_ID 0x05 -+#define SI3474_DEVICE_ID (MANUFACTURER_ID << 3 | IC_ID) -+ -+/* Misc registers */ -+#define VENDOR_IC_ID_REG 0x1B -+#define TEMPERATURE_REG 0x2C -+#define FIRMWARE_REVISION_REG 0x41 -+#define CHIP_REVISION_REG 0x43 -+ -+/* Main status registers */ -+#define POWER_STATUS_REG 0x10 -+#define PORT_MODE_REG 0x12 -+#define DETECT_CLASS_ENABLE_REG 0x14 -+ -+/* PORTn Current */ -+#define PORT1_CURRENT_LSB_REG 0x30 -+ -+/* PORTn Current [mA], return in [nA] */ -+/* 1000 * ((PORTn_CURRENT_MSB << 8) + PORTn_CURRENT_LSB) / 16384 */ -+#define SI3474_NA_STEP (1000 * 1000 * 1000 / 16384) -+ -+/* VPWR Voltage */ -+#define VPWR_LSB_REG 0x2E -+#define VPWR_MSB_REG 0x2F -+ -+/* PORTn Voltage */ -+#define PORT1_VOLTAGE_LSB_REG 0x32 -+ -+/* VPWR Voltage [V], return in [uV] */ -+/* 60 * (( VPWR_MSB << 8) + VPWR_LSB) / 16384 */ -+#define SI3474_UV_STEP (1000 * 1000 * 60 / 16384) -+ -+/* Helper macros */ -+#define CHAN_IDX(chan) ((chan) % 4) -+#define CHAN_BIT(chan) BIT(CHAN_IDX(chan)) -+#define CHAN_UPPER_BIT(chan) BIT(CHAN_IDX(chan) + 4) -+ -+#define CHAN_MASK(chan) (0x03U << (2 * CHAN_IDX(chan))) -+#define CHAN_REG(base, chan) ((base) + (CHAN_IDX(chan) * 4)) -+ -+struct si3474_pi_desc { -+ u8 chan[2]; -+ bool is_4p; -+}; -+ -+struct si3474_priv { -+ struct i2c_client *client[2]; -+ struct pse_controller_dev pcdev; -+ struct device_node *np; -+ struct si3474_pi_desc pi[SI3474_MAX_CHANS]; -+}; -+ -+static struct si3474_priv *to_si3474_priv(struct pse_controller_dev *pcdev) -+{ -+ return container_of(pcdev, struct si3474_priv, pcdev); -+} -+ -+static void si3474_get_channels(struct si3474_priv *priv, int id, -+ u8 *chan0, u8 *chan1) -+{ -+ *chan0 = priv->pi[id].chan[0]; -+ *chan1 = priv->pi[id].chan[1]; -+} -+ -+static struct i2c_client *si3474_get_chan_client(struct si3474_priv *priv, -+ u8 chan) -+{ -+ return (chan < 4) ? priv->client[0] : priv->client[1]; -+} -+ -+static int si3474_pi_get_admin_state(struct pse_controller_dev *pcdev, int id, -+ struct pse_admin_state *admin_state) -+{ -+ struct si3474_priv *priv = to_si3474_priv(pcdev); -+ struct i2c_client *client; -+ bool is_enabled; -+ u8 chan0, chan1; -+ s32 ret; -+ -+ si3474_get_channels(priv, id, &chan0, &chan1); -+ client = si3474_get_chan_client(priv, chan0); -+ -+ ret = i2c_smbus_read_byte_data(client, PORT_MODE_REG); -+ if (ret < 0) { -+ admin_state->c33_admin_state = -+ ETHTOOL_C33_PSE_ADMIN_STATE_UNKNOWN; -+ return ret; -+ } -+ -+ is_enabled = ret & (CHAN_MASK(chan0) | CHAN_MASK(chan1)); -+ -+ if (is_enabled) -+ admin_state->c33_admin_state = -+ ETHTOOL_C33_PSE_ADMIN_STATE_ENABLED; -+ else -+ admin_state->c33_admin_state = -+ ETHTOOL_C33_PSE_ADMIN_STATE_DISABLED; -+ -+ return 0; -+} -+ -+static int si3474_pi_get_pw_status(struct pse_controller_dev *pcdev, int id, -+ struct pse_pw_status *pw_status) -+{ -+ struct si3474_priv *priv = to_si3474_priv(pcdev); -+ struct i2c_client *client; -+ bool delivering; -+ u8 chan0, chan1; -+ s32 ret; -+ -+ si3474_get_channels(priv, id, &chan0, &chan1); -+ client = si3474_get_chan_client(priv, chan0); -+ -+ ret = i2c_smbus_read_byte_data(client, POWER_STATUS_REG); -+ if (ret < 0) { -+ pw_status->c33_pw_status = ETHTOOL_C33_PSE_PW_D_STATUS_UNKNOWN; -+ return ret; -+ } -+ -+ delivering = ret & (CHAN_UPPER_BIT(chan0) | CHAN_UPPER_BIT(chan1)); -+ -+ if (delivering) -+ pw_status->c33_pw_status = -+ ETHTOOL_C33_PSE_PW_D_STATUS_DELIVERING; -+ else -+ pw_status->c33_pw_status = ETHTOOL_C33_PSE_PW_D_STATUS_DISABLED; -+ -+ return 0; -+} -+ -+static int si3474_get_of_channels(struct si3474_priv *priv) -+{ -+ struct pse_pi *pi; -+ u32 chan_id; -+ u8 pi_no; -+ s32 ret; -+ -+ for (pi_no = 0; pi_no < SI3474_MAX_CHANS; pi_no++) { -+ pi = &priv->pcdev.pi[pi_no]; -+ bool pairset_found = false; -+ u8 pairset_no; -+ -+ for (pairset_no = 0; pairset_no < 2; pairset_no++) { -+ if (!pi->pairset[pairset_no].np) -+ continue; -+ -+ pairset_found = true; -+ -+ ret = of_property_read_u32(pi->pairset[pairset_no].np, -+ "reg", &chan_id); -+ if (ret) { -+ dev_err(&priv->client[0]->dev, -+ "Failed to read channel reg property\n"); -+ return ret; -+ } -+ if (chan_id > SI3474_MAX_CHANS) { -+ dev_err(&priv->client[0]->dev, -+ "Incorrect channel number: %d\n", chan_id); -+ return -EINVAL; -+ } -+ -+ priv->pi[pi_no].chan[pairset_no] = chan_id; -+ /* Mark as 4-pair if second pairset is present */ -+ priv->pi[pi_no].is_4p = (pairset_no == 1); -+ } -+ -+ if (pairset_found && !priv->pi[pi_no].is_4p) { -+ dev_err(&priv->client[0]->dev, -+ "Second pairset is missing for PI %pOF, only 4p configs are supported\n", -+ pi->np); -+ return -EINVAL; -+ } -+ } -+ -+ return 0; -+} -+ -+static int si3474_setup_pi_matrix(struct pse_controller_dev *pcdev) -+{ -+ struct si3474_priv *priv = to_si3474_priv(pcdev); -+ s32 ret; -+ -+ ret = si3474_get_of_channels(priv); -+ if (ret < 0) -+ dev_warn(&priv->client[0]->dev, -+ "Unable to parse DT PSE power interface matrix\n"); -+ -+ return ret; -+} -+ -+static int si3474_pi_enable(struct pse_controller_dev *pcdev, int id) -+{ -+ struct si3474_priv *priv = to_si3474_priv(pcdev); -+ struct i2c_client *client; -+ u8 chan0, chan1; -+ s32 ret; -+ u8 val; -+ -+ si3474_get_channels(priv, id, &chan0, &chan1); -+ client = si3474_get_chan_client(priv, chan0); -+ -+ /* Release PI from shutdown */ -+ ret = i2c_smbus_read_byte_data(client, PORT_MODE_REG); -+ if (ret < 0) -+ return ret; -+ -+ val = (u8)ret; -+ val |= CHAN_MASK(chan0); -+ val |= CHAN_MASK(chan1); -+ -+ ret = i2c_smbus_write_byte_data(client, PORT_MODE_REG, val); -+ if (ret) -+ return ret; -+ -+ /* DETECT_CLASS_ENABLE must be set when using AUTO mode, -+ * otherwise PI does not power up - datasheet section 2.10.2 -+ */ -+ val = CHAN_BIT(chan0) | CHAN_UPPER_BIT(chan0) | -+ CHAN_BIT(chan1) | CHAN_UPPER_BIT(chan1); -+ -+ ret = i2c_smbus_write_byte_data(client, DETECT_CLASS_ENABLE_REG, val); -+ if (ret) -+ return ret; -+ -+ return 0; -+} -+ -+static int si3474_pi_disable(struct pse_controller_dev *pcdev, int id) -+{ -+ struct si3474_priv *priv = to_si3474_priv(pcdev); -+ struct i2c_client *client; -+ u8 chan0, chan1; -+ s32 ret; -+ u8 val; -+ -+ si3474_get_channels(priv, id, &chan0, &chan1); -+ client = si3474_get_chan_client(priv, chan0); -+ -+ /* Set PI in shutdown mode */ -+ ret = i2c_smbus_read_byte_data(client, PORT_MODE_REG); -+ if (ret < 0) -+ return ret; -+ -+ val = (u8)ret; -+ val &= ~CHAN_MASK(chan0); -+ val &= ~CHAN_MASK(chan1); -+ -+ ret = i2c_smbus_write_byte_data(client, PORT_MODE_REG, val); -+ if (ret) -+ return ret; -+ -+ return 0; -+} -+ -+static int si3474_pi_get_chan_current(struct si3474_priv *priv, u8 chan) -+{ -+ struct i2c_client *client; -+ u64 tmp_64; -+ s32 ret; -+ u8 reg; -+ -+ client = si3474_get_chan_client(priv, chan); -+ -+ /* Registers 0x30 to 0x3d */ -+ reg = CHAN_REG(PORT1_CURRENT_LSB_REG, chan); -+ -+ ret = i2c_smbus_read_word_data(client, reg); -+ if (ret < 0) -+ return ret; -+ -+ tmp_64 = ret * SI3474_NA_STEP; -+ -+ /* uA = nA / 1000 */ -+ tmp_64 = DIV_ROUND_CLOSEST_ULL(tmp_64, 1000); -+ return (int)tmp_64; -+} -+ -+static int si3474_pi_get_chan_voltage(struct si3474_priv *priv, u8 chan) -+{ -+ struct i2c_client *client; -+ s32 ret; -+ u32 val; -+ u8 reg; -+ -+ client = si3474_get_chan_client(priv, chan); -+ -+ /* Registers 0x32 to 0x3f */ -+ reg = CHAN_REG(PORT1_VOLTAGE_LSB_REG, chan); -+ -+ ret = i2c_smbus_read_word_data(client, reg); -+ if (ret < 0) -+ return ret; -+ -+ val = ret * SI3474_UV_STEP; -+ -+ return (int)val; -+} -+ -+static int si3474_pi_get_voltage(struct pse_controller_dev *pcdev, int id) -+{ -+ struct si3474_priv *priv = to_si3474_priv(pcdev); -+ struct i2c_client *client; -+ u8 chan0, chan1; -+ s32 ret; -+ -+ si3474_get_channels(priv, id, &chan0, &chan1); -+ client = si3474_get_chan_client(priv, chan0); -+ -+ /* Check which channels are enabled*/ -+ ret = i2c_smbus_read_byte_data(client, POWER_STATUS_REG); -+ if (ret < 0) -+ return ret; -+ -+ /* Take voltage from the first enabled channel */ -+ if (ret & CHAN_BIT(chan0)) -+ ret = si3474_pi_get_chan_voltage(priv, chan0); -+ else if (ret & CHAN_BIT(chan1)) -+ ret = si3474_pi_get_chan_voltage(priv, chan1); -+ else -+ /* 'should' be no voltage in this case */ -+ return 0; -+ -+ return ret; -+} -+ -+static int si3474_pi_get_actual_pw(struct pse_controller_dev *pcdev, int id) -+{ -+ struct si3474_priv *priv = to_si3474_priv(pcdev); -+ u8 chan0, chan1; -+ u32 uV, uA; -+ u64 tmp_64; -+ s32 ret; -+ -+ ret = si3474_pi_get_voltage(&priv->pcdev, id); -+ -+ /* Do not read currents if voltage is 0 */ -+ if (ret <= 0) -+ return ret; -+ uV = ret; -+ -+ si3474_get_channels(priv, id, &chan0, &chan1); -+ -+ ret = si3474_pi_get_chan_current(priv, chan0); -+ if (ret < 0) -+ return ret; -+ uA = ret; -+ -+ ret = si3474_pi_get_chan_current(priv, chan1); -+ if (ret < 0) -+ return ret; -+ uA += ret; -+ -+ tmp_64 = uV; -+ tmp_64 *= uA; -+ /* mW = uV * uA / 1000000000 */ -+ return DIV_ROUND_CLOSEST_ULL(tmp_64, 1000000000); -+} -+ -+static const struct pse_controller_ops si3474_ops = { -+ .setup_pi_matrix = si3474_setup_pi_matrix, -+ .pi_enable = si3474_pi_enable, -+ .pi_disable = si3474_pi_disable, -+ .pi_get_actual_pw = si3474_pi_get_actual_pw, -+ .pi_get_voltage = si3474_pi_get_voltage, -+ .pi_get_admin_state = si3474_pi_get_admin_state, -+ .pi_get_pw_status = si3474_pi_get_pw_status, -+}; -+ -+static void si3474_ancillary_i2c_remove(void *data) -+{ -+ struct i2c_client *client = data; -+ -+ i2c_unregister_device(client); -+} -+ -+static int si3474_i2c_probe(struct i2c_client *client) -+{ -+ struct device *dev = &client->dev; -+ struct si3474_priv *priv; -+ u8 fw_version; -+ s32 ret; -+ -+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { -+ dev_err(dev, "i2c check functionality failed\n"); -+ return -ENXIO; -+ } -+ -+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); -+ if (!priv) -+ return -ENOMEM; -+ -+ ret = i2c_smbus_read_byte_data(client, VENDOR_IC_ID_REG); -+ if (ret < 0) -+ return ret; -+ -+ if (ret != SI3474_DEVICE_ID) { -+ dev_err(dev, "Wrong device ID: 0x%x\n", ret); -+ return -ENXIO; -+ } -+ -+ ret = i2c_smbus_read_byte_data(client, FIRMWARE_REVISION_REG); -+ if (ret < 0) -+ return ret; -+ fw_version = ret; -+ -+ ret = i2c_smbus_read_byte_data(client, CHIP_REVISION_REG); -+ if (ret < 0) -+ return ret; -+ -+ dev_dbg(dev, "Chip revision: 0x%x, firmware version: 0x%x\n", -+ ret, fw_version); -+ -+ priv->client[0] = client; -+ i2c_set_clientdata(client, priv); -+ -+ priv->client[1] = i2c_new_ancillary_device(priv->client[0], "secondary", -+ priv->client[0]->addr + 1); -+ if (IS_ERR(priv->client[1])) -+ return PTR_ERR(priv->client[1]); -+ -+ ret = devm_add_action_or_reset(dev, si3474_ancillary_i2c_remove, priv->client[1]); -+ if (ret < 0) { -+ dev_err(&priv->client[1]->dev, "Cannot register remove callback\n"); -+ return ret; -+ } -+ -+ ret = i2c_smbus_read_byte_data(priv->client[1], VENDOR_IC_ID_REG); -+ if (ret < 0) { -+ dev_err(&priv->client[1]->dev, "Cannot access secondary PSE controller\n"); -+ return ret; -+ } -+ -+ if (ret != SI3474_DEVICE_ID) { -+ dev_err(&priv->client[1]->dev, -+ "Wrong device ID for secondary PSE controller: 0x%x\n", ret); -+ return -ENXIO; -+ } -+ -+ priv->np = dev->of_node; -+ priv->pcdev.owner = THIS_MODULE; -+ priv->pcdev.ops = &si3474_ops; -+ priv->pcdev.dev = dev; -+ priv->pcdev.types = ETHTOOL_PSE_C33; -+ priv->pcdev.nr_lines = SI3474_MAX_CHANS; -+ -+ ret = devm_pse_controller_register(dev, &priv->pcdev); -+ if (ret) { -+ dev_err(dev, "Failed to register PSE controller: 0x%x\n", ret); -+ return ret; -+ } -+ -+ return 0; -+} -+ -+static const struct i2c_device_id si3474_id[] = { -+ { "si3474" }, -+ {} -+}; -+MODULE_DEVICE_TABLE(i2c, si3474_id); -+ -+static const struct of_device_id si3474_of_match[] = { -+ { -+ .compatible = "skyworks,si3474", -+ }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, si3474_of_match); -+ -+static struct i2c_driver si3474_driver = { -+ .probe = si3474_i2c_probe, -+ .id_table = si3474_id, -+ .driver = { -+ .name = "si3474", -+ .of_match_table = si3474_of_match, -+ }, -+}; -+module_i2c_driver(si3474_driver); -+ -+MODULE_AUTHOR("Piotr Kubik "); -+MODULE_DESCRIPTION("Skyworks Si3474 PoE PSE Controller driver"); -+MODULE_LICENSE("GPL"); diff --git a/target/linux/generic/backport-6.18/626-24-v6.19-net-pse-pd-tps23881-Fix-current-measurement-scaling.patch b/target/linux/generic/backport-6.18/626-24-v6.19-net-pse-pd-tps23881-Fix-current-measurement-scaling.patch deleted file mode 100644 index 5150da365f..0000000000 --- a/target/linux/generic/backport-6.18/626-24-v6.19-net-pse-pd-tps23881-Fix-current-measurement-scaling.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 2c95a756e0cfc19af6d0b32b0c6cf3bada334998 Mon Sep 17 00:00:00 2001 -From: Thomas Wismer -Date: Mon, 6 Oct 2025 22:40:29 +0200 -Subject: [PATCH] net: pse-pd: tps23881: Fix current measurement scaling - -The TPS23881 improves on the TPS23880 with current sense resistors reduced -from 255 mOhm to 200 mOhm. This has a direct impact on the scaling of the -current measurement. However, the latest TPS23881 data sheet from May 2023 -still shows the scaling of the TPS23880 model. - -Fixes: 7f076ce3f1733 ("net: pse-pd: tps23881: Add support for power limit and measurement features") -Signed-off-by: Thomas Wismer -Acked-by: Kory Maincent -Link: https://patch.msgid.link/20251006204029.7169-2-thomas@wismer.xyz -Signed-off-by: Jakub Kicinski -Signed-off-by: Carlo Szelinsky ---- - drivers/net/pse-pd/tps23881.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/net/pse-pd/tps23881.c -+++ b/drivers/net/pse-pd/tps23881.c -@@ -62,7 +62,7 @@ - #define TPS23881_REG_SRAM_DATA 0x61 - - #define TPS23881_UV_STEP 3662 --#define TPS23881_NA_STEP 70190 -+#define TPS23881_NA_STEP 89500 - #define TPS23881_MW_STEP 500 - #define TPS23881_MIN_PI_PW_LIMIT_MW 2000 - diff --git a/target/linux/generic/backport-6.18/626-v6.16-net-bridge-locally-receive-all-multicast-packets-if-.patch b/target/linux/generic/backport-6.18/626-v6.16-net-bridge-locally-receive-all-multicast-packets-if-.patch deleted file mode 100644 index d9bd8c73a0..0000000000 --- a/target/linux/generic/backport-6.18/626-v6.16-net-bridge-locally-receive-all-multicast-packets-if-.patch +++ /dev/null @@ -1,41 +0,0 @@ -From a496d2f0fd612ab9e10700afe00dc9267bad788b Mon Sep 17 00:00:00 2001 -From: Shengyu Qu -Date: Mon, 14 Apr 2025 18:56:01 +0800 -Subject: net: bridge: locally receive all multicast packets if IFF_ALLMULTI is - set - -If multicast snooping is enabled, multicast packets may not always end up -on the local bridge interface, if the host is not a member of the multicast -group. Similar to how IFF_PROMISC allows all packets to be received -locally, let IFF_ALLMULTI allow all multicast packets to be received. - -OpenWrt uses a user space daemon for DHCPv6/RA/NDP handling, and in relay -mode it sets the ALLMULTI flag in order to receive all relevant queries on -the network. - -This works for normal network interfaces and non-snooping bridges, but not -snooping bridges (unless multicast routing is enabled). - -Reported-by: Felix Fietkau -Closes: https://github.com/openwrt/openwrt/issues/15857#issuecomment-2662851243 -Signed-off-by: Shengyu Qu -Reviewed-by: Ido Schimmel -Acked-by: Nikolay Aleksandrov -Link: https://patch.msgid.link/OSZPR01MB8434308370ACAFA90A22980798B32@OSZPR01MB8434.jpnprd01.prod.outlook.com -Signed-off-by: Jakub Kicinski ---- - net/bridge/br_input.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - ---- a/net/bridge/br_input.c -+++ b/net/bridge/br_input.c -@@ -184,7 +184,8 @@ int br_handle_frame_finish(struct net *n - if ((mdst || BR_INPUT_SKB_CB_MROUTERS_ONLY(skb)) && - br_multicast_querier_exists(brmctx, eth_hdr(skb), mdst)) { - if ((mdst && mdst->host_joined) || -- br_multicast_is_router(brmctx, skb)) { -+ br_multicast_is_router(brmctx, skb) || -+ br->dev->flags & IFF_ALLMULTI) { - local_rcv = true; - DEV_STATS_INC(br->dev, multicast); - } diff --git a/target/linux/generic/backport-6.18/627-01-v6.17-net-pse-pd-Add-ethtool_netlink_generated-header.patch b/target/linux/generic/backport-6.18/627-01-v6.17-net-pse-pd-Add-ethtool_netlink_generated-header.patch deleted file mode 100644 index f773fb6e4f..0000000000 --- a/target/linux/generic/backport-6.18/627-01-v6.17-net-pse-pd-Add-ethtool_netlink_generated-header.patch +++ /dev/null @@ -1,79 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: OpenWrt PSE-PD Backport -Date: Fri, 31 Jan 2025 00:00:00 +0000 -Subject: [PATCH] net: pse-pd: Add ethtool netlink definitions for PSE events - and priority - -GENERATED PATCH - OpenWrt PSE-PD Backport - -This patch: -1. Adds ETHTOOL_A_PSE_PW_D_ID, ETHTOOL_A_PSE_PRIO_MAX, ETHTOOL_A_PSE_PRIO to - the ETHTOOL_A_PSE_* enum in ethtool_netlink.h (backported from kernel 6.17+) -2. Creates include/uapi/linux/ethtool_netlink_generated.h with PSE event - definitions (in mainline 6.17+, this file is auto-generated) -3. Adds ETHTOOL_MSG_PSE_NTF to the kernel message types enum - -These definitions are required by PSE event reporting and priority patches. - -Signed-off-by: OpenWrt PSE-PD Backport -Signed-off-by: Carlo Szelinsky ---- - include/uapi/linux/ethtool_netlink.h | 4 ++ - include/uapi/linux/ethtool_netlink_generated.h | 31 ++++++++++++++++++++++++++ - 2 files changed, 35 insertions(+) - create mode 100644 include/uapi/linux/ethtool_netlink_generated.h - ---- a/include/uapi/linux/ethtool_netlink.h -+++ b/include/uapi/linux/ethtool_netlink.h -@@ -115,6 +115,7 @@ enum { - ETHTOOL_MSG_PHY_GET_REPLY, - ETHTOOL_MSG_PHY_NTF, - -+ ETHTOOL_MSG_PSE_NTF, - /* add new constants above here */ - __ETHTOOL_MSG_KERNEL_CNT, - ETHTOOL_MSG_KERNEL_MAX = __ETHTOOL_MSG_KERNEL_CNT - 1 -@@ -970,6 +971,9 @@ enum { - ETHTOOL_A_C33_PSE_EXT_SUBSTATE, /* u32 */ - ETHTOOL_A_C33_PSE_AVAIL_PW_LIMIT, /* u32 */ - ETHTOOL_A_C33_PSE_PW_LIMIT_RANGES, /* nest - _C33_PSE_PW_LIMIT_* */ -+ ETHTOOL_A_PSE_PW_D_ID, /* u32 */ -+ ETHTOOL_A_PSE_PRIO_MAX, /* u32 */ -+ ETHTOOL_A_PSE_PRIO, /* u32 */ - - /* add new constants above here */ - __ETHTOOL_A_PSE_CNT, ---- /dev/null -+++ b/include/uapi/linux/ethtool_netlink_generated.h -@@ -0,0 +1,31 @@ -+/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */ -+/* PSE ethtool netlink definitions - OpenWrt backport for 6.12 */ -+ -+#ifndef _UAPI_LINUX_ETHTOOL_NETLINK_GENERATED_H -+#define _UAPI_LINUX_ETHTOOL_NETLINK_GENERATED_H -+ -+enum ethtool_pse_event { -+ ETHTOOL_PSE_EVENT_OVER_CURRENT = 1, -+ ETHTOOL_PSE_EVENT_OVER_TEMP = 2, -+ ETHTOOL_C33_PSE_EVENT_DETECTION = 4, -+ ETHTOOL_C33_PSE_EVENT_CLASSIFICATION = 8, -+ ETHTOOL_C33_PSE_EVENT_DISCONNECTION = 16, -+ ETHTOOL_PSE_EVENT_OVER_BUDGET = 32, -+ ETHTOOL_PSE_EVENT_SW_PW_CONTROL_ERROR = 64, -+}; -+ -+enum { -+ ETHTOOL_A_PSE_NTF_HEADER = 1, -+ ETHTOOL_A_PSE_NTF_EVENTS, -+ __ETHTOOL_A_PSE_NTF_CNT, -+ ETHTOOL_A_PSE_NTF_MAX = (__ETHTOOL_A_PSE_NTF_CNT - 1) -+}; -+ -+enum { -+ ETHTOOL_A_PSE_NTF_EVT_UNSPEC, -+ ETHTOOL_A_PSE_NTF_EVT_INDEX, -+ __ETHTOOL_A_PSE_NTF_EVT_CNT, -+ ETHTOOL_A_PSE_NTF_EVT_MAX = (__ETHTOOL_A_PSE_NTF_EVT_CNT - 1) -+}; -+ -+#endif /* _UAPI_LINUX_ETHTOOL_NETLINK_GENERATED_H */ diff --git a/target/linux/generic/backport-6.18/627-02-v6.17-net-ethtool-Add-PSE-port-priority-support.patch b/target/linux/generic/backport-6.18/627-02-v6.17-net-ethtool-Add-PSE-port-priority-support.patch deleted file mode 100644 index 06d9b11b90..0000000000 --- a/target/linux/generic/backport-6.18/627-02-v6.17-net-ethtool-Add-PSE-port-priority-support.patch +++ /dev/null @@ -1,68 +0,0 @@ -# ADAPTED FOR OPENWRT 6.12 - Documentation changes removed -# Original commit: eeb0c8f72f49 -From eeb0c8f72f49a21984981188404cfd3700edbaff Mon Sep 17 00:00:00 2001 -From: "Kory Maincent (Dent Project)" -Date: Tue, 17 Jun 2025 14:12:07 +0200 -Subject: [PATCH] net: ethtool: Add PSE port priority support feature - -This patch expands the status information provided by ethtool for PSE c33 -with current port priority and max port priority. It also adds a call to -pse_ethtool_set_prio() to configure the PSE port priority. - -Signed-off-by: Kory Maincent (Dent Project) -Reviewed-by: Oleksij Rempel -Link: https://patch.msgid.link/20250617-feature_poe_port_prio-v14-8-78a1a645e2ee@bootlin.com -Signed-off-by: Jakub Kicinski -Signed-off-by: Carlo Szelinsky ---- - net/ethtool/pse-pd.c | 18 ++++++++++++++++++ - 1 file changed, 18 insertions(+) - ---- a/net/ethtool/pse-pd.c -+++ b/net/ethtool/pse-pd.c -@@ -111,6 +111,9 @@ static int pse_reply_size(const struct e - len += st->c33_pw_limit_nb_ranges * - (nla_total_size(0) + - nla_total_size(sizeof(u32)) * 2); -+ if (st->prio_max) -+ /* _PSE_PRIO_MAX + _PSE_PRIO */ -+ len += nla_total_size(sizeof(u32)) * 2; - - return len; - } -@@ -205,6 +208,11 @@ static int pse_fill_reply(struct sk_buff - pse_put_pw_limit_ranges(skb, st)) - return -EMSGSIZE; - -+ if (st->prio_max && -+ (nla_put_u32(skb, ETHTOOL_A_PSE_PRIO_MAX, st->prio_max) || -+ nla_put_u32(skb, ETHTOOL_A_PSE_PRIO, st->prio))) -+ return -EMSGSIZE; -+ - return 0; - } - -@@ -226,6 +234,7 @@ const struct nla_policy ethnl_pse_set_po - NLA_POLICY_RANGE(NLA_U32, ETHTOOL_C33_PSE_ADMIN_STATE_DISABLED, - ETHTOOL_C33_PSE_ADMIN_STATE_ENABLED), - [ETHTOOL_A_C33_PSE_AVAIL_PW_LIMIT] = { .type = NLA_U32 }, -+ [ETHTOOL_A_PSE_PRIO] = { .type = NLA_U32 }, - }; - - static int -@@ -283,6 +292,15 @@ ethnl_set_pse(struct ethnl_req_info *req - if (ret) - return ret; - } -+ -+ if (tb[ETHTOOL_A_PSE_PRIO]) { -+ unsigned int prio; -+ -+ prio = nla_get_u32(tb[ETHTOOL_A_PSE_PRIO]); -+ ret = pse_ethtool_set_prio(phydev->psec, info->extack, prio); -+ if (ret) -+ return ret; -+ } - - /* These values are already validated by the ethnl_pse_set_policy */ - if (tb[ETHTOOL_A_PODL_PSE_ADMIN_CONTROL] || diff --git a/target/linux/generic/backport-6.18/630-v6.13-net-usb-qmi_wwan-add-Quectel-RG255C.patch b/target/linux/generic/backport-6.18/630-v6.13-net-usb-qmi_wwan-add-Quectel-RG255C.patch deleted file mode 100644 index a1eb835a55..0000000000 --- a/target/linux/generic/backport-6.18/630-v6.13-net-usb-qmi_wwan-add-Quectel-RG255C.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 5c964c8a97c12145104f5d2782aa1ffccf3a93dd Mon Sep 17 00:00:00 2001 -From: Martin Hou -Date: Mon, 16 Dec 2024 11:06:18 +0800 -Subject: [PATCH] net: usb: qmi_wwan: add Quectel RG255C - -Add support for Quectel RG255C which is based on Qualcomm SDX35 chip. -The composition is DM / NMEA / AT / QMI. - -T: Bus=01 Lev=01 Prnt=01 Port=04 Cnt=01 Dev#= 2 Spd=480 MxCh= 0 -D: Ver= 2.01 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1 -P: Vendor=2c7c ProdID=0316 Rev= 5.15 -S: Manufacturer=Quectel -S: Product=RG255C-CN -S: SerialNumber=c68192c1 -C:* #Ifs= 4 Cfg#= 1 Atr=a0 MxPwr=500mA -I:* If#= 0 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=30 Driver=option -E: Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms -E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms -I:* If#= 1 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=00 Prot=00 Driver=option -E: Ad=82(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms -E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms -I:* If#= 2 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=40 Driver=option -E: Ad=84(I) Atr=03(Int.) MxPS= 10 Ivl=32ms -E: Ad=83(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms -E: Ad=03(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms -I:* If#= 3 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=50 Driver=qmi_wwan -E: Ad=86(I) Atr=03(Int.) MxPS= 8 Ivl=32ms -E: Ad=85(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms -E: Ad=04(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms - -Signed-off-by: Martin Hou -Link: https://patch.msgid.link/tencent_17DDD787B48E8A5AB8379ED69E23A0CD9309@qq.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/usb/qmi_wwan.c | 1 + - 1 file changed, 1 insertion(+) - ---- a/drivers/net/usb/qmi_wwan.c -+++ b/drivers/net/usb/qmi_wwan.c -@@ -1442,6 +1442,7 @@ static const struct usb_device_id produc - {QMI_QUIRK_SET_DTR(0x2c7c, 0x0195, 4)}, /* Quectel EG95 */ - {QMI_FIXED_INTF(0x2c7c, 0x0296, 4)}, /* Quectel BG96 */ - {QMI_QUIRK_SET_DTR(0x2c7c, 0x030e, 4)}, /* Quectel EM05GV2 */ -+ {QMI_QUIRK_SET_DTR(0x2c7c, 0x0316, 3)}, /* Quectel RG255C */ - {QMI_QUIRK_SET_DTR(0x2cb7, 0x0104, 4)}, /* Fibocom NL678 series */ - {QMI_QUIRK_SET_DTR(0x2cb7, 0x0112, 0)}, /* Fibocom FG132 */ - {QMI_FIXED_INTF(0x0489, 0xe0b4, 0)}, /* Foxconn T77W968 LTE */ diff --git a/target/linux/generic/backport-6.18/630-v6.14-PM-sleep-wakeirq-Introduce-device-managed-variant-of.patch b/target/linux/generic/backport-6.18/630-v6.14-PM-sleep-wakeirq-Introduce-device-managed-variant-of.patch deleted file mode 100644 index 06edffade3..0000000000 --- a/target/linux/generic/backport-6.18/630-v6.14-PM-sleep-wakeirq-Introduce-device-managed-variant-of.patch +++ /dev/null @@ -1,74 +0,0 @@ -From fd8318a32573d73eb20637a0c80689de0dc98169 Mon Sep 17 00:00:00 2001 -From: Peng Fan -Date: Fri, 3 Jan 2025 16:41:13 +0800 -Subject: [PATCH] PM: sleep: wakeirq: Introduce device-managed variant of - dev_pm_set_wake_irq() - -Add device-managed variant of dev_pm_set_wake_irq which automatically -clear the wake irq on device destruction to simplify error handling -and resource management in drivers. - -Signed-off-by: Peng Fan -Link: https://patch.msgid.link/20250103-wake_irq-v2-1-e3aeff5e9966@nxp.com -Signed-off-by: Rafael J. Wysocki ---- - drivers/base/power/wakeirq.c | 26 ++++++++++++++++++++++++++ - include/linux/pm_wakeirq.h | 6 ++++++ - 2 files changed, 32 insertions(+) - ---- a/drivers/base/power/wakeirq.c -+++ b/drivers/base/power/wakeirq.c -@@ -106,6 +106,32 @@ void dev_pm_clear_wake_irq(struct device - } - EXPORT_SYMBOL_GPL(dev_pm_clear_wake_irq); - -+static void devm_pm_clear_wake_irq(void *dev) -+{ -+ dev_pm_clear_wake_irq(dev); -+} -+ -+/** -+ * devm_pm_set_wake_irq - device-managed variant of dev_pm_set_wake_irq -+ * @dev: Device entry -+ * @irq: Device IO interrupt -+ * -+ * -+ * Attach a device IO interrupt as a wake IRQ, same with dev_pm_set_wake_irq, -+ * but the device will be auto clear wake capability on driver detach. -+ */ -+int devm_pm_set_wake_irq(struct device *dev, int irq) -+{ -+ int ret; -+ -+ ret = dev_pm_set_wake_irq(dev, irq); -+ if (ret) -+ return ret; -+ -+ return devm_add_action_or_reset(dev, devm_pm_clear_wake_irq, dev); -+} -+EXPORT_SYMBOL_GPL(devm_pm_set_wake_irq); -+ - /** - * handle_threaded_wake_irq - Handler for dedicated wake-up interrupts - * @irq: Device specific dedicated wake-up interrupt ---- a/include/linux/pm_wakeirq.h -+++ b/include/linux/pm_wakeirq.h -@@ -10,6 +10,7 @@ extern int dev_pm_set_wake_irq(struct de - extern int dev_pm_set_dedicated_wake_irq(struct device *dev, int irq); - extern int dev_pm_set_dedicated_wake_irq_reverse(struct device *dev, int irq); - extern void dev_pm_clear_wake_irq(struct device *dev); -+extern int devm_pm_set_wake_irq(struct device *dev, int irq); - - #else /* !CONFIG_PM */ - -@@ -32,5 +33,10 @@ static inline void dev_pm_clear_wake_irq - { - } - -+static inline int devm_pm_set_wake_irq(struct device *dev, int irq) -+{ -+ return 0; -+} -+ - #endif /* CONFIG_PM */ - #endif /* _LINUX_PM_WAKEIRQ_H */ diff --git a/target/linux/generic/backport-6.18/710-v6.16-igc-enable-HW-vlan-tag-insertion-stripping-by-defaul.patch b/target/linux/generic/backport-6.18/710-v6.16-igc-enable-HW-vlan-tag-insertion-stripping-by-defaul.patch deleted file mode 100644 index 48d03f15e7..0000000000 --- a/target/linux/generic/backport-6.18/710-v6.16-igc-enable-HW-vlan-tag-insertion-stripping-by-defaul.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 8cae5a0d91fea01d90ce7c1827e26934a22ca2fa Mon Sep 17 00:00:00 2001 -From: Rui Salvaterra -Date: Wed, 5 Mar 2025 11:53:56 +0000 -Subject: [PATCH] igc: enable HW vlan tag insertion/stripping by default - -This is enabled by default in other Intel drivers I've checked (e1000, e1000e, -iavf, igb and ice). Fixes an out-of-the-box performance issue when running -OpenWrt on typical mini-PCs with igc-supported Ethernet controllers and 802.1Q -VLAN configurations, as ethtool isn't part of the default packages and sane -defaults are expected. - -In my specific case, with an Intel N100-based machine with four I226-V Ethernet -controllers, my upload performance increased from under 30 Mb/s to the expected -~1 Gb/s. - -Signed-off-by: Rui Salvaterra ---- - drivers/net/ethernet/intel/igc/igc_main.c | 3 +++ - 1 file changed, 3 insertions(+) - ---- a/drivers/net/ethernet/intel/igc/igc_main.c -+++ b/drivers/net/ethernet/intel/igc/igc_main.c -@@ -7070,6 +7070,9 @@ static int igc_probe(struct pci_dev *pde - netdev->xdp_features = NETDEV_XDP_ACT_BASIC | NETDEV_XDP_ACT_REDIRECT | - NETDEV_XDP_ACT_XSK_ZEROCOPY; - -+ /* enable HW vlan tag insertion/stripping by default */ -+ netdev->features |= NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX; -+ - /* MTU range: 68 - 9216 */ - netdev->min_mtu = ETH_MIN_MTU; - netdev->max_mtu = MAX_STD_JUMBO_FRAME_SIZE; diff --git a/target/linux/generic/backport-6.18/720-01-v6.13-net-phy-mediatek-ge-soc-Fix-coding-style.patch b/target/linux/generic/backport-6.18/720-01-v6.13-net-phy-mediatek-ge-soc-Fix-coding-style.patch deleted file mode 100644 index 25bd96fa1f..0000000000 --- a/target/linux/generic/backport-6.18/720-01-v6.13-net-phy-mediatek-ge-soc-Fix-coding-style.patch +++ /dev/null @@ -1,88 +0,0 @@ -From 277f96c1f3f71d6e1d3bcf650d7cd84c1442210f Mon Sep 17 00:00:00 2001 -From: "SkyLake.Huang" -Date: Thu, 17 Oct 2024 11:22:11 +0800 -Subject: [PATCH 01/20] net: phy: mediatek-ge-soc: Fix coding style - -This patch fixes spelling errors, re-arrange vars with -reverse Xmas tree and remove unnecessary parens in -mediatek-ge-soc.c. - -Signed-off-by: SkyLake.Huang -Reviewed-by: Simon Horman -Signed-off-by: Andrew Lunn ---- - drivers/net/phy/mediatek-ge-soc.c | 36 ++++++++++++++++--------------- - 1 file changed, 19 insertions(+), 17 deletions(-) - ---- a/drivers/net/phy/mediatek-ge-soc.c -+++ b/drivers/net/phy/mediatek-ge-soc.c -@@ -408,16 +408,17 @@ static int tx_offset_cal_efuse(struct ph - - static int tx_amp_fill_result(struct phy_device *phydev, u16 *buf) - { -- int i; -- int bias[16] = {}; -- const int vals_9461[16] = { 7, 1, 4, 7, -- 7, 1, 4, 7, -- 7, 1, 4, 7, -- 7, 1, 4, 7 }; - const int vals_9481[16] = { 10, 6, 6, 10, - 10, 6, 6, 10, - 10, 6, 6, 10, - 10, 6, 6, 10 }; -+ const int vals_9461[16] = { 7, 1, 4, 7, -+ 7, 1, 4, 7, -+ 7, 1, 4, 7, -+ 7, 1, 4, 7 }; -+ int bias[16] = {}; -+ int i; -+ - switch (phydev->drv->phy_id) { - case MTK_GPHY_ID_MT7981: - /* We add some calibration to efuse values -@@ -1069,10 +1070,10 @@ static int start_cal(struct phy_device * - - static int mt798x_phy_calibration(struct phy_device *phydev) - { -+ struct nvmem_cell *cell; - int ret = 0; -- u32 *buf; - size_t len; -- struct nvmem_cell *cell; -+ u32 *buf; - - cell = nvmem_cell_get(&phydev->mdio.dev, "phy-cal-data"); - if (IS_ERR(cell)) { -@@ -1210,14 +1211,15 @@ static int mt798x_phy_led_brightness_set - return mt798x_phy_hw_led_on_set(phydev, index, (value != LED_OFF)); - } - --static const unsigned long supported_triggers = (BIT(TRIGGER_NETDEV_FULL_DUPLEX) | -- BIT(TRIGGER_NETDEV_HALF_DUPLEX) | -- BIT(TRIGGER_NETDEV_LINK) | -- BIT(TRIGGER_NETDEV_LINK_10) | -- BIT(TRIGGER_NETDEV_LINK_100) | -- BIT(TRIGGER_NETDEV_LINK_1000) | -- BIT(TRIGGER_NETDEV_RX) | -- BIT(TRIGGER_NETDEV_TX)); -+static const unsigned long supported_triggers = -+ BIT(TRIGGER_NETDEV_FULL_DUPLEX) | -+ BIT(TRIGGER_NETDEV_HALF_DUPLEX) | -+ BIT(TRIGGER_NETDEV_LINK) | -+ BIT(TRIGGER_NETDEV_LINK_10) | -+ BIT(TRIGGER_NETDEV_LINK_100) | -+ BIT(TRIGGER_NETDEV_LINK_1000) | -+ BIT(TRIGGER_NETDEV_RX) | -+ BIT(TRIGGER_NETDEV_TX); - - static int mt798x_phy_led_hw_is_supported(struct phy_device *phydev, u8 index, - unsigned long rules) -@@ -1415,7 +1417,7 @@ static int mt7988_phy_probe_shared(struc - * LED_C and LED_D respectively. At the same time those pins are used to - * bootstrap configuration of the reference clock source (LED_A), - * DRAM DDRx16b x2/x1 (LED_B) and boot device (LED_C, LED_D). -- * In practise this is done using a LED and a resistor pulling the pin -+ * In practice this is done using a LED and a resistor pulling the pin - * either to GND or to VIO. - * The detected value at boot time is accessible at run-time using the - * TPBANK0 register located in the gpio base of the pinctrl, in order diff --git a/target/linux/generic/backport-6.18/720-02-v6.13-net-phy-mediatek-ge-soc-Shrink-line-wrapping-to-80-c.patch b/target/linux/generic/backport-6.18/720-02-v6.13-net-phy-mediatek-ge-soc-Shrink-line-wrapping-to-80-c.patch deleted file mode 100644 index fbf3a99bd7..0000000000 --- a/target/linux/generic/backport-6.18/720-02-v6.13-net-phy-mediatek-ge-soc-Shrink-line-wrapping-to-80-c.patch +++ /dev/null @@ -1,271 +0,0 @@ -From c0dc1b412f9d840c51c5ee8927bf066e15a59550 Mon Sep 17 00:00:00 2001 -From: "SkyLake.Huang" -Date: Thu, 17 Oct 2024 11:22:12 +0800 -Subject: [PATCH 02/20] net: phy: mediatek-ge-soc: Shrink line wrapping to 80 - characters - -This patch shrinks line wrapping to 80 chars. Also, in -tx_amp_fill_result(), use FIELD_PREP() to prettify code. - -Signed-off-by: SkyLake.Huang -Reviewed-by: Simon Horman -Signed-off-by: Andrew Lunn ---- - drivers/net/phy/mediatek-ge-soc.c | 125 +++++++++++++++++++++--------- - 1 file changed, 88 insertions(+), 37 deletions(-) - ---- a/drivers/net/phy/mediatek-ge-soc.c -+++ b/drivers/net/phy/mediatek-ge-soc.c -@@ -342,7 +342,8 @@ static int cal_cycle(struct phy_device * - ret = phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1, - MTK_PHY_RG_AD_CAL_CLK, reg_val, - reg_val & MTK_PHY_DA_CAL_CLK, 500, -- ANALOG_INTERNAL_OPERATION_MAX_US, false); -+ ANALOG_INTERNAL_OPERATION_MAX_US, -+ false); - if (ret) { - phydev_err(phydev, "Calibration cycle timeout\n"); - return ret; -@@ -441,40 +442,72 @@ static int tx_amp_fill_result(struct phy - } - - phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TXVLD_DA_RG, -- MTK_PHY_DA_TX_I2MPB_A_GBE_MASK, (buf[0] + bias[0]) << 10); -+ MTK_PHY_DA_TX_I2MPB_A_GBE_MASK, -+ FIELD_PREP(MTK_PHY_DA_TX_I2MPB_A_GBE_MASK, -+ buf[0] + bias[0])); - phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TXVLD_DA_RG, -- MTK_PHY_DA_TX_I2MPB_A_TBT_MASK, buf[0] + bias[1]); -+ MTK_PHY_DA_TX_I2MPB_A_TBT_MASK, -+ FIELD_PREP(MTK_PHY_DA_TX_I2MPB_A_TBT_MASK, -+ buf[0] + bias[1])); - phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_A2, -- MTK_PHY_DA_TX_I2MPB_A_HBT_MASK, (buf[0] + bias[2]) << 10); -+ MTK_PHY_DA_TX_I2MPB_A_HBT_MASK, -+ FIELD_PREP(MTK_PHY_DA_TX_I2MPB_A_HBT_MASK, -+ buf[0] + bias[2])); - phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_A2, -- MTK_PHY_DA_TX_I2MPB_A_TST_MASK, buf[0] + bias[3]); -+ MTK_PHY_DA_TX_I2MPB_A_TST_MASK, -+ FIELD_PREP(MTK_PHY_DA_TX_I2MPB_A_TST_MASK, -+ buf[0] + bias[3])); - - phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_B1, -- MTK_PHY_DA_TX_I2MPB_B_GBE_MASK, (buf[1] + bias[4]) << 8); -+ MTK_PHY_DA_TX_I2MPB_B_GBE_MASK, -+ FIELD_PREP(MTK_PHY_DA_TX_I2MPB_B_GBE_MASK, -+ buf[1] + bias[4])); - phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_B1, -- MTK_PHY_DA_TX_I2MPB_B_TBT_MASK, buf[1] + bias[5]); -+ MTK_PHY_DA_TX_I2MPB_B_TBT_MASK, -+ FIELD_PREP(MTK_PHY_DA_TX_I2MPB_B_TBT_MASK, -+ buf[1] + bias[5])); - phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_B2, -- MTK_PHY_DA_TX_I2MPB_B_HBT_MASK, (buf[1] + bias[6]) << 8); -+ MTK_PHY_DA_TX_I2MPB_B_HBT_MASK, -+ FIELD_PREP(MTK_PHY_DA_TX_I2MPB_B_HBT_MASK, -+ buf[1] + bias[6])); - phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_B2, -- MTK_PHY_DA_TX_I2MPB_B_TST_MASK, buf[1] + bias[7]); -+ MTK_PHY_DA_TX_I2MPB_B_TST_MASK, -+ FIELD_PREP(MTK_PHY_DA_TX_I2MPB_B_TST_MASK, -+ buf[1] + bias[7])); - - phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_C1, -- MTK_PHY_DA_TX_I2MPB_C_GBE_MASK, (buf[2] + bias[8]) << 8); -+ MTK_PHY_DA_TX_I2MPB_C_GBE_MASK, -+ FIELD_PREP(MTK_PHY_DA_TX_I2MPB_C_GBE_MASK, -+ buf[2] + bias[8])); - phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_C1, -- MTK_PHY_DA_TX_I2MPB_C_TBT_MASK, buf[2] + bias[9]); -+ MTK_PHY_DA_TX_I2MPB_C_TBT_MASK, -+ FIELD_PREP(MTK_PHY_DA_TX_I2MPB_C_TBT_MASK, -+ buf[2] + bias[9])); - phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_C2, -- MTK_PHY_DA_TX_I2MPB_C_HBT_MASK, (buf[2] + bias[10]) << 8); -+ MTK_PHY_DA_TX_I2MPB_C_HBT_MASK, -+ FIELD_PREP(MTK_PHY_DA_TX_I2MPB_C_HBT_MASK, -+ buf[2] + bias[10])); - phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_C2, -- MTK_PHY_DA_TX_I2MPB_C_TST_MASK, buf[2] + bias[11]); -+ MTK_PHY_DA_TX_I2MPB_C_TST_MASK, -+ FIELD_PREP(MTK_PHY_DA_TX_I2MPB_C_TST_MASK, -+ buf[2] + bias[11])); - - phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_D1, -- MTK_PHY_DA_TX_I2MPB_D_GBE_MASK, (buf[3] + bias[12]) << 8); -+ MTK_PHY_DA_TX_I2MPB_D_GBE_MASK, -+ FIELD_PREP(MTK_PHY_DA_TX_I2MPB_D_GBE_MASK, -+ buf[3] + bias[12])); - phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_D1, -- MTK_PHY_DA_TX_I2MPB_D_TBT_MASK, buf[3] + bias[13]); -+ MTK_PHY_DA_TX_I2MPB_D_TBT_MASK, -+ FIELD_PREP(MTK_PHY_DA_TX_I2MPB_D_TBT_MASK, -+ buf[3] + bias[13])); - phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_D2, -- MTK_PHY_DA_TX_I2MPB_D_HBT_MASK, (buf[3] + bias[14]) << 8); -+ MTK_PHY_DA_TX_I2MPB_D_HBT_MASK, -+ FIELD_PREP(MTK_PHY_DA_TX_I2MPB_D_HBT_MASK, -+ buf[3] + bias[14])); - phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_D2, -- MTK_PHY_DA_TX_I2MPB_D_TST_MASK, buf[3] + bias[15]); -+ MTK_PHY_DA_TX_I2MPB_D_TST_MASK, -+ FIELD_PREP(MTK_PHY_DA_TX_I2MPB_D_TST_MASK, -+ buf[3] + bias[15])); - - return 0; - } -@@ -663,7 +696,8 @@ static int tx_vcm_cal_sw(struct phy_devi - goto restore; - - /* We calibrate TX-VCM in different logic. Check upper index and then -- * lower index. If this calibration is valid, apply lower index's result. -+ * lower index. If this calibration is valid, apply lower index's -+ * result. - */ - ret = upper_ret - lower_ret; - if (ret == 1) { -@@ -692,7 +726,8 @@ static int tx_vcm_cal_sw(struct phy_devi - } else if (upper_idx == TXRESERVE_MAX && upper_ret == 0 && - lower_ret == 0) { - ret = 0; -- phydev_warn(phydev, "TX-VCM SW cal result at high margin 0x%x\n", -+ phydev_warn(phydev, -+ "TX-VCM SW cal result at high margin 0x%x\n", - upper_idx); - } else { - ret = -EINVAL; -@@ -796,7 +831,8 @@ static void mt7981_phy_finetune(struct p - - /* TR_OPEN_LOOP_EN = 1, lpf_x_average = 9 */ - phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG234, -- MTK_PHY_TR_OPEN_LOOP_EN_MASK | MTK_PHY_LPF_X_AVERAGE_MASK, -+ MTK_PHY_TR_OPEN_LOOP_EN_MASK | -+ MTK_PHY_LPF_X_AVERAGE_MASK, - BIT(0) | FIELD_PREP(MTK_PHY_LPF_X_AVERAGE_MASK, 0x9)); - - /* rg_tr_lpf_cnt_val = 512 */ -@@ -865,7 +901,8 @@ static void mt7988_phy_finetune(struct p - - /* TR_OPEN_LOOP_EN = 1, lpf_x_average = 10 */ - phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG234, -- MTK_PHY_TR_OPEN_LOOP_EN_MASK | MTK_PHY_LPF_X_AVERAGE_MASK, -+ MTK_PHY_TR_OPEN_LOOP_EN_MASK | -+ MTK_PHY_LPF_X_AVERAGE_MASK, - BIT(0) | FIELD_PREP(MTK_PHY_LPF_X_AVERAGE_MASK, 0xa)); - - /* rg_tr_lpf_cnt_val = 1023 */ -@@ -977,7 +1014,8 @@ static void mt798x_phy_eee(struct phy_de - phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0); - - phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_3); -- __phy_modify(phydev, MTK_PHY_LPI_REG_14, MTK_PHY_LPI_WAKE_TIMER_1000_MASK, -+ __phy_modify(phydev, MTK_PHY_LPI_REG_14, -+ MTK_PHY_LPI_WAKE_TIMER_1000_MASK, - FIELD_PREP(MTK_PHY_LPI_WAKE_TIMER_1000_MASK, 0x19c)); - - __phy_modify(phydev, MTK_PHY_LPI_REG_1c, MTK_PHY_SMI_DET_ON_THRESH_MASK, -@@ -987,7 +1025,8 @@ static void mt798x_phy_eee(struct phy_de - phy_modify_mmd(phydev, MDIO_MMD_VEND1, - MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG122, - MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK, -- FIELD_PREP(MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK, 0xff)); -+ FIELD_PREP(MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK, -+ 0xff)); - } - - static int cal_sw(struct phy_device *phydev, enum CAL_ITEM cal_item, -@@ -1147,7 +1186,8 @@ static int mt798x_phy_hw_led_on_set(stru - (index ? 16 : 0), &priv->led_state); - if (changed) - return phy_modify_mmd(phydev, MDIO_MMD_VEND2, index ? -- MTK_PHY_LED1_ON_CTRL : MTK_PHY_LED0_ON_CTRL, -+ MTK_PHY_LED1_ON_CTRL : -+ MTK_PHY_LED0_ON_CTRL, - MTK_PHY_LED_ON_MASK, - on ? MTK_PHY_LED_ON_FORCE_ON : 0); - else -@@ -1157,7 +1197,8 @@ static int mt798x_phy_hw_led_on_set(stru - static int mt798x_phy_hw_led_blink_set(struct phy_device *phydev, u8 index, - bool blinking) - { -- unsigned int bit_blink = MTK_PHY_LED_STATE_FORCE_BLINK + (index ? 16 : 0); -+ unsigned int bit_blink = MTK_PHY_LED_STATE_FORCE_BLINK + -+ (index ? 16 : 0); - struct mtk_socphy_priv *priv = phydev->priv; - bool changed; - -@@ -1170,8 +1211,10 @@ static int mt798x_phy_hw_led_blink_set(s - (index ? 16 : 0), &priv->led_state); - if (changed) - return phy_write_mmd(phydev, MDIO_MMD_VEND2, index ? -- MTK_PHY_LED1_BLINK_CTRL : MTK_PHY_LED0_BLINK_CTRL, -- blinking ? MTK_PHY_LED_BLINK_FORCE_BLINK : 0); -+ MTK_PHY_LED1_BLINK_CTRL : -+ MTK_PHY_LED0_BLINK_CTRL, -+ blinking ? -+ MTK_PHY_LED_BLINK_FORCE_BLINK : 0); - else - return 0; - } -@@ -1237,7 +1280,8 @@ static int mt798x_phy_led_hw_is_supporte - static int mt798x_phy_led_hw_control_get(struct phy_device *phydev, u8 index, - unsigned long *rules) - { -- unsigned int bit_blink = MTK_PHY_LED_STATE_FORCE_BLINK + (index ? 16 : 0); -+ unsigned int bit_blink = MTK_PHY_LED_STATE_FORCE_BLINK + -+ (index ? 16 : 0); - unsigned int bit_netdev = MTK_PHY_LED_STATE_NETDEV + (index ? 16 : 0); - unsigned int bit_on = MTK_PHY_LED_STATE_FORCE_ON + (index ? 16 : 0); - struct mtk_socphy_priv *priv = phydev->priv; -@@ -1258,8 +1302,8 @@ static int mt798x_phy_led_hw_control_get - if (blink < 0) - return -EIO; - -- if ((on & (MTK_PHY_LED_ON_LINK | MTK_PHY_LED_ON_FDX | MTK_PHY_LED_ON_HDX | -- MTK_PHY_LED_ON_LINKDOWN)) || -+ if ((on & (MTK_PHY_LED_ON_LINK | MTK_PHY_LED_ON_FDX | -+ MTK_PHY_LED_ON_HDX | MTK_PHY_LED_ON_LINKDOWN)) || - (blink & (MTK_PHY_LED_BLINK_RX | MTK_PHY_LED_BLINK_TX))) - set_bit(bit_netdev, &priv->led_state); - else -@@ -1333,17 +1377,23 @@ static int mt798x_phy_led_hw_control_set - - if (rules & BIT(TRIGGER_NETDEV_RX)) { - blink |= (on & MTK_PHY_LED_ON_LINK) ? -- (((on & MTK_PHY_LED_ON_LINK10) ? MTK_PHY_LED_BLINK_10RX : 0) | -- ((on & MTK_PHY_LED_ON_LINK100) ? MTK_PHY_LED_BLINK_100RX : 0) | -- ((on & MTK_PHY_LED_ON_LINK1000) ? MTK_PHY_LED_BLINK_1000RX : 0)) : -+ (((on & MTK_PHY_LED_ON_LINK10) ? -+ MTK_PHY_LED_BLINK_10RX : 0) | -+ ((on & MTK_PHY_LED_ON_LINK100) ? -+ MTK_PHY_LED_BLINK_100RX : 0) | -+ ((on & MTK_PHY_LED_ON_LINK1000) ? -+ MTK_PHY_LED_BLINK_1000RX : 0)) : - MTK_PHY_LED_BLINK_RX; - } - - if (rules & BIT(TRIGGER_NETDEV_TX)) { - blink |= (on & MTK_PHY_LED_ON_LINK) ? -- (((on & MTK_PHY_LED_ON_LINK10) ? MTK_PHY_LED_BLINK_10TX : 0) | -- ((on & MTK_PHY_LED_ON_LINK100) ? MTK_PHY_LED_BLINK_100TX : 0) | -- ((on & MTK_PHY_LED_ON_LINK1000) ? MTK_PHY_LED_BLINK_1000TX : 0)) : -+ (((on & MTK_PHY_LED_ON_LINK10) ? -+ MTK_PHY_LED_BLINK_10TX : 0) | -+ ((on & MTK_PHY_LED_ON_LINK100) ? -+ MTK_PHY_LED_BLINK_100TX : 0) | -+ ((on & MTK_PHY_LED_ON_LINK1000) ? -+ MTK_PHY_LED_BLINK_1000TX : 0)) : - MTK_PHY_LED_BLINK_TX; - } - -@@ -1400,7 +1450,8 @@ static int mt7988_phy_fix_leds_polaritie - /* Only now setup pinctrl to avoid bogus blinking */ - pinctrl = devm_pinctrl_get_select(&phydev->mdio.dev, "gbe-led"); - if (IS_ERR(pinctrl)) -- dev_err(&phydev->mdio.bus->dev, "Failed to setup PHY LED pinctrl\n"); -+ dev_err(&phydev->mdio.bus->dev, -+ "Failed to setup PHY LED pinctrl\n"); - - return 0; - } diff --git a/target/linux/generic/backport-6.18/720-03-v6.13-net-phy-mediatek-ge-soc-Propagate-error-code-correct.patch b/target/linux/generic/backport-6.18/720-03-v6.13-net-phy-mediatek-ge-soc-Propagate-error-code-correct.patch deleted file mode 100644 index 1f6f5f5df6..0000000000 --- a/target/linux/generic/backport-6.18/720-03-v6.13-net-phy-mediatek-ge-soc-Propagate-error-code-correct.patch +++ /dev/null @@ -1,40 +0,0 @@ -From bcbbfb4f62c4ba35783cc617997a2e92d91e3940 Mon Sep 17 00:00:00 2001 -From: "SkyLake.Huang" -Date: Thu, 17 Oct 2024 11:22:13 +0800 -Subject: [PATCH 03/20] net: phy: mediatek-ge-soc: Propagate error code - correctly in cal_cycle() - -This patch propagates error code correctly in cal_cycle() -and improve with FIELD_GET(). - -Signed-off-by: SkyLake.Huang -Reviewed-by: Simon Horman -Signed-off-by: Andrew Lunn ---- - drivers/net/phy/mediatek-ge-soc.c | 8 +++++--- - 1 file changed, 5 insertions(+), 3 deletions(-) - ---- a/drivers/net/phy/mediatek-ge-soc.c -+++ b/drivers/net/phy/mediatek-ge-soc.c -@@ -110,7 +110,7 @@ - #define MTK_PHY_CR_TX_AMP_OFFSET_D_MASK GENMASK(6, 0) - - #define MTK_PHY_RG_AD_CAL_COMP 0x17a --#define MTK_PHY_AD_CAL_COMP_OUT_SHIFT (8) -+#define MTK_PHY_AD_CAL_COMP_OUT_MASK GENMASK(8, 8) - - #define MTK_PHY_RG_AD_CAL_CLK 0x17b - #define MTK_PHY_DA_CAL_CLK BIT(0) -@@ -351,8 +351,10 @@ static int cal_cycle(struct phy_device * - - phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_AD_CALIN, - MTK_PHY_DA_CALIN_FLAG); -- ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_AD_CAL_COMP) >> -- MTK_PHY_AD_CAL_COMP_OUT_SHIFT; -+ ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_AD_CAL_COMP); -+ if (ret < 0) -+ return ret; -+ ret = FIELD_GET(MTK_PHY_AD_CAL_COMP_OUT_MASK, ret); - phydev_dbg(phydev, "cal_val: 0x%x, ret: %d\n", cal_val, ret); - - return ret; diff --git a/target/linux/generic/backport-6.18/720-04-v6.13-net-phy-mediatek-Re-organize-MediaTek-ethernet-phy-d.patch b/target/linux/generic/backport-6.18/720-04-v6.13-net-phy-mediatek-Re-organize-MediaTek-ethernet-phy-d.patch deleted file mode 100644 index 81e2510912..0000000000 --- a/target/linux/generic/backport-6.18/720-04-v6.13-net-phy-mediatek-Re-organize-MediaTek-ethernet-phy-d.patch +++ /dev/null @@ -1,3565 +0,0 @@ -From e062f073dc0df4fcd338043cb0b69b6bcd31e4af Mon Sep 17 00:00:00 2001 -From: "SkyLake.Huang" -Date: Sat, 9 Nov 2024 00:34:51 +0800 -Subject: [PATCH 04/20] net: phy: mediatek: Re-organize MediaTek ethernet phy - drivers - -Re-organize MediaTek ethernet phy driver files and get ready to integrate -some common functions and add new 2.5G phy driver. -mtk-ge.c: MT7530 Gphy on MT7621 & MT7531 Gphy -mtk-ge-soc.c: Built-in Gphy on MT7981 & Built-in switch Gphy on MT7988 -mtk-2p5ge.c: Planned for built-in 2.5G phy on MT7988 - -Reviewed-by: Andrew Lunn -Signed-off-by: SkyLake.Huang -Signed-off-by: David S. Miller ---- - MAINTAINERS | 4 ++-- - drivers/net/phy/Kconfig | 17 +------------- - drivers/net/phy/Makefile | 3 +-- - drivers/net/phy/mediatek/Kconfig | 22 +++++++++++++++++++ - drivers/net/phy/mediatek/Makefile | 3 +++ - .../mtk-ge-soc.c} | 0 - .../phy/{mediatek-ge.c => mediatek/mtk-ge.c} | 0 - 7 files changed, 29 insertions(+), 20 deletions(-) - create mode 100644 drivers/net/phy/mediatek/Kconfig - create mode 100644 drivers/net/phy/mediatek/Makefile - rename drivers/net/phy/{mediatek-ge-soc.c => mediatek/mtk-ge-soc.c} (100%) - rename drivers/net/phy/{mediatek-ge.c => mediatek/mtk-ge.c} (100%) - ---- a/MAINTAINERS -+++ b/MAINTAINERS -@@ -14427,8 +14427,8 @@ M: Qingfang Deng - M: SkyLake Huang - L: netdev@vger.kernel.org - S: Maintained --F: drivers/net/phy/mediatek-ge-soc.c --F: drivers/net/phy/mediatek-ge.c -+F: drivers/net/phy/mediatek/mtk-ge-soc.c -+F: drivers/net/phy/mediatek/mtk-ge.c - F: drivers/phy/mediatek/phy-mtk-xfi-tphy.c - - MEDIATEK I2C CONTROLLER DRIVER ---- a/drivers/net/phy/Kconfig -+++ b/drivers/net/phy/Kconfig -@@ -266,22 +266,7 @@ config MAXLINEAR_GPHY - Support for the Maxlinear GPY115, GPY211, GPY212, GPY215, - GPY241, GPY245 PHYs. - --config MEDIATEK_GE_PHY -- tristate "MediaTek Gigabit Ethernet PHYs" -- help -- Supports the MediaTek Gigabit Ethernet PHYs. -- --config MEDIATEK_GE_SOC_PHY -- tristate "MediaTek SoC Ethernet PHYs" -- depends on (ARM64 && ARCH_MEDIATEK) || COMPILE_TEST -- depends on NVMEM_MTK_EFUSE -- help -- Supports MediaTek SoC built-in Gigabit Ethernet PHYs. -- -- Include support for built-in Ethernet PHYs which are present in -- the MT7981 and MT7988 SoCs. These PHYs need calibration data -- present in the SoCs efuse and will dynamically calibrate VCM -- (common-mode voltage) during startup. -+source "drivers/net/phy/mediatek/Kconfig" - - config MICREL_PHY - tristate "Micrel PHYs" ---- a/drivers/net/phy/Makefile -+++ b/drivers/net/phy/Makefile -@@ -74,8 +74,7 @@ obj-$(CONFIG_MARVELL_PHY) += marvell.o - obj-$(CONFIG_MARVELL_88Q2XXX_PHY) += marvell-88q2xxx.o - obj-$(CONFIG_MARVELL_88X2222_PHY) += marvell-88x2222.o - obj-$(CONFIG_MAXLINEAR_GPHY) += mxl-gpy.o --obj-$(CONFIG_MEDIATEK_GE_PHY) += mediatek-ge.o --obj-$(CONFIG_MEDIATEK_GE_SOC_PHY) += mediatek-ge-soc.o -+obj-y += mediatek/ - obj-$(CONFIG_MESON_GXL_PHY) += meson-gxl.o - obj-$(CONFIG_MICREL_KS8995MA) += spi_ks8995.o - obj-$(CONFIG_MICREL_PHY) += micrel.o ---- /dev/null -+++ b/drivers/net/phy/mediatek/Kconfig -@@ -0,0 +1,22 @@ -+# SPDX-License-Identifier: GPL-2.0-only -+config MEDIATEK_GE_PHY -+ tristate "MediaTek Gigabit Ethernet PHYs" -+ help -+ Supports the MediaTek non-built-in Gigabit Ethernet PHYs. -+ -+ Non-built-in Gigabit Ethernet PHYs include mt7530/mt7531. -+ You may find mt7530 inside mt7621. This driver shares some -+ common operations with MediaTek SoC built-in Gigabit -+ Ethernet PHYs. -+ -+config MEDIATEK_GE_SOC_PHY -+ tristate "MediaTek SoC Ethernet PHYs" -+ depends on (ARM64 && ARCH_MEDIATEK) || COMPILE_TEST -+ depends on NVMEM_MTK_EFUSE -+ help -+ Supports MediaTek SoC built-in Gigabit Ethernet PHYs. -+ -+ Include support for built-in Ethernet PHYs which are present in -+ the MT7981 and MT7988 SoCs. These PHYs need calibration data -+ present in the SoCs efuse and will dynamically calibrate VCM -+ (common-mode voltage) during startup. ---- /dev/null -+++ b/drivers/net/phy/mediatek/Makefile -@@ -0,0 +1,3 @@ -+# SPDX-License-Identifier: GPL-2.0 -+obj-$(CONFIG_MEDIATEK_GE_PHY) += mtk-ge.o -+obj-$(CONFIG_MEDIATEK_GE_SOC_PHY) += mtk-ge-soc.o ---- a/drivers/net/phy/mediatek-ge-soc.c -+++ /dev/null -@@ -1,1610 +0,0 @@ --// SPDX-License-Identifier: GPL-2.0+ --#include --#include --#include --#include --#include --#include --#include --#include -- --#define MTK_GPHY_ID_MT7981 0x03a29461 --#define MTK_GPHY_ID_MT7988 0x03a29481 -- --#define MTK_EXT_PAGE_ACCESS 0x1f --#define MTK_PHY_PAGE_STANDARD 0x0000 --#define MTK_PHY_PAGE_EXTENDED_3 0x0003 -- --#define MTK_PHY_LPI_REG_14 0x14 --#define MTK_PHY_LPI_WAKE_TIMER_1000_MASK GENMASK(8, 0) -- --#define MTK_PHY_LPI_REG_1c 0x1c --#define MTK_PHY_SMI_DET_ON_THRESH_MASK GENMASK(13, 8) -- --#define MTK_PHY_PAGE_EXTENDED_2A30 0x2a30 --#define MTK_PHY_PAGE_EXTENDED_52B5 0x52b5 -- --#define ANALOG_INTERNAL_OPERATION_MAX_US 20 --#define TXRESERVE_MIN 0 --#define TXRESERVE_MAX 7 -- --#define MTK_PHY_ANARG_RG 0x10 --#define MTK_PHY_TCLKOFFSET_MASK GENMASK(12, 8) -- --/* Registers on MDIO_MMD_VEND1 */ --#define MTK_PHY_TXVLD_DA_RG 0x12 --#define MTK_PHY_DA_TX_I2MPB_A_GBE_MASK GENMASK(15, 10) --#define MTK_PHY_DA_TX_I2MPB_A_TBT_MASK GENMASK(5, 0) -- --#define MTK_PHY_TX_I2MPB_TEST_MODE_A2 0x16 --#define MTK_PHY_DA_TX_I2MPB_A_HBT_MASK GENMASK(15, 10) --#define MTK_PHY_DA_TX_I2MPB_A_TST_MASK GENMASK(5, 0) -- --#define MTK_PHY_TX_I2MPB_TEST_MODE_B1 0x17 --#define MTK_PHY_DA_TX_I2MPB_B_GBE_MASK GENMASK(13, 8) --#define MTK_PHY_DA_TX_I2MPB_B_TBT_MASK GENMASK(5, 0) -- --#define MTK_PHY_TX_I2MPB_TEST_MODE_B2 0x18 --#define MTK_PHY_DA_TX_I2MPB_B_HBT_MASK GENMASK(13, 8) --#define MTK_PHY_DA_TX_I2MPB_B_TST_MASK GENMASK(5, 0) -- --#define MTK_PHY_TX_I2MPB_TEST_MODE_C1 0x19 --#define MTK_PHY_DA_TX_I2MPB_C_GBE_MASK GENMASK(13, 8) --#define MTK_PHY_DA_TX_I2MPB_C_TBT_MASK GENMASK(5, 0) -- --#define MTK_PHY_TX_I2MPB_TEST_MODE_C2 0x20 --#define MTK_PHY_DA_TX_I2MPB_C_HBT_MASK GENMASK(13, 8) --#define MTK_PHY_DA_TX_I2MPB_C_TST_MASK GENMASK(5, 0) -- --#define MTK_PHY_TX_I2MPB_TEST_MODE_D1 0x21 --#define MTK_PHY_DA_TX_I2MPB_D_GBE_MASK GENMASK(13, 8) --#define MTK_PHY_DA_TX_I2MPB_D_TBT_MASK GENMASK(5, 0) -- --#define MTK_PHY_TX_I2MPB_TEST_MODE_D2 0x22 --#define MTK_PHY_DA_TX_I2MPB_D_HBT_MASK GENMASK(13, 8) --#define MTK_PHY_DA_TX_I2MPB_D_TST_MASK GENMASK(5, 0) -- --#define MTK_PHY_RXADC_CTRL_RG7 0xc6 --#define MTK_PHY_DA_AD_BUF_BIAS_LP_MASK GENMASK(9, 8) -- --#define MTK_PHY_RXADC_CTRL_RG9 0xc8 --#define MTK_PHY_DA_RX_PSBN_TBT_MASK GENMASK(14, 12) --#define MTK_PHY_DA_RX_PSBN_HBT_MASK GENMASK(10, 8) --#define MTK_PHY_DA_RX_PSBN_GBE_MASK GENMASK(6, 4) --#define MTK_PHY_DA_RX_PSBN_LP_MASK GENMASK(2, 0) -- --#define MTK_PHY_LDO_OUTPUT_V 0xd7 -- --#define MTK_PHY_RG_ANA_CAL_RG0 0xdb --#define MTK_PHY_RG_CAL_CKINV BIT(12) --#define MTK_PHY_RG_ANA_CALEN BIT(8) --#define MTK_PHY_RG_ZCALEN_A BIT(0) -- --#define MTK_PHY_RG_ANA_CAL_RG1 0xdc --#define MTK_PHY_RG_ZCALEN_B BIT(12) --#define MTK_PHY_RG_ZCALEN_C BIT(8) --#define MTK_PHY_RG_ZCALEN_D BIT(4) --#define MTK_PHY_RG_TXVOS_CALEN BIT(0) -- --#define MTK_PHY_RG_ANA_CAL_RG5 0xe0 --#define MTK_PHY_RG_REXT_TRIM_MASK GENMASK(13, 8) -- --#define MTK_PHY_RG_TX_FILTER 0xfe -- --#define MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG120 0x120 --#define MTK_PHY_LPI_SIG_EN_LO_THRESH1000_MASK GENMASK(12, 8) --#define MTK_PHY_LPI_SIG_EN_HI_THRESH1000_MASK GENMASK(4, 0) -- --#define MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG122 0x122 --#define MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK GENMASK(7, 0) -- --#define MTK_PHY_RG_TESTMUX_ADC_CTRL 0x144 --#define MTK_PHY_RG_TXEN_DIG_MASK GENMASK(5, 5) -- --#define MTK_PHY_RG_CR_TX_AMP_OFFSET_A_B 0x172 --#define MTK_PHY_CR_TX_AMP_OFFSET_A_MASK GENMASK(13, 8) --#define MTK_PHY_CR_TX_AMP_OFFSET_B_MASK GENMASK(6, 0) -- --#define MTK_PHY_RG_CR_TX_AMP_OFFSET_C_D 0x173 --#define MTK_PHY_CR_TX_AMP_OFFSET_C_MASK GENMASK(13, 8) --#define MTK_PHY_CR_TX_AMP_OFFSET_D_MASK GENMASK(6, 0) -- --#define MTK_PHY_RG_AD_CAL_COMP 0x17a --#define MTK_PHY_AD_CAL_COMP_OUT_MASK GENMASK(8, 8) -- --#define MTK_PHY_RG_AD_CAL_CLK 0x17b --#define MTK_PHY_DA_CAL_CLK BIT(0) -- --#define MTK_PHY_RG_AD_CALIN 0x17c --#define MTK_PHY_DA_CALIN_FLAG BIT(0) -- --#define MTK_PHY_RG_DASN_DAC_IN0_A 0x17d --#define MTK_PHY_DASN_DAC_IN0_A_MASK GENMASK(9, 0) -- --#define MTK_PHY_RG_DASN_DAC_IN0_B 0x17e --#define MTK_PHY_DASN_DAC_IN0_B_MASK GENMASK(9, 0) -- --#define MTK_PHY_RG_DASN_DAC_IN0_C 0x17f --#define MTK_PHY_DASN_DAC_IN0_C_MASK GENMASK(9, 0) -- --#define MTK_PHY_RG_DASN_DAC_IN0_D 0x180 --#define MTK_PHY_DASN_DAC_IN0_D_MASK GENMASK(9, 0) -- --#define MTK_PHY_RG_DASN_DAC_IN1_A 0x181 --#define MTK_PHY_DASN_DAC_IN1_A_MASK GENMASK(9, 0) -- --#define MTK_PHY_RG_DASN_DAC_IN1_B 0x182 --#define MTK_PHY_DASN_DAC_IN1_B_MASK GENMASK(9, 0) -- --#define MTK_PHY_RG_DASN_DAC_IN1_C 0x183 --#define MTK_PHY_DASN_DAC_IN1_C_MASK GENMASK(9, 0) -- --#define MTK_PHY_RG_DASN_DAC_IN1_D 0x184 --#define MTK_PHY_DASN_DAC_IN1_D_MASK GENMASK(9, 0) -- --#define MTK_PHY_RG_DEV1E_REG19b 0x19b --#define MTK_PHY_BYPASS_DSP_LPI_READY BIT(8) -- --#define MTK_PHY_RG_LP_IIR2_K1_L 0x22a --#define MTK_PHY_RG_LP_IIR2_K1_U 0x22b --#define MTK_PHY_RG_LP_IIR2_K2_L 0x22c --#define MTK_PHY_RG_LP_IIR2_K2_U 0x22d --#define MTK_PHY_RG_LP_IIR2_K3_L 0x22e --#define MTK_PHY_RG_LP_IIR2_K3_U 0x22f --#define MTK_PHY_RG_LP_IIR2_K4_L 0x230 --#define MTK_PHY_RG_LP_IIR2_K4_U 0x231 --#define MTK_PHY_RG_LP_IIR2_K5_L 0x232 --#define MTK_PHY_RG_LP_IIR2_K5_U 0x233 -- --#define MTK_PHY_RG_DEV1E_REG234 0x234 --#define MTK_PHY_TR_OPEN_LOOP_EN_MASK GENMASK(0, 0) --#define MTK_PHY_LPF_X_AVERAGE_MASK GENMASK(7, 4) --#define MTK_PHY_TR_LP_IIR_EEE_EN BIT(12) -- --#define MTK_PHY_RG_LPF_CNT_VAL 0x235 -- --#define MTK_PHY_RG_DEV1E_REG238 0x238 --#define MTK_PHY_LPI_SLV_SEND_TX_TIMER_MASK GENMASK(8, 0) --#define MTK_PHY_LPI_SLV_SEND_TX_EN BIT(12) -- --#define MTK_PHY_RG_DEV1E_REG239 0x239 --#define MTK_PHY_LPI_SEND_LOC_TIMER_MASK GENMASK(8, 0) --#define MTK_PHY_LPI_TXPCS_LOC_RCV BIT(12) -- --#define MTK_PHY_RG_DEV1E_REG27C 0x27c --#define MTK_PHY_VGASTATE_FFE_THR_ST1_MASK GENMASK(12, 8) --#define MTK_PHY_RG_DEV1E_REG27D 0x27d --#define MTK_PHY_VGASTATE_FFE_THR_ST2_MASK GENMASK(4, 0) -- --#define MTK_PHY_RG_DEV1E_REG2C7 0x2c7 --#define MTK_PHY_MAX_GAIN_MASK GENMASK(4, 0) --#define MTK_PHY_MIN_GAIN_MASK GENMASK(12, 8) -- --#define MTK_PHY_RG_DEV1E_REG2D1 0x2d1 --#define MTK_PHY_VCO_SLICER_THRESH_BITS_HIGH_EEE_MASK GENMASK(7, 0) --#define MTK_PHY_LPI_SKIP_SD_SLV_TR BIT(8) --#define MTK_PHY_LPI_TR_READY BIT(9) --#define MTK_PHY_LPI_VCO_EEE_STG0_EN BIT(10) -- --#define MTK_PHY_RG_DEV1E_REG323 0x323 --#define MTK_PHY_EEE_WAKE_MAS_INT_DC BIT(0) --#define MTK_PHY_EEE_WAKE_SLV_INT_DC BIT(4) -- --#define MTK_PHY_RG_DEV1E_REG324 0x324 --#define MTK_PHY_SMI_DETCNT_MAX_MASK GENMASK(5, 0) --#define MTK_PHY_SMI_DET_MAX_EN BIT(8) -- --#define MTK_PHY_RG_DEV1E_REG326 0x326 --#define MTK_PHY_LPI_MODE_SD_ON BIT(0) --#define MTK_PHY_RESET_RANDUPD_CNT BIT(1) --#define MTK_PHY_TREC_UPDATE_ENAB_CLR BIT(2) --#define MTK_PHY_LPI_QUIT_WAIT_DFE_SIG_DET_OFF BIT(4) --#define MTK_PHY_TR_READY_SKIP_AFE_WAKEUP BIT(5) -- --#define MTK_PHY_LDO_PUMP_EN_PAIRAB 0x502 --#define MTK_PHY_LDO_PUMP_EN_PAIRCD 0x503 -- --#define MTK_PHY_DA_TX_R50_PAIR_A 0x53d --#define MTK_PHY_DA_TX_R50_PAIR_B 0x53e --#define MTK_PHY_DA_TX_R50_PAIR_C 0x53f --#define MTK_PHY_DA_TX_R50_PAIR_D 0x540 -- --/* Registers on MDIO_MMD_VEND2 */ --#define MTK_PHY_LED0_ON_CTRL 0x24 --#define MTK_PHY_LED1_ON_CTRL 0x26 --#define MTK_PHY_LED_ON_MASK GENMASK(6, 0) --#define MTK_PHY_LED_ON_LINK1000 BIT(0) --#define MTK_PHY_LED_ON_LINK100 BIT(1) --#define MTK_PHY_LED_ON_LINK10 BIT(2) --#define MTK_PHY_LED_ON_LINK (MTK_PHY_LED_ON_LINK10 |\ -- MTK_PHY_LED_ON_LINK100 |\ -- MTK_PHY_LED_ON_LINK1000) --#define MTK_PHY_LED_ON_LINKDOWN BIT(3) --#define MTK_PHY_LED_ON_FDX BIT(4) /* Full duplex */ --#define MTK_PHY_LED_ON_HDX BIT(5) /* Half duplex */ --#define MTK_PHY_LED_ON_FORCE_ON BIT(6) --#define MTK_PHY_LED_ON_POLARITY BIT(14) --#define MTK_PHY_LED_ON_ENABLE BIT(15) -- --#define MTK_PHY_LED0_BLINK_CTRL 0x25 --#define MTK_PHY_LED1_BLINK_CTRL 0x27 --#define MTK_PHY_LED_BLINK_1000TX BIT(0) --#define MTK_PHY_LED_BLINK_1000RX BIT(1) --#define MTK_PHY_LED_BLINK_100TX BIT(2) --#define MTK_PHY_LED_BLINK_100RX BIT(3) --#define MTK_PHY_LED_BLINK_10TX BIT(4) --#define MTK_PHY_LED_BLINK_10RX BIT(5) --#define MTK_PHY_LED_BLINK_RX (MTK_PHY_LED_BLINK_10RX |\ -- MTK_PHY_LED_BLINK_100RX |\ -- MTK_PHY_LED_BLINK_1000RX) --#define MTK_PHY_LED_BLINK_TX (MTK_PHY_LED_BLINK_10TX |\ -- MTK_PHY_LED_BLINK_100TX |\ -- MTK_PHY_LED_BLINK_1000TX) --#define MTK_PHY_LED_BLINK_COLLISION BIT(6) --#define MTK_PHY_LED_BLINK_RX_CRC_ERR BIT(7) --#define MTK_PHY_LED_BLINK_RX_IDLE_ERR BIT(8) --#define MTK_PHY_LED_BLINK_FORCE_BLINK BIT(9) -- --#define MTK_PHY_LED1_DEFAULT_POLARITIES BIT(1) -- --#define MTK_PHY_RG_BG_RASEL 0x115 --#define MTK_PHY_RG_BG_RASEL_MASK GENMASK(2, 0) -- --/* 'boottrap' register reflecting the configuration of the 4 PHY LEDs */ --#define RG_GPIO_MISC_TPBANK0 0x6f0 --#define RG_GPIO_MISC_TPBANK0_BOOTMODE GENMASK(11, 8) -- --/* These macro privides efuse parsing for internal phy. */ --#define EFS_DA_TX_I2MPB_A(x) (((x) >> 0) & GENMASK(5, 0)) --#define EFS_DA_TX_I2MPB_B(x) (((x) >> 6) & GENMASK(5, 0)) --#define EFS_DA_TX_I2MPB_C(x) (((x) >> 12) & GENMASK(5, 0)) --#define EFS_DA_TX_I2MPB_D(x) (((x) >> 18) & GENMASK(5, 0)) --#define EFS_DA_TX_AMP_OFFSET_A(x) (((x) >> 24) & GENMASK(5, 0)) -- --#define EFS_DA_TX_AMP_OFFSET_B(x) (((x) >> 0) & GENMASK(5, 0)) --#define EFS_DA_TX_AMP_OFFSET_C(x) (((x) >> 6) & GENMASK(5, 0)) --#define EFS_DA_TX_AMP_OFFSET_D(x) (((x) >> 12) & GENMASK(5, 0)) --#define EFS_DA_TX_R50_A(x) (((x) >> 18) & GENMASK(5, 0)) --#define EFS_DA_TX_R50_B(x) (((x) >> 24) & GENMASK(5, 0)) -- --#define EFS_DA_TX_R50_C(x) (((x) >> 0) & GENMASK(5, 0)) --#define EFS_DA_TX_R50_D(x) (((x) >> 6) & GENMASK(5, 0)) -- --#define EFS_RG_BG_RASEL(x) (((x) >> 4) & GENMASK(2, 0)) --#define EFS_RG_REXT_TRIM(x) (((x) >> 7) & GENMASK(5, 0)) -- --enum { -- NO_PAIR, -- PAIR_A, -- PAIR_B, -- PAIR_C, -- PAIR_D, --}; -- --enum calibration_mode { -- EFUSE_K, -- SW_K --}; -- --enum CAL_ITEM { -- REXT, -- TX_OFFSET, -- TX_AMP, -- TX_R50, -- TX_VCM --}; -- --enum CAL_MODE { -- EFUSE_M, -- SW_M --}; -- --#define MTK_PHY_LED_STATE_FORCE_ON 0 --#define MTK_PHY_LED_STATE_FORCE_BLINK 1 --#define MTK_PHY_LED_STATE_NETDEV 2 -- --struct mtk_socphy_priv { -- unsigned long led_state; --}; -- --struct mtk_socphy_shared { -- u32 boottrap; -- struct mtk_socphy_priv priv[4]; --}; -- --static int mtk_socphy_read_page(struct phy_device *phydev) --{ -- return __phy_read(phydev, MTK_EXT_PAGE_ACCESS); --} -- --static int mtk_socphy_write_page(struct phy_device *phydev, int page) --{ -- return __phy_write(phydev, MTK_EXT_PAGE_ACCESS, page); --} -- --/* One calibration cycle consists of: -- * 1.Set DA_CALIN_FLAG high to start calibration. Keep it high -- * until AD_CAL_COMP is ready to output calibration result. -- * 2.Wait until DA_CAL_CLK is available. -- * 3.Fetch AD_CAL_COMP_OUT. -- */ --static int cal_cycle(struct phy_device *phydev, int devad, -- u32 regnum, u16 mask, u16 cal_val) --{ -- int reg_val; -- int ret; -- -- phy_modify_mmd(phydev, devad, regnum, -- mask, cal_val); -- phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_AD_CALIN, -- MTK_PHY_DA_CALIN_FLAG); -- -- ret = phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1, -- MTK_PHY_RG_AD_CAL_CLK, reg_val, -- reg_val & MTK_PHY_DA_CAL_CLK, 500, -- ANALOG_INTERNAL_OPERATION_MAX_US, -- false); -- if (ret) { -- phydev_err(phydev, "Calibration cycle timeout\n"); -- return ret; -- } -- -- phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_AD_CALIN, -- MTK_PHY_DA_CALIN_FLAG); -- ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_AD_CAL_COMP); -- if (ret < 0) -- return ret; -- ret = FIELD_GET(MTK_PHY_AD_CAL_COMP_OUT_MASK, ret); -- phydev_dbg(phydev, "cal_val: 0x%x, ret: %d\n", cal_val, ret); -- -- return ret; --} -- --static int rext_fill_result(struct phy_device *phydev, u16 *buf) --{ -- phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG5, -- MTK_PHY_RG_REXT_TRIM_MASK, buf[0] << 8); -- phy_modify_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_RG_BG_RASEL, -- MTK_PHY_RG_BG_RASEL_MASK, buf[1]); -- -- return 0; --} -- --static int rext_cal_efuse(struct phy_device *phydev, u32 *buf) --{ -- u16 rext_cal_val[2]; -- -- rext_cal_val[0] = EFS_RG_REXT_TRIM(buf[3]); -- rext_cal_val[1] = EFS_RG_BG_RASEL(buf[3]); -- rext_fill_result(phydev, rext_cal_val); -- -- return 0; --} -- --static int tx_offset_fill_result(struct phy_device *phydev, u16 *buf) --{ -- phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_CR_TX_AMP_OFFSET_A_B, -- MTK_PHY_CR_TX_AMP_OFFSET_A_MASK, buf[0] << 8); -- phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_CR_TX_AMP_OFFSET_A_B, -- MTK_PHY_CR_TX_AMP_OFFSET_B_MASK, buf[1]); -- phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_CR_TX_AMP_OFFSET_C_D, -- MTK_PHY_CR_TX_AMP_OFFSET_C_MASK, buf[2] << 8); -- phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_CR_TX_AMP_OFFSET_C_D, -- MTK_PHY_CR_TX_AMP_OFFSET_D_MASK, buf[3]); -- -- return 0; --} -- --static int tx_offset_cal_efuse(struct phy_device *phydev, u32 *buf) --{ -- u16 tx_offset_cal_val[4]; -- -- tx_offset_cal_val[0] = EFS_DA_TX_AMP_OFFSET_A(buf[0]); -- tx_offset_cal_val[1] = EFS_DA_TX_AMP_OFFSET_B(buf[1]); -- tx_offset_cal_val[2] = EFS_DA_TX_AMP_OFFSET_C(buf[1]); -- tx_offset_cal_val[3] = EFS_DA_TX_AMP_OFFSET_D(buf[1]); -- -- tx_offset_fill_result(phydev, tx_offset_cal_val); -- -- return 0; --} -- --static int tx_amp_fill_result(struct phy_device *phydev, u16 *buf) --{ -- const int vals_9481[16] = { 10, 6, 6, 10, -- 10, 6, 6, 10, -- 10, 6, 6, 10, -- 10, 6, 6, 10 }; -- const int vals_9461[16] = { 7, 1, 4, 7, -- 7, 1, 4, 7, -- 7, 1, 4, 7, -- 7, 1, 4, 7 }; -- int bias[16] = {}; -- int i; -- -- switch (phydev->drv->phy_id) { -- case MTK_GPHY_ID_MT7981: -- /* We add some calibration to efuse values -- * due to board level influence. -- * GBE: +7, TBT: +1, HBT: +4, TST: +7 -- */ -- memcpy(bias, (const void *)vals_9461, sizeof(bias)); -- break; -- case MTK_GPHY_ID_MT7988: -- memcpy(bias, (const void *)vals_9481, sizeof(bias)); -- break; -- } -- -- /* Prevent overflow */ -- for (i = 0; i < 12; i++) { -- if (buf[i >> 2] + bias[i] > 63) { -- buf[i >> 2] = 63; -- bias[i] = 0; -- } -- } -- -- phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TXVLD_DA_RG, -- MTK_PHY_DA_TX_I2MPB_A_GBE_MASK, -- FIELD_PREP(MTK_PHY_DA_TX_I2MPB_A_GBE_MASK, -- buf[0] + bias[0])); -- phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TXVLD_DA_RG, -- MTK_PHY_DA_TX_I2MPB_A_TBT_MASK, -- FIELD_PREP(MTK_PHY_DA_TX_I2MPB_A_TBT_MASK, -- buf[0] + bias[1])); -- phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_A2, -- MTK_PHY_DA_TX_I2MPB_A_HBT_MASK, -- FIELD_PREP(MTK_PHY_DA_TX_I2MPB_A_HBT_MASK, -- buf[0] + bias[2])); -- phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_A2, -- MTK_PHY_DA_TX_I2MPB_A_TST_MASK, -- FIELD_PREP(MTK_PHY_DA_TX_I2MPB_A_TST_MASK, -- buf[0] + bias[3])); -- -- phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_B1, -- MTK_PHY_DA_TX_I2MPB_B_GBE_MASK, -- FIELD_PREP(MTK_PHY_DA_TX_I2MPB_B_GBE_MASK, -- buf[1] + bias[4])); -- phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_B1, -- MTK_PHY_DA_TX_I2MPB_B_TBT_MASK, -- FIELD_PREP(MTK_PHY_DA_TX_I2MPB_B_TBT_MASK, -- buf[1] + bias[5])); -- phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_B2, -- MTK_PHY_DA_TX_I2MPB_B_HBT_MASK, -- FIELD_PREP(MTK_PHY_DA_TX_I2MPB_B_HBT_MASK, -- buf[1] + bias[6])); -- phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_B2, -- MTK_PHY_DA_TX_I2MPB_B_TST_MASK, -- FIELD_PREP(MTK_PHY_DA_TX_I2MPB_B_TST_MASK, -- buf[1] + bias[7])); -- -- phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_C1, -- MTK_PHY_DA_TX_I2MPB_C_GBE_MASK, -- FIELD_PREP(MTK_PHY_DA_TX_I2MPB_C_GBE_MASK, -- buf[2] + bias[8])); -- phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_C1, -- MTK_PHY_DA_TX_I2MPB_C_TBT_MASK, -- FIELD_PREP(MTK_PHY_DA_TX_I2MPB_C_TBT_MASK, -- buf[2] + bias[9])); -- phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_C2, -- MTK_PHY_DA_TX_I2MPB_C_HBT_MASK, -- FIELD_PREP(MTK_PHY_DA_TX_I2MPB_C_HBT_MASK, -- buf[2] + bias[10])); -- phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_C2, -- MTK_PHY_DA_TX_I2MPB_C_TST_MASK, -- FIELD_PREP(MTK_PHY_DA_TX_I2MPB_C_TST_MASK, -- buf[2] + bias[11])); -- -- phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_D1, -- MTK_PHY_DA_TX_I2MPB_D_GBE_MASK, -- FIELD_PREP(MTK_PHY_DA_TX_I2MPB_D_GBE_MASK, -- buf[3] + bias[12])); -- phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_D1, -- MTK_PHY_DA_TX_I2MPB_D_TBT_MASK, -- FIELD_PREP(MTK_PHY_DA_TX_I2MPB_D_TBT_MASK, -- buf[3] + bias[13])); -- phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_D2, -- MTK_PHY_DA_TX_I2MPB_D_HBT_MASK, -- FIELD_PREP(MTK_PHY_DA_TX_I2MPB_D_HBT_MASK, -- buf[3] + bias[14])); -- phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_D2, -- MTK_PHY_DA_TX_I2MPB_D_TST_MASK, -- FIELD_PREP(MTK_PHY_DA_TX_I2MPB_D_TST_MASK, -- buf[3] + bias[15])); -- -- return 0; --} -- --static int tx_amp_cal_efuse(struct phy_device *phydev, u32 *buf) --{ -- u16 tx_amp_cal_val[4]; -- -- tx_amp_cal_val[0] = EFS_DA_TX_I2MPB_A(buf[0]); -- tx_amp_cal_val[1] = EFS_DA_TX_I2MPB_B(buf[0]); -- tx_amp_cal_val[2] = EFS_DA_TX_I2MPB_C(buf[0]); -- tx_amp_cal_val[3] = EFS_DA_TX_I2MPB_D(buf[0]); -- tx_amp_fill_result(phydev, tx_amp_cal_val); -- -- return 0; --} -- --static int tx_r50_fill_result(struct phy_device *phydev, u16 tx_r50_cal_val, -- u8 txg_calen_x) --{ -- int bias = 0; -- u16 reg, val; -- -- if (phydev->drv->phy_id == MTK_GPHY_ID_MT7988) -- bias = -1; -- -- val = clamp_val(bias + tx_r50_cal_val, 0, 63); -- -- switch (txg_calen_x) { -- case PAIR_A: -- reg = MTK_PHY_DA_TX_R50_PAIR_A; -- break; -- case PAIR_B: -- reg = MTK_PHY_DA_TX_R50_PAIR_B; -- break; -- case PAIR_C: -- reg = MTK_PHY_DA_TX_R50_PAIR_C; -- break; -- case PAIR_D: -- reg = MTK_PHY_DA_TX_R50_PAIR_D; -- break; -- default: -- return -EINVAL; -- } -- -- phy_write_mmd(phydev, MDIO_MMD_VEND1, reg, val | val << 8); -- -- return 0; --} -- --static int tx_r50_cal_efuse(struct phy_device *phydev, u32 *buf, -- u8 txg_calen_x) --{ -- u16 tx_r50_cal_val; -- -- switch (txg_calen_x) { -- case PAIR_A: -- tx_r50_cal_val = EFS_DA_TX_R50_A(buf[1]); -- break; -- case PAIR_B: -- tx_r50_cal_val = EFS_DA_TX_R50_B(buf[1]); -- break; -- case PAIR_C: -- tx_r50_cal_val = EFS_DA_TX_R50_C(buf[2]); -- break; -- case PAIR_D: -- tx_r50_cal_val = EFS_DA_TX_R50_D(buf[2]); -- break; -- default: -- return -EINVAL; -- } -- tx_r50_fill_result(phydev, tx_r50_cal_val, txg_calen_x); -- -- return 0; --} -- --static int tx_vcm_cal_sw(struct phy_device *phydev, u8 rg_txreserve_x) --{ -- u8 lower_idx, upper_idx, txreserve_val; -- u8 lower_ret, upper_ret; -- int ret; -- -- phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0, -- MTK_PHY_RG_ANA_CALEN); -- phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0, -- MTK_PHY_RG_CAL_CKINV); -- phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG1, -- MTK_PHY_RG_TXVOS_CALEN); -- -- switch (rg_txreserve_x) { -- case PAIR_A: -- phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, -- MTK_PHY_RG_DASN_DAC_IN0_A, -- MTK_PHY_DASN_DAC_IN0_A_MASK); -- phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, -- MTK_PHY_RG_DASN_DAC_IN1_A, -- MTK_PHY_DASN_DAC_IN1_A_MASK); -- phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, -- MTK_PHY_RG_ANA_CAL_RG0, -- MTK_PHY_RG_ZCALEN_A); -- break; -- case PAIR_B: -- phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, -- MTK_PHY_RG_DASN_DAC_IN0_B, -- MTK_PHY_DASN_DAC_IN0_B_MASK); -- phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, -- MTK_PHY_RG_DASN_DAC_IN1_B, -- MTK_PHY_DASN_DAC_IN1_B_MASK); -- phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, -- MTK_PHY_RG_ANA_CAL_RG1, -- MTK_PHY_RG_ZCALEN_B); -- break; -- case PAIR_C: -- phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, -- MTK_PHY_RG_DASN_DAC_IN0_C, -- MTK_PHY_DASN_DAC_IN0_C_MASK); -- phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, -- MTK_PHY_RG_DASN_DAC_IN1_C, -- MTK_PHY_DASN_DAC_IN1_C_MASK); -- phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, -- MTK_PHY_RG_ANA_CAL_RG1, -- MTK_PHY_RG_ZCALEN_C); -- break; -- case PAIR_D: -- phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, -- MTK_PHY_RG_DASN_DAC_IN0_D, -- MTK_PHY_DASN_DAC_IN0_D_MASK); -- phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, -- MTK_PHY_RG_DASN_DAC_IN1_D, -- MTK_PHY_DASN_DAC_IN1_D_MASK); -- phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, -- MTK_PHY_RG_ANA_CAL_RG1, -- MTK_PHY_RG_ZCALEN_D); -- break; -- default: -- ret = -EINVAL; -- goto restore; -- } -- -- lower_idx = TXRESERVE_MIN; -- upper_idx = TXRESERVE_MAX; -- -- phydev_dbg(phydev, "Start TX-VCM SW cal.\n"); -- while ((upper_idx - lower_idx) > 1) { -- txreserve_val = DIV_ROUND_CLOSEST(lower_idx + upper_idx, 2); -- ret = cal_cycle(phydev, MDIO_MMD_VEND1, MTK_PHY_RXADC_CTRL_RG9, -- MTK_PHY_DA_RX_PSBN_TBT_MASK | -- MTK_PHY_DA_RX_PSBN_HBT_MASK | -- MTK_PHY_DA_RX_PSBN_GBE_MASK | -- MTK_PHY_DA_RX_PSBN_LP_MASK, -- txreserve_val << 12 | txreserve_val << 8 | -- txreserve_val << 4 | txreserve_val); -- if (ret == 1) { -- upper_idx = txreserve_val; -- upper_ret = ret; -- } else if (ret == 0) { -- lower_idx = txreserve_val; -- lower_ret = ret; -- } else { -- goto restore; -- } -- } -- -- if (lower_idx == TXRESERVE_MIN) { -- lower_ret = cal_cycle(phydev, MDIO_MMD_VEND1, -- MTK_PHY_RXADC_CTRL_RG9, -- MTK_PHY_DA_RX_PSBN_TBT_MASK | -- MTK_PHY_DA_RX_PSBN_HBT_MASK | -- MTK_PHY_DA_RX_PSBN_GBE_MASK | -- MTK_PHY_DA_RX_PSBN_LP_MASK, -- lower_idx << 12 | lower_idx << 8 | -- lower_idx << 4 | lower_idx); -- ret = lower_ret; -- } else if (upper_idx == TXRESERVE_MAX) { -- upper_ret = cal_cycle(phydev, MDIO_MMD_VEND1, -- MTK_PHY_RXADC_CTRL_RG9, -- MTK_PHY_DA_RX_PSBN_TBT_MASK | -- MTK_PHY_DA_RX_PSBN_HBT_MASK | -- MTK_PHY_DA_RX_PSBN_GBE_MASK | -- MTK_PHY_DA_RX_PSBN_LP_MASK, -- upper_idx << 12 | upper_idx << 8 | -- upper_idx << 4 | upper_idx); -- ret = upper_ret; -- } -- if (ret < 0) -- goto restore; -- -- /* We calibrate TX-VCM in different logic. Check upper index and then -- * lower index. If this calibration is valid, apply lower index's -- * result. -- */ -- ret = upper_ret - lower_ret; -- if (ret == 1) { -- ret = 0; -- /* Make sure we use upper_idx in our calibration system */ -- cal_cycle(phydev, MDIO_MMD_VEND1, MTK_PHY_RXADC_CTRL_RG9, -- MTK_PHY_DA_RX_PSBN_TBT_MASK | -- MTK_PHY_DA_RX_PSBN_HBT_MASK | -- MTK_PHY_DA_RX_PSBN_GBE_MASK | -- MTK_PHY_DA_RX_PSBN_LP_MASK, -- upper_idx << 12 | upper_idx << 8 | -- upper_idx << 4 | upper_idx); -- phydev_dbg(phydev, "TX-VCM SW cal result: 0x%x\n", upper_idx); -- } else if (lower_idx == TXRESERVE_MIN && upper_ret == 1 && -- lower_ret == 1) { -- ret = 0; -- cal_cycle(phydev, MDIO_MMD_VEND1, MTK_PHY_RXADC_CTRL_RG9, -- MTK_PHY_DA_RX_PSBN_TBT_MASK | -- MTK_PHY_DA_RX_PSBN_HBT_MASK | -- MTK_PHY_DA_RX_PSBN_GBE_MASK | -- MTK_PHY_DA_RX_PSBN_LP_MASK, -- lower_idx << 12 | lower_idx << 8 | -- lower_idx << 4 | lower_idx); -- phydev_warn(phydev, "TX-VCM SW cal result at low margin 0x%x\n", -- lower_idx); -- } else if (upper_idx == TXRESERVE_MAX && upper_ret == 0 && -- lower_ret == 0) { -- ret = 0; -- phydev_warn(phydev, -- "TX-VCM SW cal result at high margin 0x%x\n", -- upper_idx); -- } else { -- ret = -EINVAL; -- } -- --restore: -- phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0, -- MTK_PHY_RG_ANA_CALEN); -- phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG1, -- MTK_PHY_RG_TXVOS_CALEN); -- phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0, -- MTK_PHY_RG_ZCALEN_A); -- phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG1, -- MTK_PHY_RG_ZCALEN_B | MTK_PHY_RG_ZCALEN_C | -- MTK_PHY_RG_ZCALEN_D); -- -- return ret; --} -- --static void mt798x_phy_common_finetune(struct phy_device *phydev) --{ -- phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5); -- /* SlvDSPreadyTime = 24, MasDSPreadyTime = 24 */ -- __phy_write(phydev, 0x11, 0xc71); -- __phy_write(phydev, 0x12, 0xc); -- __phy_write(phydev, 0x10, 0x8fae); -- -- /* EnabRandUpdTrig = 1 */ -- __phy_write(phydev, 0x11, 0x2f00); -- __phy_write(phydev, 0x12, 0xe); -- __phy_write(phydev, 0x10, 0x8fb0); -- -- /* NormMseLoThresh = 85 */ -- __phy_write(phydev, 0x11, 0x55a0); -- __phy_write(phydev, 0x12, 0x0); -- __phy_write(phydev, 0x10, 0x83aa); -- -- /* FfeUpdGainForce = 1(Enable), FfeUpdGainForceVal = 4 */ -- __phy_write(phydev, 0x11, 0x240); -- __phy_write(phydev, 0x12, 0x0); -- __phy_write(phydev, 0x10, 0x9680); -- -- /* TrFreeze = 0 (mt7988 default) */ -- __phy_write(phydev, 0x11, 0x0); -- __phy_write(phydev, 0x12, 0x0); -- __phy_write(phydev, 0x10, 0x9686); -- -- /* SSTrKp100 = 5 */ -- /* SSTrKf100 = 6 */ -- /* SSTrKp1000Mas = 5 */ -- /* SSTrKf1000Mas = 6 */ -- /* SSTrKp1000Slv = 5 */ -- /* SSTrKf1000Slv = 6 */ -- __phy_write(phydev, 0x11, 0xbaef); -- __phy_write(phydev, 0x12, 0x2e); -- __phy_write(phydev, 0x10, 0x968c); -- phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0); --} -- --static void mt7981_phy_finetune(struct phy_device *phydev) --{ -- u16 val[8] = { 0x01ce, 0x01c1, -- 0x020f, 0x0202, -- 0x03d0, 0x03c0, -- 0x0013, 0x0005 }; -- int i, k; -- -- /* 100M eye finetune: -- * Keep middle level of TX MLT3 shapper as default. -- * Only change TX MLT3 overshoot level here. -- */ -- for (k = 0, i = 1; i < 12; i++) { -- if (i % 3 == 0) -- continue; -- phy_write_mmd(phydev, MDIO_MMD_VEND1, i, val[k++]); -- } -- -- phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5); -- /* ResetSyncOffset = 6 */ -- __phy_write(phydev, 0x11, 0x600); -- __phy_write(phydev, 0x12, 0x0); -- __phy_write(phydev, 0x10, 0x8fc0); -- -- /* VgaDecRate = 1 */ -- __phy_write(phydev, 0x11, 0x4c2a); -- __phy_write(phydev, 0x12, 0x3e); -- __phy_write(phydev, 0x10, 0x8fa4); -- -- /* MrvlTrFix100Kp = 3, MrvlTrFix100Kf = 2, -- * MrvlTrFix1000Kp = 3, MrvlTrFix1000Kf = 2 -- */ -- __phy_write(phydev, 0x11, 0xd10a); -- __phy_write(phydev, 0x12, 0x34); -- __phy_write(phydev, 0x10, 0x8f82); -- -- /* VcoSlicerThreshBitsHigh */ -- __phy_write(phydev, 0x11, 0x5555); -- __phy_write(phydev, 0x12, 0x55); -- __phy_write(phydev, 0x10, 0x8ec0); -- phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0); -- -- /* TR_OPEN_LOOP_EN = 1, lpf_x_average = 9 */ -- phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG234, -- MTK_PHY_TR_OPEN_LOOP_EN_MASK | -- MTK_PHY_LPF_X_AVERAGE_MASK, -- BIT(0) | FIELD_PREP(MTK_PHY_LPF_X_AVERAGE_MASK, 0x9)); -- -- /* rg_tr_lpf_cnt_val = 512 */ -- phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LPF_CNT_VAL, 0x200); -- -- /* IIR2 related */ -- phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K1_L, 0x82); -- phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K1_U, 0x0); -- phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K2_L, 0x103); -- phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K2_U, 0x0); -- phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K3_L, 0x82); -- phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K3_U, 0x0); -- phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K4_L, 0xd177); -- phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K4_U, 0x3); -- phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K5_L, 0x2c82); -- phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K5_U, 0xe); -- -- /* FFE peaking */ -- phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG27C, -- MTK_PHY_VGASTATE_FFE_THR_ST1_MASK, 0x1b << 8); -- phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG27D, -- MTK_PHY_VGASTATE_FFE_THR_ST2_MASK, 0x1e); -- -- /* Disable LDO pump */ -- phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_LDO_PUMP_EN_PAIRAB, 0x0); -- phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_LDO_PUMP_EN_PAIRCD, 0x0); -- /* Adjust LDO output voltage */ -- phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_LDO_OUTPUT_V, 0x2222); --} -- --static void mt7988_phy_finetune(struct phy_device *phydev) --{ -- u16 val[12] = { 0x0187, 0x01cd, 0x01c8, 0x0182, -- 0x020d, 0x0206, 0x0384, 0x03d0, -- 0x03c6, 0x030a, 0x0011, 0x0005 }; -- int i; -- -- /* Set default MLT3 shaper first */ -- for (i = 0; i < 12; i++) -- phy_write_mmd(phydev, MDIO_MMD_VEND1, i, val[i]); -- -- /* TCT finetune */ -- phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_TX_FILTER, 0x5); -- -- phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5); -- /* ResetSyncOffset = 5 */ -- __phy_write(phydev, 0x11, 0x500); -- __phy_write(phydev, 0x12, 0x0); -- __phy_write(phydev, 0x10, 0x8fc0); -- -- /* VgaDecRate is 1 at default on mt7988 */ -- -- /* MrvlTrFix100Kp = 6, MrvlTrFix100Kf = 7, -- * MrvlTrFix1000Kp = 6, MrvlTrFix1000Kf = 7 -- */ -- __phy_write(phydev, 0x11, 0xb90a); -- __phy_write(phydev, 0x12, 0x6f); -- __phy_write(phydev, 0x10, 0x8f82); -- -- /* RemAckCntLimitCtrl = 1 */ -- __phy_write(phydev, 0x11, 0xfbba); -- __phy_write(phydev, 0x12, 0xc3); -- __phy_write(phydev, 0x10, 0x87f8); -- -- phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0); -- -- /* TR_OPEN_LOOP_EN = 1, lpf_x_average = 10 */ -- phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG234, -- MTK_PHY_TR_OPEN_LOOP_EN_MASK | -- MTK_PHY_LPF_X_AVERAGE_MASK, -- BIT(0) | FIELD_PREP(MTK_PHY_LPF_X_AVERAGE_MASK, 0xa)); -- -- /* rg_tr_lpf_cnt_val = 1023 */ -- phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LPF_CNT_VAL, 0x3ff); --} -- --static void mt798x_phy_eee(struct phy_device *phydev) --{ -- phy_modify_mmd(phydev, MDIO_MMD_VEND1, -- MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG120, -- MTK_PHY_LPI_SIG_EN_LO_THRESH1000_MASK | -- MTK_PHY_LPI_SIG_EN_HI_THRESH1000_MASK, -- FIELD_PREP(MTK_PHY_LPI_SIG_EN_LO_THRESH1000_MASK, 0x0) | -- FIELD_PREP(MTK_PHY_LPI_SIG_EN_HI_THRESH1000_MASK, 0x14)); -- -- phy_modify_mmd(phydev, MDIO_MMD_VEND1, -- MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG122, -- MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK, -- FIELD_PREP(MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK, -- 0xff)); -- -- phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, -- MTK_PHY_RG_TESTMUX_ADC_CTRL, -- MTK_PHY_RG_TXEN_DIG_MASK); -- -- phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, -- MTK_PHY_RG_DEV1E_REG19b, MTK_PHY_BYPASS_DSP_LPI_READY); -- -- phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, -- MTK_PHY_RG_DEV1E_REG234, MTK_PHY_TR_LP_IIR_EEE_EN); -- -- phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG238, -- MTK_PHY_LPI_SLV_SEND_TX_TIMER_MASK | -- MTK_PHY_LPI_SLV_SEND_TX_EN, -- FIELD_PREP(MTK_PHY_LPI_SLV_SEND_TX_TIMER_MASK, 0x120)); -- -- /* Keep MTK_PHY_LPI_SEND_LOC_TIMER as 375 */ -- phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG239, -- MTK_PHY_LPI_TXPCS_LOC_RCV); -- -- /* This also fixes some IoT issues, such as CH340 */ -- phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG2C7, -- MTK_PHY_MAX_GAIN_MASK | MTK_PHY_MIN_GAIN_MASK, -- FIELD_PREP(MTK_PHY_MAX_GAIN_MASK, 0x8) | -- FIELD_PREP(MTK_PHY_MIN_GAIN_MASK, 0x13)); -- -- phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG2D1, -- MTK_PHY_VCO_SLICER_THRESH_BITS_HIGH_EEE_MASK, -- FIELD_PREP(MTK_PHY_VCO_SLICER_THRESH_BITS_HIGH_EEE_MASK, -- 0x33) | -- MTK_PHY_LPI_SKIP_SD_SLV_TR | MTK_PHY_LPI_TR_READY | -- MTK_PHY_LPI_VCO_EEE_STG0_EN); -- -- phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG323, -- MTK_PHY_EEE_WAKE_MAS_INT_DC | -- MTK_PHY_EEE_WAKE_SLV_INT_DC); -- -- phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG324, -- MTK_PHY_SMI_DETCNT_MAX_MASK, -- FIELD_PREP(MTK_PHY_SMI_DETCNT_MAX_MASK, 0x3f) | -- MTK_PHY_SMI_DET_MAX_EN); -- -- phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG326, -- MTK_PHY_LPI_MODE_SD_ON | MTK_PHY_RESET_RANDUPD_CNT | -- MTK_PHY_TREC_UPDATE_ENAB_CLR | -- MTK_PHY_LPI_QUIT_WAIT_DFE_SIG_DET_OFF | -- MTK_PHY_TR_READY_SKIP_AFE_WAKEUP); -- -- phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5); -- /* Regsigdet_sel_1000 = 0 */ -- __phy_write(phydev, 0x11, 0xb); -- __phy_write(phydev, 0x12, 0x0); -- __phy_write(phydev, 0x10, 0x9690); -- -- /* REG_EEE_st2TrKf1000 = 2 */ -- __phy_write(phydev, 0x11, 0x114f); -- __phy_write(phydev, 0x12, 0x2); -- __phy_write(phydev, 0x10, 0x969a); -- -- /* RegEEE_slv_wake_tr_timer_tar = 6, RegEEE_slv_remtx_timer_tar = 20 */ -- __phy_write(phydev, 0x11, 0x3028); -- __phy_write(phydev, 0x12, 0x0); -- __phy_write(phydev, 0x10, 0x969e); -- -- /* RegEEE_slv_wake_int_timer_tar = 8 */ -- __phy_write(phydev, 0x11, 0x5010); -- __phy_write(phydev, 0x12, 0x0); -- __phy_write(phydev, 0x10, 0x96a0); -- -- /* RegEEE_trfreeze_timer2 = 586 */ -- __phy_write(phydev, 0x11, 0x24a); -- __phy_write(phydev, 0x12, 0x0); -- __phy_write(phydev, 0x10, 0x96a8); -- -- /* RegEEE100Stg1_tar = 16 */ -- __phy_write(phydev, 0x11, 0x3210); -- __phy_write(phydev, 0x12, 0x0); -- __phy_write(phydev, 0x10, 0x96b8); -- -- /* REGEEE_wake_slv_tr_wait_dfesigdet_en = 0 */ -- __phy_write(phydev, 0x11, 0x1463); -- __phy_write(phydev, 0x12, 0x0); -- __phy_write(phydev, 0x10, 0x96ca); -- -- /* DfeTailEnableVgaThresh1000 = 27 */ -- __phy_write(phydev, 0x11, 0x36); -- __phy_write(phydev, 0x12, 0x0); -- __phy_write(phydev, 0x10, 0x8f80); -- phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0); -- -- phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_3); -- __phy_modify(phydev, MTK_PHY_LPI_REG_14, -- MTK_PHY_LPI_WAKE_TIMER_1000_MASK, -- FIELD_PREP(MTK_PHY_LPI_WAKE_TIMER_1000_MASK, 0x19c)); -- -- __phy_modify(phydev, MTK_PHY_LPI_REG_1c, MTK_PHY_SMI_DET_ON_THRESH_MASK, -- FIELD_PREP(MTK_PHY_SMI_DET_ON_THRESH_MASK, 0xc)); -- phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0); -- -- phy_modify_mmd(phydev, MDIO_MMD_VEND1, -- MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG122, -- MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK, -- FIELD_PREP(MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK, -- 0xff)); --} -- --static int cal_sw(struct phy_device *phydev, enum CAL_ITEM cal_item, -- u8 start_pair, u8 end_pair) --{ -- u8 pair_n; -- int ret; -- -- for (pair_n = start_pair; pair_n <= end_pair; pair_n++) { -- /* TX_OFFSET & TX_AMP have no SW calibration. */ -- switch (cal_item) { -- case TX_VCM: -- ret = tx_vcm_cal_sw(phydev, pair_n); -- break; -- default: -- return -EINVAL; -- } -- if (ret) -- return ret; -- } -- return 0; --} -- --static int cal_efuse(struct phy_device *phydev, enum CAL_ITEM cal_item, -- u8 start_pair, u8 end_pair, u32 *buf) --{ -- u8 pair_n; -- int ret; -- -- for (pair_n = start_pair; pair_n <= end_pair; pair_n++) { -- /* TX_VCM has no efuse calibration. */ -- switch (cal_item) { -- case REXT: -- ret = rext_cal_efuse(phydev, buf); -- break; -- case TX_OFFSET: -- ret = tx_offset_cal_efuse(phydev, buf); -- break; -- case TX_AMP: -- ret = tx_amp_cal_efuse(phydev, buf); -- break; -- case TX_R50: -- ret = tx_r50_cal_efuse(phydev, buf, pair_n); -- break; -- default: -- return -EINVAL; -- } -- if (ret) -- return ret; -- } -- -- return 0; --} -- --static int start_cal(struct phy_device *phydev, enum CAL_ITEM cal_item, -- enum CAL_MODE cal_mode, u8 start_pair, -- u8 end_pair, u32 *buf) --{ -- int ret; -- -- switch (cal_mode) { -- case EFUSE_M: -- ret = cal_efuse(phydev, cal_item, start_pair, -- end_pair, buf); -- break; -- case SW_M: -- ret = cal_sw(phydev, cal_item, start_pair, end_pair); -- break; -- default: -- return -EINVAL; -- } -- -- if (ret) { -- phydev_err(phydev, "cal %d failed\n", cal_item); -- return -EIO; -- } -- -- return 0; --} -- --static int mt798x_phy_calibration(struct phy_device *phydev) --{ -- struct nvmem_cell *cell; -- int ret = 0; -- size_t len; -- u32 *buf; -- -- cell = nvmem_cell_get(&phydev->mdio.dev, "phy-cal-data"); -- if (IS_ERR(cell)) { -- if (PTR_ERR(cell) == -EPROBE_DEFER) -- return PTR_ERR(cell); -- return 0; -- } -- -- buf = (u32 *)nvmem_cell_read(cell, &len); -- nvmem_cell_put(cell); -- if (IS_ERR(buf)) -- return PTR_ERR(buf); -- -- if (!buf[0] || !buf[1] || !buf[2] || !buf[3] || len < 4 * sizeof(u32)) { -- phydev_err(phydev, "invalid efuse data\n"); -- ret = -EINVAL; -- goto out; -- } -- -- ret = start_cal(phydev, REXT, EFUSE_M, NO_PAIR, NO_PAIR, buf); -- if (ret) -- goto out; -- ret = start_cal(phydev, TX_OFFSET, EFUSE_M, NO_PAIR, NO_PAIR, buf); -- if (ret) -- goto out; -- ret = start_cal(phydev, TX_AMP, EFUSE_M, NO_PAIR, NO_PAIR, buf); -- if (ret) -- goto out; -- ret = start_cal(phydev, TX_R50, EFUSE_M, PAIR_A, PAIR_D, buf); -- if (ret) -- goto out; -- ret = start_cal(phydev, TX_VCM, SW_M, PAIR_A, PAIR_A, buf); -- if (ret) -- goto out; -- --out: -- kfree(buf); -- return ret; --} -- --static int mt798x_phy_config_init(struct phy_device *phydev) --{ -- switch (phydev->drv->phy_id) { -- case MTK_GPHY_ID_MT7981: -- mt7981_phy_finetune(phydev); -- break; -- case MTK_GPHY_ID_MT7988: -- mt7988_phy_finetune(phydev); -- break; -- } -- -- mt798x_phy_common_finetune(phydev); -- mt798x_phy_eee(phydev); -- -- return mt798x_phy_calibration(phydev); --} -- --static int mt798x_phy_hw_led_on_set(struct phy_device *phydev, u8 index, -- bool on) --{ -- unsigned int bit_on = MTK_PHY_LED_STATE_FORCE_ON + (index ? 16 : 0); -- struct mtk_socphy_priv *priv = phydev->priv; -- bool changed; -- -- if (on) -- changed = !test_and_set_bit(bit_on, &priv->led_state); -- else -- changed = !!test_and_clear_bit(bit_on, &priv->led_state); -- -- changed |= !!test_and_clear_bit(MTK_PHY_LED_STATE_NETDEV + -- (index ? 16 : 0), &priv->led_state); -- if (changed) -- return phy_modify_mmd(phydev, MDIO_MMD_VEND2, index ? -- MTK_PHY_LED1_ON_CTRL : -- MTK_PHY_LED0_ON_CTRL, -- MTK_PHY_LED_ON_MASK, -- on ? MTK_PHY_LED_ON_FORCE_ON : 0); -- else -- return 0; --} -- --static int mt798x_phy_hw_led_blink_set(struct phy_device *phydev, u8 index, -- bool blinking) --{ -- unsigned int bit_blink = MTK_PHY_LED_STATE_FORCE_BLINK + -- (index ? 16 : 0); -- struct mtk_socphy_priv *priv = phydev->priv; -- bool changed; -- -- if (blinking) -- changed = !test_and_set_bit(bit_blink, &priv->led_state); -- else -- changed = !!test_and_clear_bit(bit_blink, &priv->led_state); -- -- changed |= !!test_bit(MTK_PHY_LED_STATE_NETDEV + -- (index ? 16 : 0), &priv->led_state); -- if (changed) -- return phy_write_mmd(phydev, MDIO_MMD_VEND2, index ? -- MTK_PHY_LED1_BLINK_CTRL : -- MTK_PHY_LED0_BLINK_CTRL, -- blinking ? -- MTK_PHY_LED_BLINK_FORCE_BLINK : 0); -- else -- return 0; --} -- --static int mt798x_phy_led_blink_set(struct phy_device *phydev, u8 index, -- unsigned long *delay_on, -- unsigned long *delay_off) --{ -- bool blinking = false; -- int err = 0; -- -- if (index > 1) -- return -EINVAL; -- -- if (delay_on && delay_off && (*delay_on > 0) && (*delay_off > 0)) { -- blinking = true; -- *delay_on = 50; -- *delay_off = 50; -- } -- -- err = mt798x_phy_hw_led_blink_set(phydev, index, blinking); -- if (err) -- return err; -- -- return mt798x_phy_hw_led_on_set(phydev, index, false); --} -- --static int mt798x_phy_led_brightness_set(struct phy_device *phydev, -- u8 index, enum led_brightness value) --{ -- int err; -- -- err = mt798x_phy_hw_led_blink_set(phydev, index, false); -- if (err) -- return err; -- -- return mt798x_phy_hw_led_on_set(phydev, index, (value != LED_OFF)); --} -- --static const unsigned long supported_triggers = -- BIT(TRIGGER_NETDEV_FULL_DUPLEX) | -- BIT(TRIGGER_NETDEV_HALF_DUPLEX) | -- BIT(TRIGGER_NETDEV_LINK) | -- BIT(TRIGGER_NETDEV_LINK_10) | -- BIT(TRIGGER_NETDEV_LINK_100) | -- BIT(TRIGGER_NETDEV_LINK_1000) | -- BIT(TRIGGER_NETDEV_RX) | -- BIT(TRIGGER_NETDEV_TX); -- --static int mt798x_phy_led_hw_is_supported(struct phy_device *phydev, u8 index, -- unsigned long rules) --{ -- if (index > 1) -- return -EINVAL; -- -- /* All combinations of the supported triggers are allowed */ -- if (rules & ~supported_triggers) -- return -EOPNOTSUPP; -- -- return 0; --}; -- --static int mt798x_phy_led_hw_control_get(struct phy_device *phydev, u8 index, -- unsigned long *rules) --{ -- unsigned int bit_blink = MTK_PHY_LED_STATE_FORCE_BLINK + -- (index ? 16 : 0); -- unsigned int bit_netdev = MTK_PHY_LED_STATE_NETDEV + (index ? 16 : 0); -- unsigned int bit_on = MTK_PHY_LED_STATE_FORCE_ON + (index ? 16 : 0); -- struct mtk_socphy_priv *priv = phydev->priv; -- int on, blink; -- -- if (index > 1) -- return -EINVAL; -- -- on = phy_read_mmd(phydev, MDIO_MMD_VEND2, -- index ? MTK_PHY_LED1_ON_CTRL : MTK_PHY_LED0_ON_CTRL); -- -- if (on < 0) -- return -EIO; -- -- blink = phy_read_mmd(phydev, MDIO_MMD_VEND2, -- index ? MTK_PHY_LED1_BLINK_CTRL : -- MTK_PHY_LED0_BLINK_CTRL); -- if (blink < 0) -- return -EIO; -- -- if ((on & (MTK_PHY_LED_ON_LINK | MTK_PHY_LED_ON_FDX | -- MTK_PHY_LED_ON_HDX | MTK_PHY_LED_ON_LINKDOWN)) || -- (blink & (MTK_PHY_LED_BLINK_RX | MTK_PHY_LED_BLINK_TX))) -- set_bit(bit_netdev, &priv->led_state); -- else -- clear_bit(bit_netdev, &priv->led_state); -- -- if (on & MTK_PHY_LED_ON_FORCE_ON) -- set_bit(bit_on, &priv->led_state); -- else -- clear_bit(bit_on, &priv->led_state); -- -- if (blink & MTK_PHY_LED_BLINK_FORCE_BLINK) -- set_bit(bit_blink, &priv->led_state); -- else -- clear_bit(bit_blink, &priv->led_state); -- -- if (!rules) -- return 0; -- -- if (on & MTK_PHY_LED_ON_LINK) -- *rules |= BIT(TRIGGER_NETDEV_LINK); -- -- if (on & MTK_PHY_LED_ON_LINK10) -- *rules |= BIT(TRIGGER_NETDEV_LINK_10); -- -- if (on & MTK_PHY_LED_ON_LINK100) -- *rules |= BIT(TRIGGER_NETDEV_LINK_100); -- -- if (on & MTK_PHY_LED_ON_LINK1000) -- *rules |= BIT(TRIGGER_NETDEV_LINK_1000); -- -- if (on & MTK_PHY_LED_ON_FDX) -- *rules |= BIT(TRIGGER_NETDEV_FULL_DUPLEX); -- -- if (on & MTK_PHY_LED_ON_HDX) -- *rules |= BIT(TRIGGER_NETDEV_HALF_DUPLEX); -- -- if (blink & MTK_PHY_LED_BLINK_RX) -- *rules |= BIT(TRIGGER_NETDEV_RX); -- -- if (blink & MTK_PHY_LED_BLINK_TX) -- *rules |= BIT(TRIGGER_NETDEV_TX); -- -- return 0; --}; -- --static int mt798x_phy_led_hw_control_set(struct phy_device *phydev, u8 index, -- unsigned long rules) --{ -- unsigned int bit_netdev = MTK_PHY_LED_STATE_NETDEV + (index ? 16 : 0); -- struct mtk_socphy_priv *priv = phydev->priv; -- u16 on = 0, blink = 0; -- int ret; -- -- if (index > 1) -- return -EINVAL; -- -- if (rules & BIT(TRIGGER_NETDEV_FULL_DUPLEX)) -- on |= MTK_PHY_LED_ON_FDX; -- -- if (rules & BIT(TRIGGER_NETDEV_HALF_DUPLEX)) -- on |= MTK_PHY_LED_ON_HDX; -- -- if (rules & (BIT(TRIGGER_NETDEV_LINK_10) | BIT(TRIGGER_NETDEV_LINK))) -- on |= MTK_PHY_LED_ON_LINK10; -- -- if (rules & (BIT(TRIGGER_NETDEV_LINK_100) | BIT(TRIGGER_NETDEV_LINK))) -- on |= MTK_PHY_LED_ON_LINK100; -- -- if (rules & (BIT(TRIGGER_NETDEV_LINK_1000) | BIT(TRIGGER_NETDEV_LINK))) -- on |= MTK_PHY_LED_ON_LINK1000; -- -- if (rules & BIT(TRIGGER_NETDEV_RX)) { -- blink |= (on & MTK_PHY_LED_ON_LINK) ? -- (((on & MTK_PHY_LED_ON_LINK10) ? -- MTK_PHY_LED_BLINK_10RX : 0) | -- ((on & MTK_PHY_LED_ON_LINK100) ? -- MTK_PHY_LED_BLINK_100RX : 0) | -- ((on & MTK_PHY_LED_ON_LINK1000) ? -- MTK_PHY_LED_BLINK_1000RX : 0)) : -- MTK_PHY_LED_BLINK_RX; -- } -- -- if (rules & BIT(TRIGGER_NETDEV_TX)) { -- blink |= (on & MTK_PHY_LED_ON_LINK) ? -- (((on & MTK_PHY_LED_ON_LINK10) ? -- MTK_PHY_LED_BLINK_10TX : 0) | -- ((on & MTK_PHY_LED_ON_LINK100) ? -- MTK_PHY_LED_BLINK_100TX : 0) | -- ((on & MTK_PHY_LED_ON_LINK1000) ? -- MTK_PHY_LED_BLINK_1000TX : 0)) : -- MTK_PHY_LED_BLINK_TX; -- } -- -- if (blink || on) -- set_bit(bit_netdev, &priv->led_state); -- else -- clear_bit(bit_netdev, &priv->led_state); -- -- ret = phy_modify_mmd(phydev, MDIO_MMD_VEND2, index ? -- MTK_PHY_LED1_ON_CTRL : -- MTK_PHY_LED0_ON_CTRL, -- MTK_PHY_LED_ON_FDX | -- MTK_PHY_LED_ON_HDX | -- MTK_PHY_LED_ON_LINK, -- on); -- -- if (ret) -- return ret; -- -- return phy_write_mmd(phydev, MDIO_MMD_VEND2, index ? -- MTK_PHY_LED1_BLINK_CTRL : -- MTK_PHY_LED0_BLINK_CTRL, blink); --}; -- --static bool mt7988_phy_led_get_polarity(struct phy_device *phydev, int led_num) --{ -- struct mtk_socphy_shared *priv = phydev->shared->priv; -- u32 polarities; -- -- if (led_num == 0) -- polarities = ~(priv->boottrap); -- else -- polarities = MTK_PHY_LED1_DEFAULT_POLARITIES; -- -- if (polarities & BIT(phydev->mdio.addr)) -- return true; -- -- return false; --} -- --static int mt7988_phy_fix_leds_polarities(struct phy_device *phydev) --{ -- struct pinctrl *pinctrl; -- int index; -- -- /* Setup LED polarity according to bootstrap use of LED pins */ -- for (index = 0; index < 2; ++index) -- phy_modify_mmd(phydev, MDIO_MMD_VEND2, index ? -- MTK_PHY_LED1_ON_CTRL : MTK_PHY_LED0_ON_CTRL, -- MTK_PHY_LED_ON_POLARITY, -- mt7988_phy_led_get_polarity(phydev, index) ? -- MTK_PHY_LED_ON_POLARITY : 0); -- -- /* Only now setup pinctrl to avoid bogus blinking */ -- pinctrl = devm_pinctrl_get_select(&phydev->mdio.dev, "gbe-led"); -- if (IS_ERR(pinctrl)) -- dev_err(&phydev->mdio.bus->dev, -- "Failed to setup PHY LED pinctrl\n"); -- -- return 0; --} -- --static int mt7988_phy_probe_shared(struct phy_device *phydev) --{ -- struct device_node *np = dev_of_node(&phydev->mdio.bus->dev); -- struct mtk_socphy_shared *shared = phydev->shared->priv; -- struct regmap *regmap; -- u32 reg; -- int ret; -- -- /* The LED0 of the 4 PHYs in MT7988 are wired to SoC pins LED_A, LED_B, -- * LED_C and LED_D respectively. At the same time those pins are used to -- * bootstrap configuration of the reference clock source (LED_A), -- * DRAM DDRx16b x2/x1 (LED_B) and boot device (LED_C, LED_D). -- * In practice this is done using a LED and a resistor pulling the pin -- * either to GND or to VIO. -- * The detected value at boot time is accessible at run-time using the -- * TPBANK0 register located in the gpio base of the pinctrl, in order -- * to read it here it needs to be referenced by a phandle called -- * 'mediatek,pio' in the MDIO bus hosting the PHY. -- * The 4 bits in TPBANK0 are kept as package shared data and are used to -- * set LED polarity for each of the LED0. -- */ -- regmap = syscon_regmap_lookup_by_phandle(np, "mediatek,pio"); -- if (IS_ERR(regmap)) -- return PTR_ERR(regmap); -- -- ret = regmap_read(regmap, RG_GPIO_MISC_TPBANK0, ®); -- if (ret) -- return ret; -- -- shared->boottrap = FIELD_GET(RG_GPIO_MISC_TPBANK0_BOOTMODE, reg); -- -- return 0; --} -- --static void mt798x_phy_leds_state_init(struct phy_device *phydev) --{ -- int i; -- -- for (i = 0; i < 2; ++i) -- mt798x_phy_led_hw_control_get(phydev, i, NULL); --} -- --static int mt7988_phy_probe(struct phy_device *phydev) --{ -- struct mtk_socphy_shared *shared; -- struct mtk_socphy_priv *priv; -- int err; -- -- if (phydev->mdio.addr > 3) -- return -EINVAL; -- -- err = devm_phy_package_join(&phydev->mdio.dev, phydev, 0, -- sizeof(struct mtk_socphy_shared)); -- if (err) -- return err; -- -- if (phy_package_probe_once(phydev)) { -- err = mt7988_phy_probe_shared(phydev); -- if (err) -- return err; -- } -- -- shared = phydev->shared->priv; -- priv = &shared->priv[phydev->mdio.addr]; -- -- phydev->priv = priv; -- -- mt798x_phy_leds_state_init(phydev); -- -- err = mt7988_phy_fix_leds_polarities(phydev); -- if (err) -- return err; -- -- /* Disable TX power saving at probing to: -- * 1. Meet common mode compliance test criteria -- * 2. Make sure that TX-VCM calibration works fine -- */ -- phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RXADC_CTRL_RG7, -- MTK_PHY_DA_AD_BUF_BIAS_LP_MASK, 0x3 << 8); -- -- return mt798x_phy_calibration(phydev); --} -- --static int mt7981_phy_probe(struct phy_device *phydev) --{ -- struct mtk_socphy_priv *priv; -- -- priv = devm_kzalloc(&phydev->mdio.dev, sizeof(struct mtk_socphy_priv), -- GFP_KERNEL); -- if (!priv) -- return -ENOMEM; -- -- phydev->priv = priv; -- -- mt798x_phy_leds_state_init(phydev); -- -- return mt798x_phy_calibration(phydev); --} -- --static struct phy_driver mtk_socphy_driver[] = { -- { -- PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7981), -- .name = "MediaTek MT7981 PHY", -- .config_init = mt798x_phy_config_init, -- .config_intr = genphy_no_config_intr, -- .handle_interrupt = genphy_handle_interrupt_no_ack, -- .probe = mt7981_phy_probe, -- .suspend = genphy_suspend, -- .resume = genphy_resume, -- .read_page = mtk_socphy_read_page, -- .write_page = mtk_socphy_write_page, -- .led_blink_set = mt798x_phy_led_blink_set, -- .led_brightness_set = mt798x_phy_led_brightness_set, -- .led_hw_is_supported = mt798x_phy_led_hw_is_supported, -- .led_hw_control_set = mt798x_phy_led_hw_control_set, -- .led_hw_control_get = mt798x_phy_led_hw_control_get, -- }, -- { -- PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7988), -- .name = "MediaTek MT7988 PHY", -- .config_init = mt798x_phy_config_init, -- .config_intr = genphy_no_config_intr, -- .handle_interrupt = genphy_handle_interrupt_no_ack, -- .probe = mt7988_phy_probe, -- .suspend = genphy_suspend, -- .resume = genphy_resume, -- .read_page = mtk_socphy_read_page, -- .write_page = mtk_socphy_write_page, -- .led_blink_set = mt798x_phy_led_blink_set, -- .led_brightness_set = mt798x_phy_led_brightness_set, -- .led_hw_is_supported = mt798x_phy_led_hw_is_supported, -- .led_hw_control_set = mt798x_phy_led_hw_control_set, -- .led_hw_control_get = mt798x_phy_led_hw_control_get, -- }, --}; -- --module_phy_driver(mtk_socphy_driver); -- --static struct mdio_device_id __maybe_unused mtk_socphy_tbl[] = { -- { PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7981) }, -- { PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7988) }, -- { } --}; -- --MODULE_DESCRIPTION("MediaTek SoC Gigabit Ethernet PHY driver"); --MODULE_AUTHOR("Daniel Golle "); --MODULE_AUTHOR("SkyLake Huang "); --MODULE_LICENSE("GPL"); -- --MODULE_DEVICE_TABLE(mdio, mtk_socphy_tbl); ---- a/drivers/net/phy/mediatek-ge.c -+++ /dev/null -@@ -1,111 +0,0 @@ --// SPDX-License-Identifier: GPL-2.0+ --#include --#include --#include -- --#define MTK_EXT_PAGE_ACCESS 0x1f --#define MTK_PHY_PAGE_STANDARD 0x0000 --#define MTK_PHY_PAGE_EXTENDED 0x0001 --#define MTK_PHY_PAGE_EXTENDED_2 0x0002 --#define MTK_PHY_PAGE_EXTENDED_3 0x0003 --#define MTK_PHY_PAGE_EXTENDED_2A30 0x2a30 --#define MTK_PHY_PAGE_EXTENDED_52B5 0x52b5 -- --static int mtk_gephy_read_page(struct phy_device *phydev) --{ -- return __phy_read(phydev, MTK_EXT_PAGE_ACCESS); --} -- --static int mtk_gephy_write_page(struct phy_device *phydev, int page) --{ -- return __phy_write(phydev, MTK_EXT_PAGE_ACCESS, page); --} -- --static void mtk_gephy_config_init(struct phy_device *phydev) --{ -- /* Enable HW auto downshift */ -- phy_modify_paged(phydev, MTK_PHY_PAGE_EXTENDED, 0x14, 0, BIT(4)); -- -- /* Increase SlvDPSready time */ -- phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5); -- __phy_write(phydev, 0x10, 0xafae); -- __phy_write(phydev, 0x12, 0x2f); -- __phy_write(phydev, 0x10, 0x8fae); -- phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0); -- -- /* Adjust 100_mse_threshold */ -- phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x123, 0xffff); -- -- /* Disable mcc */ -- phy_write_mmd(phydev, MDIO_MMD_VEND1, 0xa6, 0x300); --} -- --static int mt7530_phy_config_init(struct phy_device *phydev) --{ -- mtk_gephy_config_init(phydev); -- -- /* Increase post_update_timer */ -- phy_write_paged(phydev, MTK_PHY_PAGE_EXTENDED_3, 0x11, 0x4b); -- -- return 0; --} -- --static int mt7531_phy_config_init(struct phy_device *phydev) --{ -- mtk_gephy_config_init(phydev); -- -- /* PHY link down power saving enable */ -- phy_set_bits(phydev, 0x17, BIT(4)); -- phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, 0xc6, 0x300); -- -- /* Set TX Pair delay selection */ -- phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x13, 0x404); -- phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x14, 0x404); -- -- return 0; --} -- --static struct phy_driver mtk_gephy_driver[] = { -- { -- PHY_ID_MATCH_EXACT(0x03a29412), -- .name = "MediaTek MT7530 PHY", -- .config_init = mt7530_phy_config_init, -- /* Interrupts are handled by the switch, not the PHY -- * itself. -- */ -- .config_intr = genphy_no_config_intr, -- .handle_interrupt = genphy_handle_interrupt_no_ack, -- .suspend = genphy_suspend, -- .resume = genphy_resume, -- .read_page = mtk_gephy_read_page, -- .write_page = mtk_gephy_write_page, -- }, -- { -- PHY_ID_MATCH_EXACT(0x03a29441), -- .name = "MediaTek MT7531 PHY", -- .config_init = mt7531_phy_config_init, -- /* Interrupts are handled by the switch, not the PHY -- * itself. -- */ -- .config_intr = genphy_no_config_intr, -- .handle_interrupt = genphy_handle_interrupt_no_ack, -- .suspend = genphy_suspend, -- .resume = genphy_resume, -- .read_page = mtk_gephy_read_page, -- .write_page = mtk_gephy_write_page, -- }, --}; -- --module_phy_driver(mtk_gephy_driver); -- --static struct mdio_device_id __maybe_unused mtk_gephy_tbl[] = { -- { PHY_ID_MATCH_EXACT(0x03a29441) }, -- { PHY_ID_MATCH_EXACT(0x03a29412) }, -- { } --}; -- --MODULE_DESCRIPTION("MediaTek Gigabit Ethernet PHY driver"); --MODULE_AUTHOR("DENG, Qingfang "); --MODULE_LICENSE("GPL"); -- --MODULE_DEVICE_TABLE(mdio, mtk_gephy_tbl); ---- /dev/null -+++ b/drivers/net/phy/mediatek/mtk-ge-soc.c -@@ -0,0 +1,1610 @@ -+// SPDX-License-Identifier: GPL-2.0+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define MTK_GPHY_ID_MT7981 0x03a29461 -+#define MTK_GPHY_ID_MT7988 0x03a29481 -+ -+#define MTK_EXT_PAGE_ACCESS 0x1f -+#define MTK_PHY_PAGE_STANDARD 0x0000 -+#define MTK_PHY_PAGE_EXTENDED_3 0x0003 -+ -+#define MTK_PHY_LPI_REG_14 0x14 -+#define MTK_PHY_LPI_WAKE_TIMER_1000_MASK GENMASK(8, 0) -+ -+#define MTK_PHY_LPI_REG_1c 0x1c -+#define MTK_PHY_SMI_DET_ON_THRESH_MASK GENMASK(13, 8) -+ -+#define MTK_PHY_PAGE_EXTENDED_2A30 0x2a30 -+#define MTK_PHY_PAGE_EXTENDED_52B5 0x52b5 -+ -+#define ANALOG_INTERNAL_OPERATION_MAX_US 20 -+#define TXRESERVE_MIN 0 -+#define TXRESERVE_MAX 7 -+ -+#define MTK_PHY_ANARG_RG 0x10 -+#define MTK_PHY_TCLKOFFSET_MASK GENMASK(12, 8) -+ -+/* Registers on MDIO_MMD_VEND1 */ -+#define MTK_PHY_TXVLD_DA_RG 0x12 -+#define MTK_PHY_DA_TX_I2MPB_A_GBE_MASK GENMASK(15, 10) -+#define MTK_PHY_DA_TX_I2MPB_A_TBT_MASK GENMASK(5, 0) -+ -+#define MTK_PHY_TX_I2MPB_TEST_MODE_A2 0x16 -+#define MTK_PHY_DA_TX_I2MPB_A_HBT_MASK GENMASK(15, 10) -+#define MTK_PHY_DA_TX_I2MPB_A_TST_MASK GENMASK(5, 0) -+ -+#define MTK_PHY_TX_I2MPB_TEST_MODE_B1 0x17 -+#define MTK_PHY_DA_TX_I2MPB_B_GBE_MASK GENMASK(13, 8) -+#define MTK_PHY_DA_TX_I2MPB_B_TBT_MASK GENMASK(5, 0) -+ -+#define MTK_PHY_TX_I2MPB_TEST_MODE_B2 0x18 -+#define MTK_PHY_DA_TX_I2MPB_B_HBT_MASK GENMASK(13, 8) -+#define MTK_PHY_DA_TX_I2MPB_B_TST_MASK GENMASK(5, 0) -+ -+#define MTK_PHY_TX_I2MPB_TEST_MODE_C1 0x19 -+#define MTK_PHY_DA_TX_I2MPB_C_GBE_MASK GENMASK(13, 8) -+#define MTK_PHY_DA_TX_I2MPB_C_TBT_MASK GENMASK(5, 0) -+ -+#define MTK_PHY_TX_I2MPB_TEST_MODE_C2 0x20 -+#define MTK_PHY_DA_TX_I2MPB_C_HBT_MASK GENMASK(13, 8) -+#define MTK_PHY_DA_TX_I2MPB_C_TST_MASK GENMASK(5, 0) -+ -+#define MTK_PHY_TX_I2MPB_TEST_MODE_D1 0x21 -+#define MTK_PHY_DA_TX_I2MPB_D_GBE_MASK GENMASK(13, 8) -+#define MTK_PHY_DA_TX_I2MPB_D_TBT_MASK GENMASK(5, 0) -+ -+#define MTK_PHY_TX_I2MPB_TEST_MODE_D2 0x22 -+#define MTK_PHY_DA_TX_I2MPB_D_HBT_MASK GENMASK(13, 8) -+#define MTK_PHY_DA_TX_I2MPB_D_TST_MASK GENMASK(5, 0) -+ -+#define MTK_PHY_RXADC_CTRL_RG7 0xc6 -+#define MTK_PHY_DA_AD_BUF_BIAS_LP_MASK GENMASK(9, 8) -+ -+#define MTK_PHY_RXADC_CTRL_RG9 0xc8 -+#define MTK_PHY_DA_RX_PSBN_TBT_MASK GENMASK(14, 12) -+#define MTK_PHY_DA_RX_PSBN_HBT_MASK GENMASK(10, 8) -+#define MTK_PHY_DA_RX_PSBN_GBE_MASK GENMASK(6, 4) -+#define MTK_PHY_DA_RX_PSBN_LP_MASK GENMASK(2, 0) -+ -+#define MTK_PHY_LDO_OUTPUT_V 0xd7 -+ -+#define MTK_PHY_RG_ANA_CAL_RG0 0xdb -+#define MTK_PHY_RG_CAL_CKINV BIT(12) -+#define MTK_PHY_RG_ANA_CALEN BIT(8) -+#define MTK_PHY_RG_ZCALEN_A BIT(0) -+ -+#define MTK_PHY_RG_ANA_CAL_RG1 0xdc -+#define MTK_PHY_RG_ZCALEN_B BIT(12) -+#define MTK_PHY_RG_ZCALEN_C BIT(8) -+#define MTK_PHY_RG_ZCALEN_D BIT(4) -+#define MTK_PHY_RG_TXVOS_CALEN BIT(0) -+ -+#define MTK_PHY_RG_ANA_CAL_RG5 0xe0 -+#define MTK_PHY_RG_REXT_TRIM_MASK GENMASK(13, 8) -+ -+#define MTK_PHY_RG_TX_FILTER 0xfe -+ -+#define MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG120 0x120 -+#define MTK_PHY_LPI_SIG_EN_LO_THRESH1000_MASK GENMASK(12, 8) -+#define MTK_PHY_LPI_SIG_EN_HI_THRESH1000_MASK GENMASK(4, 0) -+ -+#define MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG122 0x122 -+#define MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK GENMASK(7, 0) -+ -+#define MTK_PHY_RG_TESTMUX_ADC_CTRL 0x144 -+#define MTK_PHY_RG_TXEN_DIG_MASK GENMASK(5, 5) -+ -+#define MTK_PHY_RG_CR_TX_AMP_OFFSET_A_B 0x172 -+#define MTK_PHY_CR_TX_AMP_OFFSET_A_MASK GENMASK(13, 8) -+#define MTK_PHY_CR_TX_AMP_OFFSET_B_MASK GENMASK(6, 0) -+ -+#define MTK_PHY_RG_CR_TX_AMP_OFFSET_C_D 0x173 -+#define MTK_PHY_CR_TX_AMP_OFFSET_C_MASK GENMASK(13, 8) -+#define MTK_PHY_CR_TX_AMP_OFFSET_D_MASK GENMASK(6, 0) -+ -+#define MTK_PHY_RG_AD_CAL_COMP 0x17a -+#define MTK_PHY_AD_CAL_COMP_OUT_MASK GENMASK(8, 8) -+ -+#define MTK_PHY_RG_AD_CAL_CLK 0x17b -+#define MTK_PHY_DA_CAL_CLK BIT(0) -+ -+#define MTK_PHY_RG_AD_CALIN 0x17c -+#define MTK_PHY_DA_CALIN_FLAG BIT(0) -+ -+#define MTK_PHY_RG_DASN_DAC_IN0_A 0x17d -+#define MTK_PHY_DASN_DAC_IN0_A_MASK GENMASK(9, 0) -+ -+#define MTK_PHY_RG_DASN_DAC_IN0_B 0x17e -+#define MTK_PHY_DASN_DAC_IN0_B_MASK GENMASK(9, 0) -+ -+#define MTK_PHY_RG_DASN_DAC_IN0_C 0x17f -+#define MTK_PHY_DASN_DAC_IN0_C_MASK GENMASK(9, 0) -+ -+#define MTK_PHY_RG_DASN_DAC_IN0_D 0x180 -+#define MTK_PHY_DASN_DAC_IN0_D_MASK GENMASK(9, 0) -+ -+#define MTK_PHY_RG_DASN_DAC_IN1_A 0x181 -+#define MTK_PHY_DASN_DAC_IN1_A_MASK GENMASK(9, 0) -+ -+#define MTK_PHY_RG_DASN_DAC_IN1_B 0x182 -+#define MTK_PHY_DASN_DAC_IN1_B_MASK GENMASK(9, 0) -+ -+#define MTK_PHY_RG_DASN_DAC_IN1_C 0x183 -+#define MTK_PHY_DASN_DAC_IN1_C_MASK GENMASK(9, 0) -+ -+#define MTK_PHY_RG_DASN_DAC_IN1_D 0x184 -+#define MTK_PHY_DASN_DAC_IN1_D_MASK GENMASK(9, 0) -+ -+#define MTK_PHY_RG_DEV1E_REG19b 0x19b -+#define MTK_PHY_BYPASS_DSP_LPI_READY BIT(8) -+ -+#define MTK_PHY_RG_LP_IIR2_K1_L 0x22a -+#define MTK_PHY_RG_LP_IIR2_K1_U 0x22b -+#define MTK_PHY_RG_LP_IIR2_K2_L 0x22c -+#define MTK_PHY_RG_LP_IIR2_K2_U 0x22d -+#define MTK_PHY_RG_LP_IIR2_K3_L 0x22e -+#define MTK_PHY_RG_LP_IIR2_K3_U 0x22f -+#define MTK_PHY_RG_LP_IIR2_K4_L 0x230 -+#define MTK_PHY_RG_LP_IIR2_K4_U 0x231 -+#define MTK_PHY_RG_LP_IIR2_K5_L 0x232 -+#define MTK_PHY_RG_LP_IIR2_K5_U 0x233 -+ -+#define MTK_PHY_RG_DEV1E_REG234 0x234 -+#define MTK_PHY_TR_OPEN_LOOP_EN_MASK GENMASK(0, 0) -+#define MTK_PHY_LPF_X_AVERAGE_MASK GENMASK(7, 4) -+#define MTK_PHY_TR_LP_IIR_EEE_EN BIT(12) -+ -+#define MTK_PHY_RG_LPF_CNT_VAL 0x235 -+ -+#define MTK_PHY_RG_DEV1E_REG238 0x238 -+#define MTK_PHY_LPI_SLV_SEND_TX_TIMER_MASK GENMASK(8, 0) -+#define MTK_PHY_LPI_SLV_SEND_TX_EN BIT(12) -+ -+#define MTK_PHY_RG_DEV1E_REG239 0x239 -+#define MTK_PHY_LPI_SEND_LOC_TIMER_MASK GENMASK(8, 0) -+#define MTK_PHY_LPI_TXPCS_LOC_RCV BIT(12) -+ -+#define MTK_PHY_RG_DEV1E_REG27C 0x27c -+#define MTK_PHY_VGASTATE_FFE_THR_ST1_MASK GENMASK(12, 8) -+#define MTK_PHY_RG_DEV1E_REG27D 0x27d -+#define MTK_PHY_VGASTATE_FFE_THR_ST2_MASK GENMASK(4, 0) -+ -+#define MTK_PHY_RG_DEV1E_REG2C7 0x2c7 -+#define MTK_PHY_MAX_GAIN_MASK GENMASK(4, 0) -+#define MTK_PHY_MIN_GAIN_MASK GENMASK(12, 8) -+ -+#define MTK_PHY_RG_DEV1E_REG2D1 0x2d1 -+#define MTK_PHY_VCO_SLICER_THRESH_BITS_HIGH_EEE_MASK GENMASK(7, 0) -+#define MTK_PHY_LPI_SKIP_SD_SLV_TR BIT(8) -+#define MTK_PHY_LPI_TR_READY BIT(9) -+#define MTK_PHY_LPI_VCO_EEE_STG0_EN BIT(10) -+ -+#define MTK_PHY_RG_DEV1E_REG323 0x323 -+#define MTK_PHY_EEE_WAKE_MAS_INT_DC BIT(0) -+#define MTK_PHY_EEE_WAKE_SLV_INT_DC BIT(4) -+ -+#define MTK_PHY_RG_DEV1E_REG324 0x324 -+#define MTK_PHY_SMI_DETCNT_MAX_MASK GENMASK(5, 0) -+#define MTK_PHY_SMI_DET_MAX_EN BIT(8) -+ -+#define MTK_PHY_RG_DEV1E_REG326 0x326 -+#define MTK_PHY_LPI_MODE_SD_ON BIT(0) -+#define MTK_PHY_RESET_RANDUPD_CNT BIT(1) -+#define MTK_PHY_TREC_UPDATE_ENAB_CLR BIT(2) -+#define MTK_PHY_LPI_QUIT_WAIT_DFE_SIG_DET_OFF BIT(4) -+#define MTK_PHY_TR_READY_SKIP_AFE_WAKEUP BIT(5) -+ -+#define MTK_PHY_LDO_PUMP_EN_PAIRAB 0x502 -+#define MTK_PHY_LDO_PUMP_EN_PAIRCD 0x503 -+ -+#define MTK_PHY_DA_TX_R50_PAIR_A 0x53d -+#define MTK_PHY_DA_TX_R50_PAIR_B 0x53e -+#define MTK_PHY_DA_TX_R50_PAIR_C 0x53f -+#define MTK_PHY_DA_TX_R50_PAIR_D 0x540 -+ -+/* Registers on MDIO_MMD_VEND2 */ -+#define MTK_PHY_LED0_ON_CTRL 0x24 -+#define MTK_PHY_LED1_ON_CTRL 0x26 -+#define MTK_PHY_LED_ON_MASK GENMASK(6, 0) -+#define MTK_PHY_LED_ON_LINK1000 BIT(0) -+#define MTK_PHY_LED_ON_LINK100 BIT(1) -+#define MTK_PHY_LED_ON_LINK10 BIT(2) -+#define MTK_PHY_LED_ON_LINK (MTK_PHY_LED_ON_LINK10 |\ -+ MTK_PHY_LED_ON_LINK100 |\ -+ MTK_PHY_LED_ON_LINK1000) -+#define MTK_PHY_LED_ON_LINKDOWN BIT(3) -+#define MTK_PHY_LED_ON_FDX BIT(4) /* Full duplex */ -+#define MTK_PHY_LED_ON_HDX BIT(5) /* Half duplex */ -+#define MTK_PHY_LED_ON_FORCE_ON BIT(6) -+#define MTK_PHY_LED_ON_POLARITY BIT(14) -+#define MTK_PHY_LED_ON_ENABLE BIT(15) -+ -+#define MTK_PHY_LED0_BLINK_CTRL 0x25 -+#define MTK_PHY_LED1_BLINK_CTRL 0x27 -+#define MTK_PHY_LED_BLINK_1000TX BIT(0) -+#define MTK_PHY_LED_BLINK_1000RX BIT(1) -+#define MTK_PHY_LED_BLINK_100TX BIT(2) -+#define MTK_PHY_LED_BLINK_100RX BIT(3) -+#define MTK_PHY_LED_BLINK_10TX BIT(4) -+#define MTK_PHY_LED_BLINK_10RX BIT(5) -+#define MTK_PHY_LED_BLINK_RX (MTK_PHY_LED_BLINK_10RX |\ -+ MTK_PHY_LED_BLINK_100RX |\ -+ MTK_PHY_LED_BLINK_1000RX) -+#define MTK_PHY_LED_BLINK_TX (MTK_PHY_LED_BLINK_10TX |\ -+ MTK_PHY_LED_BLINK_100TX |\ -+ MTK_PHY_LED_BLINK_1000TX) -+#define MTK_PHY_LED_BLINK_COLLISION BIT(6) -+#define MTK_PHY_LED_BLINK_RX_CRC_ERR BIT(7) -+#define MTK_PHY_LED_BLINK_RX_IDLE_ERR BIT(8) -+#define MTK_PHY_LED_BLINK_FORCE_BLINK BIT(9) -+ -+#define MTK_PHY_LED1_DEFAULT_POLARITIES BIT(1) -+ -+#define MTK_PHY_RG_BG_RASEL 0x115 -+#define MTK_PHY_RG_BG_RASEL_MASK GENMASK(2, 0) -+ -+/* 'boottrap' register reflecting the configuration of the 4 PHY LEDs */ -+#define RG_GPIO_MISC_TPBANK0 0x6f0 -+#define RG_GPIO_MISC_TPBANK0_BOOTMODE GENMASK(11, 8) -+ -+/* These macro privides efuse parsing for internal phy. */ -+#define EFS_DA_TX_I2MPB_A(x) (((x) >> 0) & GENMASK(5, 0)) -+#define EFS_DA_TX_I2MPB_B(x) (((x) >> 6) & GENMASK(5, 0)) -+#define EFS_DA_TX_I2MPB_C(x) (((x) >> 12) & GENMASK(5, 0)) -+#define EFS_DA_TX_I2MPB_D(x) (((x) >> 18) & GENMASK(5, 0)) -+#define EFS_DA_TX_AMP_OFFSET_A(x) (((x) >> 24) & GENMASK(5, 0)) -+ -+#define EFS_DA_TX_AMP_OFFSET_B(x) (((x) >> 0) & GENMASK(5, 0)) -+#define EFS_DA_TX_AMP_OFFSET_C(x) (((x) >> 6) & GENMASK(5, 0)) -+#define EFS_DA_TX_AMP_OFFSET_D(x) (((x) >> 12) & GENMASK(5, 0)) -+#define EFS_DA_TX_R50_A(x) (((x) >> 18) & GENMASK(5, 0)) -+#define EFS_DA_TX_R50_B(x) (((x) >> 24) & GENMASK(5, 0)) -+ -+#define EFS_DA_TX_R50_C(x) (((x) >> 0) & GENMASK(5, 0)) -+#define EFS_DA_TX_R50_D(x) (((x) >> 6) & GENMASK(5, 0)) -+ -+#define EFS_RG_BG_RASEL(x) (((x) >> 4) & GENMASK(2, 0)) -+#define EFS_RG_REXT_TRIM(x) (((x) >> 7) & GENMASK(5, 0)) -+ -+enum { -+ NO_PAIR, -+ PAIR_A, -+ PAIR_B, -+ PAIR_C, -+ PAIR_D, -+}; -+ -+enum calibration_mode { -+ EFUSE_K, -+ SW_K -+}; -+ -+enum CAL_ITEM { -+ REXT, -+ TX_OFFSET, -+ TX_AMP, -+ TX_R50, -+ TX_VCM -+}; -+ -+enum CAL_MODE { -+ EFUSE_M, -+ SW_M -+}; -+ -+#define MTK_PHY_LED_STATE_FORCE_ON 0 -+#define MTK_PHY_LED_STATE_FORCE_BLINK 1 -+#define MTK_PHY_LED_STATE_NETDEV 2 -+ -+struct mtk_socphy_priv { -+ unsigned long led_state; -+}; -+ -+struct mtk_socphy_shared { -+ u32 boottrap; -+ struct mtk_socphy_priv priv[4]; -+}; -+ -+static int mtk_socphy_read_page(struct phy_device *phydev) -+{ -+ return __phy_read(phydev, MTK_EXT_PAGE_ACCESS); -+} -+ -+static int mtk_socphy_write_page(struct phy_device *phydev, int page) -+{ -+ return __phy_write(phydev, MTK_EXT_PAGE_ACCESS, page); -+} -+ -+/* One calibration cycle consists of: -+ * 1.Set DA_CALIN_FLAG high to start calibration. Keep it high -+ * until AD_CAL_COMP is ready to output calibration result. -+ * 2.Wait until DA_CAL_CLK is available. -+ * 3.Fetch AD_CAL_COMP_OUT. -+ */ -+static int cal_cycle(struct phy_device *phydev, int devad, -+ u32 regnum, u16 mask, u16 cal_val) -+{ -+ int reg_val; -+ int ret; -+ -+ phy_modify_mmd(phydev, devad, regnum, -+ mask, cal_val); -+ phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_AD_CALIN, -+ MTK_PHY_DA_CALIN_FLAG); -+ -+ ret = phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1, -+ MTK_PHY_RG_AD_CAL_CLK, reg_val, -+ reg_val & MTK_PHY_DA_CAL_CLK, 500, -+ ANALOG_INTERNAL_OPERATION_MAX_US, -+ false); -+ if (ret) { -+ phydev_err(phydev, "Calibration cycle timeout\n"); -+ return ret; -+ } -+ -+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_AD_CALIN, -+ MTK_PHY_DA_CALIN_FLAG); -+ ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_AD_CAL_COMP); -+ if (ret < 0) -+ return ret; -+ ret = FIELD_GET(MTK_PHY_AD_CAL_COMP_OUT_MASK, ret); -+ phydev_dbg(phydev, "cal_val: 0x%x, ret: %d\n", cal_val, ret); -+ -+ return ret; -+} -+ -+static int rext_fill_result(struct phy_device *phydev, u16 *buf) -+{ -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG5, -+ MTK_PHY_RG_REXT_TRIM_MASK, buf[0] << 8); -+ phy_modify_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_RG_BG_RASEL, -+ MTK_PHY_RG_BG_RASEL_MASK, buf[1]); -+ -+ return 0; -+} -+ -+static int rext_cal_efuse(struct phy_device *phydev, u32 *buf) -+{ -+ u16 rext_cal_val[2]; -+ -+ rext_cal_val[0] = EFS_RG_REXT_TRIM(buf[3]); -+ rext_cal_val[1] = EFS_RG_BG_RASEL(buf[3]); -+ rext_fill_result(phydev, rext_cal_val); -+ -+ return 0; -+} -+ -+static int tx_offset_fill_result(struct phy_device *phydev, u16 *buf) -+{ -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_CR_TX_AMP_OFFSET_A_B, -+ MTK_PHY_CR_TX_AMP_OFFSET_A_MASK, buf[0] << 8); -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_CR_TX_AMP_OFFSET_A_B, -+ MTK_PHY_CR_TX_AMP_OFFSET_B_MASK, buf[1]); -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_CR_TX_AMP_OFFSET_C_D, -+ MTK_PHY_CR_TX_AMP_OFFSET_C_MASK, buf[2] << 8); -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_CR_TX_AMP_OFFSET_C_D, -+ MTK_PHY_CR_TX_AMP_OFFSET_D_MASK, buf[3]); -+ -+ return 0; -+} -+ -+static int tx_offset_cal_efuse(struct phy_device *phydev, u32 *buf) -+{ -+ u16 tx_offset_cal_val[4]; -+ -+ tx_offset_cal_val[0] = EFS_DA_TX_AMP_OFFSET_A(buf[0]); -+ tx_offset_cal_val[1] = EFS_DA_TX_AMP_OFFSET_B(buf[1]); -+ tx_offset_cal_val[2] = EFS_DA_TX_AMP_OFFSET_C(buf[1]); -+ tx_offset_cal_val[3] = EFS_DA_TX_AMP_OFFSET_D(buf[1]); -+ -+ tx_offset_fill_result(phydev, tx_offset_cal_val); -+ -+ return 0; -+} -+ -+static int tx_amp_fill_result(struct phy_device *phydev, u16 *buf) -+{ -+ const int vals_9481[16] = { 10, 6, 6, 10, -+ 10, 6, 6, 10, -+ 10, 6, 6, 10, -+ 10, 6, 6, 10 }; -+ const int vals_9461[16] = { 7, 1, 4, 7, -+ 7, 1, 4, 7, -+ 7, 1, 4, 7, -+ 7, 1, 4, 7 }; -+ int bias[16] = {}; -+ int i; -+ -+ switch (phydev->drv->phy_id) { -+ case MTK_GPHY_ID_MT7981: -+ /* We add some calibration to efuse values -+ * due to board level influence. -+ * GBE: +7, TBT: +1, HBT: +4, TST: +7 -+ */ -+ memcpy(bias, (const void *)vals_9461, sizeof(bias)); -+ break; -+ case MTK_GPHY_ID_MT7988: -+ memcpy(bias, (const void *)vals_9481, sizeof(bias)); -+ break; -+ } -+ -+ /* Prevent overflow */ -+ for (i = 0; i < 12; i++) { -+ if (buf[i >> 2] + bias[i] > 63) { -+ buf[i >> 2] = 63; -+ bias[i] = 0; -+ } -+ } -+ -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TXVLD_DA_RG, -+ MTK_PHY_DA_TX_I2MPB_A_GBE_MASK, -+ FIELD_PREP(MTK_PHY_DA_TX_I2MPB_A_GBE_MASK, -+ buf[0] + bias[0])); -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TXVLD_DA_RG, -+ MTK_PHY_DA_TX_I2MPB_A_TBT_MASK, -+ FIELD_PREP(MTK_PHY_DA_TX_I2MPB_A_TBT_MASK, -+ buf[0] + bias[1])); -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_A2, -+ MTK_PHY_DA_TX_I2MPB_A_HBT_MASK, -+ FIELD_PREP(MTK_PHY_DA_TX_I2MPB_A_HBT_MASK, -+ buf[0] + bias[2])); -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_A2, -+ MTK_PHY_DA_TX_I2MPB_A_TST_MASK, -+ FIELD_PREP(MTK_PHY_DA_TX_I2MPB_A_TST_MASK, -+ buf[0] + bias[3])); -+ -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_B1, -+ MTK_PHY_DA_TX_I2MPB_B_GBE_MASK, -+ FIELD_PREP(MTK_PHY_DA_TX_I2MPB_B_GBE_MASK, -+ buf[1] + bias[4])); -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_B1, -+ MTK_PHY_DA_TX_I2MPB_B_TBT_MASK, -+ FIELD_PREP(MTK_PHY_DA_TX_I2MPB_B_TBT_MASK, -+ buf[1] + bias[5])); -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_B2, -+ MTK_PHY_DA_TX_I2MPB_B_HBT_MASK, -+ FIELD_PREP(MTK_PHY_DA_TX_I2MPB_B_HBT_MASK, -+ buf[1] + bias[6])); -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_B2, -+ MTK_PHY_DA_TX_I2MPB_B_TST_MASK, -+ FIELD_PREP(MTK_PHY_DA_TX_I2MPB_B_TST_MASK, -+ buf[1] + bias[7])); -+ -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_C1, -+ MTK_PHY_DA_TX_I2MPB_C_GBE_MASK, -+ FIELD_PREP(MTK_PHY_DA_TX_I2MPB_C_GBE_MASK, -+ buf[2] + bias[8])); -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_C1, -+ MTK_PHY_DA_TX_I2MPB_C_TBT_MASK, -+ FIELD_PREP(MTK_PHY_DA_TX_I2MPB_C_TBT_MASK, -+ buf[2] + bias[9])); -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_C2, -+ MTK_PHY_DA_TX_I2MPB_C_HBT_MASK, -+ FIELD_PREP(MTK_PHY_DA_TX_I2MPB_C_HBT_MASK, -+ buf[2] + bias[10])); -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_C2, -+ MTK_PHY_DA_TX_I2MPB_C_TST_MASK, -+ FIELD_PREP(MTK_PHY_DA_TX_I2MPB_C_TST_MASK, -+ buf[2] + bias[11])); -+ -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_D1, -+ MTK_PHY_DA_TX_I2MPB_D_GBE_MASK, -+ FIELD_PREP(MTK_PHY_DA_TX_I2MPB_D_GBE_MASK, -+ buf[3] + bias[12])); -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_D1, -+ MTK_PHY_DA_TX_I2MPB_D_TBT_MASK, -+ FIELD_PREP(MTK_PHY_DA_TX_I2MPB_D_TBT_MASK, -+ buf[3] + bias[13])); -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_D2, -+ MTK_PHY_DA_TX_I2MPB_D_HBT_MASK, -+ FIELD_PREP(MTK_PHY_DA_TX_I2MPB_D_HBT_MASK, -+ buf[3] + bias[14])); -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_D2, -+ MTK_PHY_DA_TX_I2MPB_D_TST_MASK, -+ FIELD_PREP(MTK_PHY_DA_TX_I2MPB_D_TST_MASK, -+ buf[3] + bias[15])); -+ -+ return 0; -+} -+ -+static int tx_amp_cal_efuse(struct phy_device *phydev, u32 *buf) -+{ -+ u16 tx_amp_cal_val[4]; -+ -+ tx_amp_cal_val[0] = EFS_DA_TX_I2MPB_A(buf[0]); -+ tx_amp_cal_val[1] = EFS_DA_TX_I2MPB_B(buf[0]); -+ tx_amp_cal_val[2] = EFS_DA_TX_I2MPB_C(buf[0]); -+ tx_amp_cal_val[3] = EFS_DA_TX_I2MPB_D(buf[0]); -+ tx_amp_fill_result(phydev, tx_amp_cal_val); -+ -+ return 0; -+} -+ -+static int tx_r50_fill_result(struct phy_device *phydev, u16 tx_r50_cal_val, -+ u8 txg_calen_x) -+{ -+ int bias = 0; -+ u16 reg, val; -+ -+ if (phydev->drv->phy_id == MTK_GPHY_ID_MT7988) -+ bias = -1; -+ -+ val = clamp_val(bias + tx_r50_cal_val, 0, 63); -+ -+ switch (txg_calen_x) { -+ case PAIR_A: -+ reg = MTK_PHY_DA_TX_R50_PAIR_A; -+ break; -+ case PAIR_B: -+ reg = MTK_PHY_DA_TX_R50_PAIR_B; -+ break; -+ case PAIR_C: -+ reg = MTK_PHY_DA_TX_R50_PAIR_C; -+ break; -+ case PAIR_D: -+ reg = MTK_PHY_DA_TX_R50_PAIR_D; -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, reg, val | val << 8); -+ -+ return 0; -+} -+ -+static int tx_r50_cal_efuse(struct phy_device *phydev, u32 *buf, -+ u8 txg_calen_x) -+{ -+ u16 tx_r50_cal_val; -+ -+ switch (txg_calen_x) { -+ case PAIR_A: -+ tx_r50_cal_val = EFS_DA_TX_R50_A(buf[1]); -+ break; -+ case PAIR_B: -+ tx_r50_cal_val = EFS_DA_TX_R50_B(buf[1]); -+ break; -+ case PAIR_C: -+ tx_r50_cal_val = EFS_DA_TX_R50_C(buf[2]); -+ break; -+ case PAIR_D: -+ tx_r50_cal_val = EFS_DA_TX_R50_D(buf[2]); -+ break; -+ default: -+ return -EINVAL; -+ } -+ tx_r50_fill_result(phydev, tx_r50_cal_val, txg_calen_x); -+ -+ return 0; -+} -+ -+static int tx_vcm_cal_sw(struct phy_device *phydev, u8 rg_txreserve_x) -+{ -+ u8 lower_idx, upper_idx, txreserve_val; -+ u8 lower_ret, upper_ret; -+ int ret; -+ -+ phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0, -+ MTK_PHY_RG_ANA_CALEN); -+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0, -+ MTK_PHY_RG_CAL_CKINV); -+ phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG1, -+ MTK_PHY_RG_TXVOS_CALEN); -+ -+ switch (rg_txreserve_x) { -+ case PAIR_A: -+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, -+ MTK_PHY_RG_DASN_DAC_IN0_A, -+ MTK_PHY_DASN_DAC_IN0_A_MASK); -+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, -+ MTK_PHY_RG_DASN_DAC_IN1_A, -+ MTK_PHY_DASN_DAC_IN1_A_MASK); -+ phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, -+ MTK_PHY_RG_ANA_CAL_RG0, -+ MTK_PHY_RG_ZCALEN_A); -+ break; -+ case PAIR_B: -+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, -+ MTK_PHY_RG_DASN_DAC_IN0_B, -+ MTK_PHY_DASN_DAC_IN0_B_MASK); -+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, -+ MTK_PHY_RG_DASN_DAC_IN1_B, -+ MTK_PHY_DASN_DAC_IN1_B_MASK); -+ phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, -+ MTK_PHY_RG_ANA_CAL_RG1, -+ MTK_PHY_RG_ZCALEN_B); -+ break; -+ case PAIR_C: -+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, -+ MTK_PHY_RG_DASN_DAC_IN0_C, -+ MTK_PHY_DASN_DAC_IN0_C_MASK); -+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, -+ MTK_PHY_RG_DASN_DAC_IN1_C, -+ MTK_PHY_DASN_DAC_IN1_C_MASK); -+ phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, -+ MTK_PHY_RG_ANA_CAL_RG1, -+ MTK_PHY_RG_ZCALEN_C); -+ break; -+ case PAIR_D: -+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, -+ MTK_PHY_RG_DASN_DAC_IN0_D, -+ MTK_PHY_DASN_DAC_IN0_D_MASK); -+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, -+ MTK_PHY_RG_DASN_DAC_IN1_D, -+ MTK_PHY_DASN_DAC_IN1_D_MASK); -+ phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, -+ MTK_PHY_RG_ANA_CAL_RG1, -+ MTK_PHY_RG_ZCALEN_D); -+ break; -+ default: -+ ret = -EINVAL; -+ goto restore; -+ } -+ -+ lower_idx = TXRESERVE_MIN; -+ upper_idx = TXRESERVE_MAX; -+ -+ phydev_dbg(phydev, "Start TX-VCM SW cal.\n"); -+ while ((upper_idx - lower_idx) > 1) { -+ txreserve_val = DIV_ROUND_CLOSEST(lower_idx + upper_idx, 2); -+ ret = cal_cycle(phydev, MDIO_MMD_VEND1, MTK_PHY_RXADC_CTRL_RG9, -+ MTK_PHY_DA_RX_PSBN_TBT_MASK | -+ MTK_PHY_DA_RX_PSBN_HBT_MASK | -+ MTK_PHY_DA_RX_PSBN_GBE_MASK | -+ MTK_PHY_DA_RX_PSBN_LP_MASK, -+ txreserve_val << 12 | txreserve_val << 8 | -+ txreserve_val << 4 | txreserve_val); -+ if (ret == 1) { -+ upper_idx = txreserve_val; -+ upper_ret = ret; -+ } else if (ret == 0) { -+ lower_idx = txreserve_val; -+ lower_ret = ret; -+ } else { -+ goto restore; -+ } -+ } -+ -+ if (lower_idx == TXRESERVE_MIN) { -+ lower_ret = cal_cycle(phydev, MDIO_MMD_VEND1, -+ MTK_PHY_RXADC_CTRL_RG9, -+ MTK_PHY_DA_RX_PSBN_TBT_MASK | -+ MTK_PHY_DA_RX_PSBN_HBT_MASK | -+ MTK_PHY_DA_RX_PSBN_GBE_MASK | -+ MTK_PHY_DA_RX_PSBN_LP_MASK, -+ lower_idx << 12 | lower_idx << 8 | -+ lower_idx << 4 | lower_idx); -+ ret = lower_ret; -+ } else if (upper_idx == TXRESERVE_MAX) { -+ upper_ret = cal_cycle(phydev, MDIO_MMD_VEND1, -+ MTK_PHY_RXADC_CTRL_RG9, -+ MTK_PHY_DA_RX_PSBN_TBT_MASK | -+ MTK_PHY_DA_RX_PSBN_HBT_MASK | -+ MTK_PHY_DA_RX_PSBN_GBE_MASK | -+ MTK_PHY_DA_RX_PSBN_LP_MASK, -+ upper_idx << 12 | upper_idx << 8 | -+ upper_idx << 4 | upper_idx); -+ ret = upper_ret; -+ } -+ if (ret < 0) -+ goto restore; -+ -+ /* We calibrate TX-VCM in different logic. Check upper index and then -+ * lower index. If this calibration is valid, apply lower index's -+ * result. -+ */ -+ ret = upper_ret - lower_ret; -+ if (ret == 1) { -+ ret = 0; -+ /* Make sure we use upper_idx in our calibration system */ -+ cal_cycle(phydev, MDIO_MMD_VEND1, MTK_PHY_RXADC_CTRL_RG9, -+ MTK_PHY_DA_RX_PSBN_TBT_MASK | -+ MTK_PHY_DA_RX_PSBN_HBT_MASK | -+ MTK_PHY_DA_RX_PSBN_GBE_MASK | -+ MTK_PHY_DA_RX_PSBN_LP_MASK, -+ upper_idx << 12 | upper_idx << 8 | -+ upper_idx << 4 | upper_idx); -+ phydev_dbg(phydev, "TX-VCM SW cal result: 0x%x\n", upper_idx); -+ } else if (lower_idx == TXRESERVE_MIN && upper_ret == 1 && -+ lower_ret == 1) { -+ ret = 0; -+ cal_cycle(phydev, MDIO_MMD_VEND1, MTK_PHY_RXADC_CTRL_RG9, -+ MTK_PHY_DA_RX_PSBN_TBT_MASK | -+ MTK_PHY_DA_RX_PSBN_HBT_MASK | -+ MTK_PHY_DA_RX_PSBN_GBE_MASK | -+ MTK_PHY_DA_RX_PSBN_LP_MASK, -+ lower_idx << 12 | lower_idx << 8 | -+ lower_idx << 4 | lower_idx); -+ phydev_warn(phydev, "TX-VCM SW cal result at low margin 0x%x\n", -+ lower_idx); -+ } else if (upper_idx == TXRESERVE_MAX && upper_ret == 0 && -+ lower_ret == 0) { -+ ret = 0; -+ phydev_warn(phydev, -+ "TX-VCM SW cal result at high margin 0x%x\n", -+ upper_idx); -+ } else { -+ ret = -EINVAL; -+ } -+ -+restore: -+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0, -+ MTK_PHY_RG_ANA_CALEN); -+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG1, -+ MTK_PHY_RG_TXVOS_CALEN); -+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0, -+ MTK_PHY_RG_ZCALEN_A); -+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG1, -+ MTK_PHY_RG_ZCALEN_B | MTK_PHY_RG_ZCALEN_C | -+ MTK_PHY_RG_ZCALEN_D); -+ -+ return ret; -+} -+ -+static void mt798x_phy_common_finetune(struct phy_device *phydev) -+{ -+ phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5); -+ /* SlvDSPreadyTime = 24, MasDSPreadyTime = 24 */ -+ __phy_write(phydev, 0x11, 0xc71); -+ __phy_write(phydev, 0x12, 0xc); -+ __phy_write(phydev, 0x10, 0x8fae); -+ -+ /* EnabRandUpdTrig = 1 */ -+ __phy_write(phydev, 0x11, 0x2f00); -+ __phy_write(phydev, 0x12, 0xe); -+ __phy_write(phydev, 0x10, 0x8fb0); -+ -+ /* NormMseLoThresh = 85 */ -+ __phy_write(phydev, 0x11, 0x55a0); -+ __phy_write(phydev, 0x12, 0x0); -+ __phy_write(phydev, 0x10, 0x83aa); -+ -+ /* FfeUpdGainForce = 1(Enable), FfeUpdGainForceVal = 4 */ -+ __phy_write(phydev, 0x11, 0x240); -+ __phy_write(phydev, 0x12, 0x0); -+ __phy_write(phydev, 0x10, 0x9680); -+ -+ /* TrFreeze = 0 (mt7988 default) */ -+ __phy_write(phydev, 0x11, 0x0); -+ __phy_write(phydev, 0x12, 0x0); -+ __phy_write(phydev, 0x10, 0x9686); -+ -+ /* SSTrKp100 = 5 */ -+ /* SSTrKf100 = 6 */ -+ /* SSTrKp1000Mas = 5 */ -+ /* SSTrKf1000Mas = 6 */ -+ /* SSTrKp1000Slv = 5 */ -+ /* SSTrKf1000Slv = 6 */ -+ __phy_write(phydev, 0x11, 0xbaef); -+ __phy_write(phydev, 0x12, 0x2e); -+ __phy_write(phydev, 0x10, 0x968c); -+ phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0); -+} -+ -+static void mt7981_phy_finetune(struct phy_device *phydev) -+{ -+ u16 val[8] = { 0x01ce, 0x01c1, -+ 0x020f, 0x0202, -+ 0x03d0, 0x03c0, -+ 0x0013, 0x0005 }; -+ int i, k; -+ -+ /* 100M eye finetune: -+ * Keep middle level of TX MLT3 shapper as default. -+ * Only change TX MLT3 overshoot level here. -+ */ -+ for (k = 0, i = 1; i < 12; i++) { -+ if (i % 3 == 0) -+ continue; -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, i, val[k++]); -+ } -+ -+ phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5); -+ /* ResetSyncOffset = 6 */ -+ __phy_write(phydev, 0x11, 0x600); -+ __phy_write(phydev, 0x12, 0x0); -+ __phy_write(phydev, 0x10, 0x8fc0); -+ -+ /* VgaDecRate = 1 */ -+ __phy_write(phydev, 0x11, 0x4c2a); -+ __phy_write(phydev, 0x12, 0x3e); -+ __phy_write(phydev, 0x10, 0x8fa4); -+ -+ /* MrvlTrFix100Kp = 3, MrvlTrFix100Kf = 2, -+ * MrvlTrFix1000Kp = 3, MrvlTrFix1000Kf = 2 -+ */ -+ __phy_write(phydev, 0x11, 0xd10a); -+ __phy_write(phydev, 0x12, 0x34); -+ __phy_write(phydev, 0x10, 0x8f82); -+ -+ /* VcoSlicerThreshBitsHigh */ -+ __phy_write(phydev, 0x11, 0x5555); -+ __phy_write(phydev, 0x12, 0x55); -+ __phy_write(phydev, 0x10, 0x8ec0); -+ phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0); -+ -+ /* TR_OPEN_LOOP_EN = 1, lpf_x_average = 9 */ -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG234, -+ MTK_PHY_TR_OPEN_LOOP_EN_MASK | -+ MTK_PHY_LPF_X_AVERAGE_MASK, -+ BIT(0) | FIELD_PREP(MTK_PHY_LPF_X_AVERAGE_MASK, 0x9)); -+ -+ /* rg_tr_lpf_cnt_val = 512 */ -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LPF_CNT_VAL, 0x200); -+ -+ /* IIR2 related */ -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K1_L, 0x82); -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K1_U, 0x0); -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K2_L, 0x103); -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K2_U, 0x0); -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K3_L, 0x82); -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K3_U, 0x0); -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K4_L, 0xd177); -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K4_U, 0x3); -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K5_L, 0x2c82); -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K5_U, 0xe); -+ -+ /* FFE peaking */ -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG27C, -+ MTK_PHY_VGASTATE_FFE_THR_ST1_MASK, 0x1b << 8); -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG27D, -+ MTK_PHY_VGASTATE_FFE_THR_ST2_MASK, 0x1e); -+ -+ /* Disable LDO pump */ -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_LDO_PUMP_EN_PAIRAB, 0x0); -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_LDO_PUMP_EN_PAIRCD, 0x0); -+ /* Adjust LDO output voltage */ -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_LDO_OUTPUT_V, 0x2222); -+} -+ -+static void mt7988_phy_finetune(struct phy_device *phydev) -+{ -+ u16 val[12] = { 0x0187, 0x01cd, 0x01c8, 0x0182, -+ 0x020d, 0x0206, 0x0384, 0x03d0, -+ 0x03c6, 0x030a, 0x0011, 0x0005 }; -+ int i; -+ -+ /* Set default MLT3 shaper first */ -+ for (i = 0; i < 12; i++) -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, i, val[i]); -+ -+ /* TCT finetune */ -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_TX_FILTER, 0x5); -+ -+ phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5); -+ /* ResetSyncOffset = 5 */ -+ __phy_write(phydev, 0x11, 0x500); -+ __phy_write(phydev, 0x12, 0x0); -+ __phy_write(phydev, 0x10, 0x8fc0); -+ -+ /* VgaDecRate is 1 at default on mt7988 */ -+ -+ /* MrvlTrFix100Kp = 6, MrvlTrFix100Kf = 7, -+ * MrvlTrFix1000Kp = 6, MrvlTrFix1000Kf = 7 -+ */ -+ __phy_write(phydev, 0x11, 0xb90a); -+ __phy_write(phydev, 0x12, 0x6f); -+ __phy_write(phydev, 0x10, 0x8f82); -+ -+ /* RemAckCntLimitCtrl = 1 */ -+ __phy_write(phydev, 0x11, 0xfbba); -+ __phy_write(phydev, 0x12, 0xc3); -+ __phy_write(phydev, 0x10, 0x87f8); -+ -+ phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0); -+ -+ /* TR_OPEN_LOOP_EN = 1, lpf_x_average = 10 */ -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG234, -+ MTK_PHY_TR_OPEN_LOOP_EN_MASK | -+ MTK_PHY_LPF_X_AVERAGE_MASK, -+ BIT(0) | FIELD_PREP(MTK_PHY_LPF_X_AVERAGE_MASK, 0xa)); -+ -+ /* rg_tr_lpf_cnt_val = 1023 */ -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LPF_CNT_VAL, 0x3ff); -+} -+ -+static void mt798x_phy_eee(struct phy_device *phydev) -+{ -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, -+ MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG120, -+ MTK_PHY_LPI_SIG_EN_LO_THRESH1000_MASK | -+ MTK_PHY_LPI_SIG_EN_HI_THRESH1000_MASK, -+ FIELD_PREP(MTK_PHY_LPI_SIG_EN_LO_THRESH1000_MASK, 0x0) | -+ FIELD_PREP(MTK_PHY_LPI_SIG_EN_HI_THRESH1000_MASK, 0x14)); -+ -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, -+ MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG122, -+ MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK, -+ FIELD_PREP(MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK, -+ 0xff)); -+ -+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, -+ MTK_PHY_RG_TESTMUX_ADC_CTRL, -+ MTK_PHY_RG_TXEN_DIG_MASK); -+ -+ phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, -+ MTK_PHY_RG_DEV1E_REG19b, MTK_PHY_BYPASS_DSP_LPI_READY); -+ -+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, -+ MTK_PHY_RG_DEV1E_REG234, MTK_PHY_TR_LP_IIR_EEE_EN); -+ -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG238, -+ MTK_PHY_LPI_SLV_SEND_TX_TIMER_MASK | -+ MTK_PHY_LPI_SLV_SEND_TX_EN, -+ FIELD_PREP(MTK_PHY_LPI_SLV_SEND_TX_TIMER_MASK, 0x120)); -+ -+ /* Keep MTK_PHY_LPI_SEND_LOC_TIMER as 375 */ -+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG239, -+ MTK_PHY_LPI_TXPCS_LOC_RCV); -+ -+ /* This also fixes some IoT issues, such as CH340 */ -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG2C7, -+ MTK_PHY_MAX_GAIN_MASK | MTK_PHY_MIN_GAIN_MASK, -+ FIELD_PREP(MTK_PHY_MAX_GAIN_MASK, 0x8) | -+ FIELD_PREP(MTK_PHY_MIN_GAIN_MASK, 0x13)); -+ -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG2D1, -+ MTK_PHY_VCO_SLICER_THRESH_BITS_HIGH_EEE_MASK, -+ FIELD_PREP(MTK_PHY_VCO_SLICER_THRESH_BITS_HIGH_EEE_MASK, -+ 0x33) | -+ MTK_PHY_LPI_SKIP_SD_SLV_TR | MTK_PHY_LPI_TR_READY | -+ MTK_PHY_LPI_VCO_EEE_STG0_EN); -+ -+ phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG323, -+ MTK_PHY_EEE_WAKE_MAS_INT_DC | -+ MTK_PHY_EEE_WAKE_SLV_INT_DC); -+ -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG324, -+ MTK_PHY_SMI_DETCNT_MAX_MASK, -+ FIELD_PREP(MTK_PHY_SMI_DETCNT_MAX_MASK, 0x3f) | -+ MTK_PHY_SMI_DET_MAX_EN); -+ -+ phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG326, -+ MTK_PHY_LPI_MODE_SD_ON | MTK_PHY_RESET_RANDUPD_CNT | -+ MTK_PHY_TREC_UPDATE_ENAB_CLR | -+ MTK_PHY_LPI_QUIT_WAIT_DFE_SIG_DET_OFF | -+ MTK_PHY_TR_READY_SKIP_AFE_WAKEUP); -+ -+ phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5); -+ /* Regsigdet_sel_1000 = 0 */ -+ __phy_write(phydev, 0x11, 0xb); -+ __phy_write(phydev, 0x12, 0x0); -+ __phy_write(phydev, 0x10, 0x9690); -+ -+ /* REG_EEE_st2TrKf1000 = 2 */ -+ __phy_write(phydev, 0x11, 0x114f); -+ __phy_write(phydev, 0x12, 0x2); -+ __phy_write(phydev, 0x10, 0x969a); -+ -+ /* RegEEE_slv_wake_tr_timer_tar = 6, RegEEE_slv_remtx_timer_tar = 20 */ -+ __phy_write(phydev, 0x11, 0x3028); -+ __phy_write(phydev, 0x12, 0x0); -+ __phy_write(phydev, 0x10, 0x969e); -+ -+ /* RegEEE_slv_wake_int_timer_tar = 8 */ -+ __phy_write(phydev, 0x11, 0x5010); -+ __phy_write(phydev, 0x12, 0x0); -+ __phy_write(phydev, 0x10, 0x96a0); -+ -+ /* RegEEE_trfreeze_timer2 = 586 */ -+ __phy_write(phydev, 0x11, 0x24a); -+ __phy_write(phydev, 0x12, 0x0); -+ __phy_write(phydev, 0x10, 0x96a8); -+ -+ /* RegEEE100Stg1_tar = 16 */ -+ __phy_write(phydev, 0x11, 0x3210); -+ __phy_write(phydev, 0x12, 0x0); -+ __phy_write(phydev, 0x10, 0x96b8); -+ -+ /* REGEEE_wake_slv_tr_wait_dfesigdet_en = 0 */ -+ __phy_write(phydev, 0x11, 0x1463); -+ __phy_write(phydev, 0x12, 0x0); -+ __phy_write(phydev, 0x10, 0x96ca); -+ -+ /* DfeTailEnableVgaThresh1000 = 27 */ -+ __phy_write(phydev, 0x11, 0x36); -+ __phy_write(phydev, 0x12, 0x0); -+ __phy_write(phydev, 0x10, 0x8f80); -+ phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0); -+ -+ phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_3); -+ __phy_modify(phydev, MTK_PHY_LPI_REG_14, -+ MTK_PHY_LPI_WAKE_TIMER_1000_MASK, -+ FIELD_PREP(MTK_PHY_LPI_WAKE_TIMER_1000_MASK, 0x19c)); -+ -+ __phy_modify(phydev, MTK_PHY_LPI_REG_1c, MTK_PHY_SMI_DET_ON_THRESH_MASK, -+ FIELD_PREP(MTK_PHY_SMI_DET_ON_THRESH_MASK, 0xc)); -+ phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0); -+ -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, -+ MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG122, -+ MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK, -+ FIELD_PREP(MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK, -+ 0xff)); -+} -+ -+static int cal_sw(struct phy_device *phydev, enum CAL_ITEM cal_item, -+ u8 start_pair, u8 end_pair) -+{ -+ u8 pair_n; -+ int ret; -+ -+ for (pair_n = start_pair; pair_n <= end_pair; pair_n++) { -+ /* TX_OFFSET & TX_AMP have no SW calibration. */ -+ switch (cal_item) { -+ case TX_VCM: -+ ret = tx_vcm_cal_sw(phydev, pair_n); -+ break; -+ default: -+ return -EINVAL; -+ } -+ if (ret) -+ return ret; -+ } -+ return 0; -+} -+ -+static int cal_efuse(struct phy_device *phydev, enum CAL_ITEM cal_item, -+ u8 start_pair, u8 end_pair, u32 *buf) -+{ -+ u8 pair_n; -+ int ret; -+ -+ for (pair_n = start_pair; pair_n <= end_pair; pair_n++) { -+ /* TX_VCM has no efuse calibration. */ -+ switch (cal_item) { -+ case REXT: -+ ret = rext_cal_efuse(phydev, buf); -+ break; -+ case TX_OFFSET: -+ ret = tx_offset_cal_efuse(phydev, buf); -+ break; -+ case TX_AMP: -+ ret = tx_amp_cal_efuse(phydev, buf); -+ break; -+ case TX_R50: -+ ret = tx_r50_cal_efuse(phydev, buf, pair_n); -+ break; -+ default: -+ return -EINVAL; -+ } -+ if (ret) -+ return ret; -+ } -+ -+ return 0; -+} -+ -+static int start_cal(struct phy_device *phydev, enum CAL_ITEM cal_item, -+ enum CAL_MODE cal_mode, u8 start_pair, -+ u8 end_pair, u32 *buf) -+{ -+ int ret; -+ -+ switch (cal_mode) { -+ case EFUSE_M: -+ ret = cal_efuse(phydev, cal_item, start_pair, -+ end_pair, buf); -+ break; -+ case SW_M: -+ ret = cal_sw(phydev, cal_item, start_pair, end_pair); -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ if (ret) { -+ phydev_err(phydev, "cal %d failed\n", cal_item); -+ return -EIO; -+ } -+ -+ return 0; -+} -+ -+static int mt798x_phy_calibration(struct phy_device *phydev) -+{ -+ struct nvmem_cell *cell; -+ int ret = 0; -+ size_t len; -+ u32 *buf; -+ -+ cell = nvmem_cell_get(&phydev->mdio.dev, "phy-cal-data"); -+ if (IS_ERR(cell)) { -+ if (PTR_ERR(cell) == -EPROBE_DEFER) -+ return PTR_ERR(cell); -+ return 0; -+ } -+ -+ buf = (u32 *)nvmem_cell_read(cell, &len); -+ if (IS_ERR(buf)) -+ return PTR_ERR(buf); -+ nvmem_cell_put(cell); -+ -+ if (!buf[0] || !buf[1] || !buf[2] || !buf[3] || len < 4 * sizeof(u32)) { -+ phydev_err(phydev, "invalid efuse data\n"); -+ ret = -EINVAL; -+ goto out; -+ } -+ -+ ret = start_cal(phydev, REXT, EFUSE_M, NO_PAIR, NO_PAIR, buf); -+ if (ret) -+ goto out; -+ ret = start_cal(phydev, TX_OFFSET, EFUSE_M, NO_PAIR, NO_PAIR, buf); -+ if (ret) -+ goto out; -+ ret = start_cal(phydev, TX_AMP, EFUSE_M, NO_PAIR, NO_PAIR, buf); -+ if (ret) -+ goto out; -+ ret = start_cal(phydev, TX_R50, EFUSE_M, PAIR_A, PAIR_D, buf); -+ if (ret) -+ goto out; -+ ret = start_cal(phydev, TX_VCM, SW_M, PAIR_A, PAIR_A, buf); -+ if (ret) -+ goto out; -+ -+out: -+ kfree(buf); -+ return ret; -+} -+ -+static int mt798x_phy_config_init(struct phy_device *phydev) -+{ -+ switch (phydev->drv->phy_id) { -+ case MTK_GPHY_ID_MT7981: -+ mt7981_phy_finetune(phydev); -+ break; -+ case MTK_GPHY_ID_MT7988: -+ mt7988_phy_finetune(phydev); -+ break; -+ } -+ -+ mt798x_phy_common_finetune(phydev); -+ mt798x_phy_eee(phydev); -+ -+ return mt798x_phy_calibration(phydev); -+} -+ -+static int mt798x_phy_hw_led_on_set(struct phy_device *phydev, u8 index, -+ bool on) -+{ -+ unsigned int bit_on = MTK_PHY_LED_STATE_FORCE_ON + (index ? 16 : 0); -+ struct mtk_socphy_priv *priv = phydev->priv; -+ bool changed; -+ -+ if (on) -+ changed = !test_and_set_bit(bit_on, &priv->led_state); -+ else -+ changed = !!test_and_clear_bit(bit_on, &priv->led_state); -+ -+ changed |= !!test_and_clear_bit(MTK_PHY_LED_STATE_NETDEV + -+ (index ? 16 : 0), &priv->led_state); -+ if (changed) -+ return phy_modify_mmd(phydev, MDIO_MMD_VEND2, index ? -+ MTK_PHY_LED1_ON_CTRL : -+ MTK_PHY_LED0_ON_CTRL, -+ MTK_PHY_LED_ON_MASK, -+ on ? MTK_PHY_LED_ON_FORCE_ON : 0); -+ else -+ return 0; -+} -+ -+static int mt798x_phy_hw_led_blink_set(struct phy_device *phydev, u8 index, -+ bool blinking) -+{ -+ unsigned int bit_blink = MTK_PHY_LED_STATE_FORCE_BLINK + -+ (index ? 16 : 0); -+ struct mtk_socphy_priv *priv = phydev->priv; -+ bool changed; -+ -+ if (blinking) -+ changed = !test_and_set_bit(bit_blink, &priv->led_state); -+ else -+ changed = !!test_and_clear_bit(bit_blink, &priv->led_state); -+ -+ changed |= !!test_bit(MTK_PHY_LED_STATE_NETDEV + -+ (index ? 16 : 0), &priv->led_state); -+ if (changed) -+ return phy_write_mmd(phydev, MDIO_MMD_VEND2, index ? -+ MTK_PHY_LED1_BLINK_CTRL : -+ MTK_PHY_LED0_BLINK_CTRL, -+ blinking ? -+ MTK_PHY_LED_BLINK_FORCE_BLINK : 0); -+ else -+ return 0; -+} -+ -+static int mt798x_phy_led_blink_set(struct phy_device *phydev, u8 index, -+ unsigned long *delay_on, -+ unsigned long *delay_off) -+{ -+ bool blinking = false; -+ int err = 0; -+ -+ if (index > 1) -+ return -EINVAL; -+ -+ if (delay_on && delay_off && (*delay_on > 0) && (*delay_off > 0)) { -+ blinking = true; -+ *delay_on = 50; -+ *delay_off = 50; -+ } -+ -+ err = mt798x_phy_hw_led_blink_set(phydev, index, blinking); -+ if (err) -+ return err; -+ -+ return mt798x_phy_hw_led_on_set(phydev, index, false); -+} -+ -+static int mt798x_phy_led_brightness_set(struct phy_device *phydev, -+ u8 index, enum led_brightness value) -+{ -+ int err; -+ -+ err = mt798x_phy_hw_led_blink_set(phydev, index, false); -+ if (err) -+ return err; -+ -+ return mt798x_phy_hw_led_on_set(phydev, index, (value != LED_OFF)); -+} -+ -+static const unsigned long supported_triggers = -+ BIT(TRIGGER_NETDEV_FULL_DUPLEX) | -+ BIT(TRIGGER_NETDEV_HALF_DUPLEX) | -+ BIT(TRIGGER_NETDEV_LINK) | -+ BIT(TRIGGER_NETDEV_LINK_10) | -+ BIT(TRIGGER_NETDEV_LINK_100) | -+ BIT(TRIGGER_NETDEV_LINK_1000) | -+ BIT(TRIGGER_NETDEV_RX) | -+ BIT(TRIGGER_NETDEV_TX); -+ -+static int mt798x_phy_led_hw_is_supported(struct phy_device *phydev, u8 index, -+ unsigned long rules) -+{ -+ if (index > 1) -+ return -EINVAL; -+ -+ /* All combinations of the supported triggers are allowed */ -+ if (rules & ~supported_triggers) -+ return -EOPNOTSUPP; -+ -+ return 0; -+}; -+ -+static int mt798x_phy_led_hw_control_get(struct phy_device *phydev, u8 index, -+ unsigned long *rules) -+{ -+ unsigned int bit_blink = MTK_PHY_LED_STATE_FORCE_BLINK + -+ (index ? 16 : 0); -+ unsigned int bit_netdev = MTK_PHY_LED_STATE_NETDEV + (index ? 16 : 0); -+ unsigned int bit_on = MTK_PHY_LED_STATE_FORCE_ON + (index ? 16 : 0); -+ struct mtk_socphy_priv *priv = phydev->priv; -+ int on, blink; -+ -+ if (index > 1) -+ return -EINVAL; -+ -+ on = phy_read_mmd(phydev, MDIO_MMD_VEND2, -+ index ? MTK_PHY_LED1_ON_CTRL : MTK_PHY_LED0_ON_CTRL); -+ -+ if (on < 0) -+ return -EIO; -+ -+ blink = phy_read_mmd(phydev, MDIO_MMD_VEND2, -+ index ? MTK_PHY_LED1_BLINK_CTRL : -+ MTK_PHY_LED0_BLINK_CTRL); -+ if (blink < 0) -+ return -EIO; -+ -+ if ((on & (MTK_PHY_LED_ON_LINK | MTK_PHY_LED_ON_FDX | -+ MTK_PHY_LED_ON_HDX | MTK_PHY_LED_ON_LINKDOWN)) || -+ (blink & (MTK_PHY_LED_BLINK_RX | MTK_PHY_LED_BLINK_TX))) -+ set_bit(bit_netdev, &priv->led_state); -+ else -+ clear_bit(bit_netdev, &priv->led_state); -+ -+ if (on & MTK_PHY_LED_ON_FORCE_ON) -+ set_bit(bit_on, &priv->led_state); -+ else -+ clear_bit(bit_on, &priv->led_state); -+ -+ if (blink & MTK_PHY_LED_BLINK_FORCE_BLINK) -+ set_bit(bit_blink, &priv->led_state); -+ else -+ clear_bit(bit_blink, &priv->led_state); -+ -+ if (!rules) -+ return 0; -+ -+ if (on & MTK_PHY_LED_ON_LINK) -+ *rules |= BIT(TRIGGER_NETDEV_LINK); -+ -+ if (on & MTK_PHY_LED_ON_LINK10) -+ *rules |= BIT(TRIGGER_NETDEV_LINK_10); -+ -+ if (on & MTK_PHY_LED_ON_LINK100) -+ *rules |= BIT(TRIGGER_NETDEV_LINK_100); -+ -+ if (on & MTK_PHY_LED_ON_LINK1000) -+ *rules |= BIT(TRIGGER_NETDEV_LINK_1000); -+ -+ if (on & MTK_PHY_LED_ON_FDX) -+ *rules |= BIT(TRIGGER_NETDEV_FULL_DUPLEX); -+ -+ if (on & MTK_PHY_LED_ON_HDX) -+ *rules |= BIT(TRIGGER_NETDEV_HALF_DUPLEX); -+ -+ if (blink & MTK_PHY_LED_BLINK_RX) -+ *rules |= BIT(TRIGGER_NETDEV_RX); -+ -+ if (blink & MTK_PHY_LED_BLINK_TX) -+ *rules |= BIT(TRIGGER_NETDEV_TX); -+ -+ return 0; -+}; -+ -+static int mt798x_phy_led_hw_control_set(struct phy_device *phydev, u8 index, -+ unsigned long rules) -+{ -+ unsigned int bit_netdev = MTK_PHY_LED_STATE_NETDEV + (index ? 16 : 0); -+ struct mtk_socphy_priv *priv = phydev->priv; -+ u16 on = 0, blink = 0; -+ int ret; -+ -+ if (index > 1) -+ return -EINVAL; -+ -+ if (rules & BIT(TRIGGER_NETDEV_FULL_DUPLEX)) -+ on |= MTK_PHY_LED_ON_FDX; -+ -+ if (rules & BIT(TRIGGER_NETDEV_HALF_DUPLEX)) -+ on |= MTK_PHY_LED_ON_HDX; -+ -+ if (rules & (BIT(TRIGGER_NETDEV_LINK_10) | BIT(TRIGGER_NETDEV_LINK))) -+ on |= MTK_PHY_LED_ON_LINK10; -+ -+ if (rules & (BIT(TRIGGER_NETDEV_LINK_100) | BIT(TRIGGER_NETDEV_LINK))) -+ on |= MTK_PHY_LED_ON_LINK100; -+ -+ if (rules & (BIT(TRIGGER_NETDEV_LINK_1000) | BIT(TRIGGER_NETDEV_LINK))) -+ on |= MTK_PHY_LED_ON_LINK1000; -+ -+ if (rules & BIT(TRIGGER_NETDEV_RX)) { -+ blink |= (on & MTK_PHY_LED_ON_LINK) ? -+ (((on & MTK_PHY_LED_ON_LINK10) ? -+ MTK_PHY_LED_BLINK_10RX : 0) | -+ ((on & MTK_PHY_LED_ON_LINK100) ? -+ MTK_PHY_LED_BLINK_100RX : 0) | -+ ((on & MTK_PHY_LED_ON_LINK1000) ? -+ MTK_PHY_LED_BLINK_1000RX : 0)) : -+ MTK_PHY_LED_BLINK_RX; -+ } -+ -+ if (rules & BIT(TRIGGER_NETDEV_TX)) { -+ blink |= (on & MTK_PHY_LED_ON_LINK) ? -+ (((on & MTK_PHY_LED_ON_LINK10) ? -+ MTK_PHY_LED_BLINK_10TX : 0) | -+ ((on & MTK_PHY_LED_ON_LINK100) ? -+ MTK_PHY_LED_BLINK_100TX : 0) | -+ ((on & MTK_PHY_LED_ON_LINK1000) ? -+ MTK_PHY_LED_BLINK_1000TX : 0)) : -+ MTK_PHY_LED_BLINK_TX; -+ } -+ -+ if (blink || on) -+ set_bit(bit_netdev, &priv->led_state); -+ else -+ clear_bit(bit_netdev, &priv->led_state); -+ -+ ret = phy_modify_mmd(phydev, MDIO_MMD_VEND2, index ? -+ MTK_PHY_LED1_ON_CTRL : -+ MTK_PHY_LED0_ON_CTRL, -+ MTK_PHY_LED_ON_FDX | -+ MTK_PHY_LED_ON_HDX | -+ MTK_PHY_LED_ON_LINK, -+ on); -+ -+ if (ret) -+ return ret; -+ -+ return phy_write_mmd(phydev, MDIO_MMD_VEND2, index ? -+ MTK_PHY_LED1_BLINK_CTRL : -+ MTK_PHY_LED0_BLINK_CTRL, blink); -+}; -+ -+static bool mt7988_phy_led_get_polarity(struct phy_device *phydev, int led_num) -+{ -+ struct mtk_socphy_shared *priv = phydev->shared->priv; -+ u32 polarities; -+ -+ if (led_num == 0) -+ polarities = ~(priv->boottrap); -+ else -+ polarities = MTK_PHY_LED1_DEFAULT_POLARITIES; -+ -+ if (polarities & BIT(phydev->mdio.addr)) -+ return true; -+ -+ return false; -+} -+ -+static int mt7988_phy_fix_leds_polarities(struct phy_device *phydev) -+{ -+ struct pinctrl *pinctrl; -+ int index; -+ -+ /* Setup LED polarity according to bootstrap use of LED pins */ -+ for (index = 0; index < 2; ++index) -+ phy_modify_mmd(phydev, MDIO_MMD_VEND2, index ? -+ MTK_PHY_LED1_ON_CTRL : MTK_PHY_LED0_ON_CTRL, -+ MTK_PHY_LED_ON_POLARITY, -+ mt7988_phy_led_get_polarity(phydev, index) ? -+ MTK_PHY_LED_ON_POLARITY : 0); -+ -+ /* Only now setup pinctrl to avoid bogus blinking */ -+ pinctrl = devm_pinctrl_get_select(&phydev->mdio.dev, "gbe-led"); -+ if (IS_ERR(pinctrl)) -+ dev_err(&phydev->mdio.bus->dev, -+ "Failed to setup PHY LED pinctrl\n"); -+ -+ return 0; -+} -+ -+static int mt7988_phy_probe_shared(struct phy_device *phydev) -+{ -+ struct device_node *np = dev_of_node(&phydev->mdio.bus->dev); -+ struct mtk_socphy_shared *shared = phydev->shared->priv; -+ struct regmap *regmap; -+ u32 reg; -+ int ret; -+ -+ /* The LED0 of the 4 PHYs in MT7988 are wired to SoC pins LED_A, LED_B, -+ * LED_C and LED_D respectively. At the same time those pins are used to -+ * bootstrap configuration of the reference clock source (LED_A), -+ * DRAM DDRx16b x2/x1 (LED_B) and boot device (LED_C, LED_D). -+ * In practice this is done using a LED and a resistor pulling the pin -+ * either to GND or to VIO. -+ * The detected value at boot time is accessible at run-time using the -+ * TPBANK0 register located in the gpio base of the pinctrl, in order -+ * to read it here it needs to be referenced by a phandle called -+ * 'mediatek,pio' in the MDIO bus hosting the PHY. -+ * The 4 bits in TPBANK0 are kept as package shared data and are used to -+ * set LED polarity for each of the LED0. -+ */ -+ regmap = syscon_regmap_lookup_by_phandle(np, "mediatek,pio"); -+ if (IS_ERR(regmap)) -+ return PTR_ERR(regmap); -+ -+ ret = regmap_read(regmap, RG_GPIO_MISC_TPBANK0, ®); -+ if (ret) -+ return ret; -+ -+ shared->boottrap = FIELD_GET(RG_GPIO_MISC_TPBANK0_BOOTMODE, reg); -+ -+ return 0; -+} -+ -+static void mt798x_phy_leds_state_init(struct phy_device *phydev) -+{ -+ int i; -+ -+ for (i = 0; i < 2; ++i) -+ mt798x_phy_led_hw_control_get(phydev, i, NULL); -+} -+ -+static int mt7988_phy_probe(struct phy_device *phydev) -+{ -+ struct mtk_socphy_shared *shared; -+ struct mtk_socphy_priv *priv; -+ int err; -+ -+ if (phydev->mdio.addr > 3) -+ return -EINVAL; -+ -+ err = devm_phy_package_join(&phydev->mdio.dev, phydev, 0, -+ sizeof(struct mtk_socphy_shared)); -+ if (err) -+ return err; -+ -+ if (phy_package_probe_once(phydev)) { -+ err = mt7988_phy_probe_shared(phydev); -+ if (err) -+ return err; -+ } -+ -+ shared = phydev->shared->priv; -+ priv = &shared->priv[phydev->mdio.addr]; -+ -+ phydev->priv = priv; -+ -+ mt798x_phy_leds_state_init(phydev); -+ -+ err = mt7988_phy_fix_leds_polarities(phydev); -+ if (err) -+ return err; -+ -+ /* Disable TX power saving at probing to: -+ * 1. Meet common mode compliance test criteria -+ * 2. Make sure that TX-VCM calibration works fine -+ */ -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RXADC_CTRL_RG7, -+ MTK_PHY_DA_AD_BUF_BIAS_LP_MASK, 0x3 << 8); -+ -+ return mt798x_phy_calibration(phydev); -+} -+ -+static int mt7981_phy_probe(struct phy_device *phydev) -+{ -+ struct mtk_socphy_priv *priv; -+ -+ priv = devm_kzalloc(&phydev->mdio.dev, sizeof(struct mtk_socphy_priv), -+ GFP_KERNEL); -+ if (!priv) -+ return -ENOMEM; -+ -+ phydev->priv = priv; -+ -+ mt798x_phy_leds_state_init(phydev); -+ -+ return mt798x_phy_calibration(phydev); -+} -+ -+static struct phy_driver mtk_socphy_driver[] = { -+ { -+ PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7981), -+ .name = "MediaTek MT7981 PHY", -+ .config_init = mt798x_phy_config_init, -+ .config_intr = genphy_no_config_intr, -+ .handle_interrupt = genphy_handle_interrupt_no_ack, -+ .probe = mt7981_phy_probe, -+ .suspend = genphy_suspend, -+ .resume = genphy_resume, -+ .read_page = mtk_socphy_read_page, -+ .write_page = mtk_socphy_write_page, -+ .led_blink_set = mt798x_phy_led_blink_set, -+ .led_brightness_set = mt798x_phy_led_brightness_set, -+ .led_hw_is_supported = mt798x_phy_led_hw_is_supported, -+ .led_hw_control_set = mt798x_phy_led_hw_control_set, -+ .led_hw_control_get = mt798x_phy_led_hw_control_get, -+ }, -+ { -+ PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7988), -+ .name = "MediaTek MT7988 PHY", -+ .config_init = mt798x_phy_config_init, -+ .config_intr = genphy_no_config_intr, -+ .handle_interrupt = genphy_handle_interrupt_no_ack, -+ .probe = mt7988_phy_probe, -+ .suspend = genphy_suspend, -+ .resume = genphy_resume, -+ .read_page = mtk_socphy_read_page, -+ .write_page = mtk_socphy_write_page, -+ .led_blink_set = mt798x_phy_led_blink_set, -+ .led_brightness_set = mt798x_phy_led_brightness_set, -+ .led_hw_is_supported = mt798x_phy_led_hw_is_supported, -+ .led_hw_control_set = mt798x_phy_led_hw_control_set, -+ .led_hw_control_get = mt798x_phy_led_hw_control_get, -+ }, -+}; -+ -+module_phy_driver(mtk_socphy_driver); -+ -+static struct mdio_device_id __maybe_unused mtk_socphy_tbl[] = { -+ { PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7981) }, -+ { PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7988) }, -+ { } -+}; -+ -+MODULE_DESCRIPTION("MediaTek SoC Gigabit Ethernet PHY driver"); -+MODULE_AUTHOR("Daniel Golle "); -+MODULE_AUTHOR("SkyLake Huang "); -+MODULE_LICENSE("GPL"); -+ -+MODULE_DEVICE_TABLE(mdio, mtk_socphy_tbl); ---- /dev/null -+++ b/drivers/net/phy/mediatek/mtk-ge.c -@@ -0,0 +1,111 @@ -+// SPDX-License-Identifier: GPL-2.0+ -+#include -+#include -+#include -+ -+#define MTK_EXT_PAGE_ACCESS 0x1f -+#define MTK_PHY_PAGE_STANDARD 0x0000 -+#define MTK_PHY_PAGE_EXTENDED 0x0001 -+#define MTK_PHY_PAGE_EXTENDED_2 0x0002 -+#define MTK_PHY_PAGE_EXTENDED_3 0x0003 -+#define MTK_PHY_PAGE_EXTENDED_2A30 0x2a30 -+#define MTK_PHY_PAGE_EXTENDED_52B5 0x52b5 -+ -+static int mtk_gephy_read_page(struct phy_device *phydev) -+{ -+ return __phy_read(phydev, MTK_EXT_PAGE_ACCESS); -+} -+ -+static int mtk_gephy_write_page(struct phy_device *phydev, int page) -+{ -+ return __phy_write(phydev, MTK_EXT_PAGE_ACCESS, page); -+} -+ -+static void mtk_gephy_config_init(struct phy_device *phydev) -+{ -+ /* Enable HW auto downshift */ -+ phy_modify_paged(phydev, MTK_PHY_PAGE_EXTENDED, 0x14, 0, BIT(4)); -+ -+ /* Increase SlvDPSready time */ -+ phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5); -+ __phy_write(phydev, 0x10, 0xafae); -+ __phy_write(phydev, 0x12, 0x2f); -+ __phy_write(phydev, 0x10, 0x8fae); -+ phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0); -+ -+ /* Adjust 100_mse_threshold */ -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x123, 0xffff); -+ -+ /* Disable mcc */ -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0xa6, 0x300); -+} -+ -+static int mt7530_phy_config_init(struct phy_device *phydev) -+{ -+ mtk_gephy_config_init(phydev); -+ -+ /* Increase post_update_timer */ -+ phy_write_paged(phydev, MTK_PHY_PAGE_EXTENDED_3, 0x11, 0x4b); -+ -+ return 0; -+} -+ -+static int mt7531_phy_config_init(struct phy_device *phydev) -+{ -+ mtk_gephy_config_init(phydev); -+ -+ /* PHY link down power saving enable */ -+ phy_set_bits(phydev, 0x17, BIT(4)); -+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, 0xc6, 0x300); -+ -+ /* Set TX Pair delay selection */ -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x13, 0x404); -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x14, 0x404); -+ -+ return 0; -+} -+ -+static struct phy_driver mtk_gephy_driver[] = { -+ { -+ PHY_ID_MATCH_EXACT(0x03a29412), -+ .name = "MediaTek MT7530 PHY", -+ .config_init = mt7530_phy_config_init, -+ /* Interrupts are handled by the switch, not the PHY -+ * itself. -+ */ -+ .config_intr = genphy_no_config_intr, -+ .handle_interrupt = genphy_handle_interrupt_no_ack, -+ .suspend = genphy_suspend, -+ .resume = genphy_resume, -+ .read_page = mtk_gephy_read_page, -+ .write_page = mtk_gephy_write_page, -+ }, -+ { -+ PHY_ID_MATCH_EXACT(0x03a29441), -+ .name = "MediaTek MT7531 PHY", -+ .config_init = mt7531_phy_config_init, -+ /* Interrupts are handled by the switch, not the PHY -+ * itself. -+ */ -+ .config_intr = genphy_no_config_intr, -+ .handle_interrupt = genphy_handle_interrupt_no_ack, -+ .suspend = genphy_suspend, -+ .resume = genphy_resume, -+ .read_page = mtk_gephy_read_page, -+ .write_page = mtk_gephy_write_page, -+ }, -+}; -+ -+module_phy_driver(mtk_gephy_driver); -+ -+static struct mdio_device_id __maybe_unused mtk_gephy_tbl[] = { -+ { PHY_ID_MATCH_EXACT(0x03a29441) }, -+ { PHY_ID_MATCH_EXACT(0x03a29412) }, -+ { } -+}; -+ -+MODULE_DESCRIPTION("MediaTek Gigabit Ethernet PHY driver"); -+MODULE_AUTHOR("DENG, Qingfang "); -+MODULE_LICENSE("GPL"); -+ -+MODULE_DEVICE_TABLE(mdio, mtk_gephy_tbl); diff --git a/target/linux/generic/backport-6.18/720-05-v6.13-net-phy-mediatek-Move-LED-helper-functions-into-mtk-.patch b/target/linux/generic/backport-6.18/720-05-v6.13-net-phy-mediatek-Move-LED-helper-functions-into-mtk-.patch deleted file mode 100644 index 63407ac55c..0000000000 --- a/target/linux/generic/backport-6.18/720-05-v6.13-net-phy-mediatek-Move-LED-helper-functions-into-mtk-.patch +++ /dev/null @@ -1,774 +0,0 @@ -From 71d88c7409b91c853d7f9c933f5e27933d656e5e Mon Sep 17 00:00:00 2001 -From: "SkyLake.Huang" -Date: Sat, 9 Nov 2024 00:34:52 +0800 -Subject: [PATCH 05/20] net: phy: mediatek: Move LED helper functions into mtk - phy lib - -This patch creates mtk-phy-lib.c & mtk-phy.h and integrates mtk-ge-soc.c's -LED helper functions so that we can use those helper functions in other -MTK's ethernet phy driver. - -Reviewed-by: Andrew Lunn -Signed-off-by: SkyLake.Huang -Signed-off-by: David S. Miller ---- - MAINTAINERS | 2 + - drivers/net/phy/mediatek/Kconfig | 4 + - drivers/net/phy/mediatek/Makefile | 1 + - drivers/net/phy/mediatek/mtk-ge-soc.c | 280 +++---------------------- - drivers/net/phy/mediatek/mtk-phy-lib.c | 254 ++++++++++++++++++++++ - drivers/net/phy/mediatek/mtk.h | 86 ++++++++ - 6 files changed, 372 insertions(+), 255 deletions(-) - create mode 100644 drivers/net/phy/mediatek/mtk-phy-lib.c - create mode 100644 drivers/net/phy/mediatek/mtk.h - ---- a/MAINTAINERS -+++ b/MAINTAINERS -@@ -14428,7 +14428,9 @@ M: SkyLake Huang - #include - -+#include "mtk.h" -+ - #define MTK_GPHY_ID_MT7981 0x03a29461 - #define MTK_GPHY_ID_MT7988 0x03a29481 - -@@ -210,41 +212,6 @@ - #define MTK_PHY_DA_TX_R50_PAIR_D 0x540 - - /* Registers on MDIO_MMD_VEND2 */ --#define MTK_PHY_LED0_ON_CTRL 0x24 --#define MTK_PHY_LED1_ON_CTRL 0x26 --#define MTK_PHY_LED_ON_MASK GENMASK(6, 0) --#define MTK_PHY_LED_ON_LINK1000 BIT(0) --#define MTK_PHY_LED_ON_LINK100 BIT(1) --#define MTK_PHY_LED_ON_LINK10 BIT(2) --#define MTK_PHY_LED_ON_LINK (MTK_PHY_LED_ON_LINK10 |\ -- MTK_PHY_LED_ON_LINK100 |\ -- MTK_PHY_LED_ON_LINK1000) --#define MTK_PHY_LED_ON_LINKDOWN BIT(3) --#define MTK_PHY_LED_ON_FDX BIT(4) /* Full duplex */ --#define MTK_PHY_LED_ON_HDX BIT(5) /* Half duplex */ --#define MTK_PHY_LED_ON_FORCE_ON BIT(6) --#define MTK_PHY_LED_ON_POLARITY BIT(14) --#define MTK_PHY_LED_ON_ENABLE BIT(15) -- --#define MTK_PHY_LED0_BLINK_CTRL 0x25 --#define MTK_PHY_LED1_BLINK_CTRL 0x27 --#define MTK_PHY_LED_BLINK_1000TX BIT(0) --#define MTK_PHY_LED_BLINK_1000RX BIT(1) --#define MTK_PHY_LED_BLINK_100TX BIT(2) --#define MTK_PHY_LED_BLINK_100RX BIT(3) --#define MTK_PHY_LED_BLINK_10TX BIT(4) --#define MTK_PHY_LED_BLINK_10RX BIT(5) --#define MTK_PHY_LED_BLINK_RX (MTK_PHY_LED_BLINK_10RX |\ -- MTK_PHY_LED_BLINK_100RX |\ -- MTK_PHY_LED_BLINK_1000RX) --#define MTK_PHY_LED_BLINK_TX (MTK_PHY_LED_BLINK_10TX |\ -- MTK_PHY_LED_BLINK_100TX |\ -- MTK_PHY_LED_BLINK_1000TX) --#define MTK_PHY_LED_BLINK_COLLISION BIT(6) --#define MTK_PHY_LED_BLINK_RX_CRC_ERR BIT(7) --#define MTK_PHY_LED_BLINK_RX_IDLE_ERR BIT(8) --#define MTK_PHY_LED_BLINK_FORCE_BLINK BIT(9) -- - #define MTK_PHY_LED1_DEFAULT_POLARITIES BIT(1) - - #define MTK_PHY_RG_BG_RASEL 0x115 -@@ -299,14 +266,6 @@ enum CAL_MODE { - SW_M - }; - --#define MTK_PHY_LED_STATE_FORCE_ON 0 --#define MTK_PHY_LED_STATE_FORCE_BLINK 1 --#define MTK_PHY_LED_STATE_NETDEV 2 -- --struct mtk_socphy_priv { -- unsigned long led_state; --}; -- - struct mtk_socphy_shared { - u32 boottrap; - struct mtk_socphy_priv priv[4]; -@@ -1172,76 +1131,23 @@ static int mt798x_phy_config_init(struct - return mt798x_phy_calibration(phydev); - } - --static int mt798x_phy_hw_led_on_set(struct phy_device *phydev, u8 index, -- bool on) --{ -- unsigned int bit_on = MTK_PHY_LED_STATE_FORCE_ON + (index ? 16 : 0); -- struct mtk_socphy_priv *priv = phydev->priv; -- bool changed; -- -- if (on) -- changed = !test_and_set_bit(bit_on, &priv->led_state); -- else -- changed = !!test_and_clear_bit(bit_on, &priv->led_state); -- -- changed |= !!test_and_clear_bit(MTK_PHY_LED_STATE_NETDEV + -- (index ? 16 : 0), &priv->led_state); -- if (changed) -- return phy_modify_mmd(phydev, MDIO_MMD_VEND2, index ? -- MTK_PHY_LED1_ON_CTRL : -- MTK_PHY_LED0_ON_CTRL, -- MTK_PHY_LED_ON_MASK, -- on ? MTK_PHY_LED_ON_FORCE_ON : 0); -- else -- return 0; --} -- --static int mt798x_phy_hw_led_blink_set(struct phy_device *phydev, u8 index, -- bool blinking) --{ -- unsigned int bit_blink = MTK_PHY_LED_STATE_FORCE_BLINK + -- (index ? 16 : 0); -- struct mtk_socphy_priv *priv = phydev->priv; -- bool changed; -- -- if (blinking) -- changed = !test_and_set_bit(bit_blink, &priv->led_state); -- else -- changed = !!test_and_clear_bit(bit_blink, &priv->led_state); -- -- changed |= !!test_bit(MTK_PHY_LED_STATE_NETDEV + -- (index ? 16 : 0), &priv->led_state); -- if (changed) -- return phy_write_mmd(phydev, MDIO_MMD_VEND2, index ? -- MTK_PHY_LED1_BLINK_CTRL : -- MTK_PHY_LED0_BLINK_CTRL, -- blinking ? -- MTK_PHY_LED_BLINK_FORCE_BLINK : 0); -- else -- return 0; --} -- - static int mt798x_phy_led_blink_set(struct phy_device *phydev, u8 index, - unsigned long *delay_on, - unsigned long *delay_off) - { - bool blinking = false; -- int err = 0; -- -- if (index > 1) -- return -EINVAL; -+ int err; - -- if (delay_on && delay_off && (*delay_on > 0) && (*delay_off > 0)) { -- blinking = true; -- *delay_on = 50; -- *delay_off = 50; -- } -+ err = mtk_phy_led_num_dly_cfg(index, delay_on, delay_off, &blinking); -+ if (err < 0) -+ return err; - -- err = mt798x_phy_hw_led_blink_set(phydev, index, blinking); -+ err = mtk_phy_hw_led_blink_set(phydev, index, blinking); - if (err) - return err; - -- return mt798x_phy_hw_led_on_set(phydev, index, false); -+ return mtk_phy_hw_led_on_set(phydev, index, MTK_GPHY_LED_ON_MASK, -+ false); - } - - static int mt798x_phy_led_brightness_set(struct phy_device *phydev, -@@ -1249,11 +1155,12 @@ static int mt798x_phy_led_brightness_set - { - int err; - -- err = mt798x_phy_hw_led_blink_set(phydev, index, false); -+ err = mtk_phy_hw_led_blink_set(phydev, index, false); - if (err) - return err; - -- return mt798x_phy_hw_led_on_set(phydev, index, (value != LED_OFF)); -+ return mtk_phy_hw_led_on_set(phydev, index, MTK_GPHY_LED_ON_MASK, -+ (value != LED_OFF)); - } - - static const unsigned long supported_triggers = -@@ -1269,155 +1176,26 @@ static const unsigned long supported_tri - static int mt798x_phy_led_hw_is_supported(struct phy_device *phydev, u8 index, - unsigned long rules) - { -- if (index > 1) -- return -EINVAL; -- -- /* All combinations of the supported triggers are allowed */ -- if (rules & ~supported_triggers) -- return -EOPNOTSUPP; -- -- return 0; --}; -+ return mtk_phy_led_hw_is_supported(phydev, index, rules, -+ supported_triggers); -+} - - static int mt798x_phy_led_hw_control_get(struct phy_device *phydev, u8 index, - unsigned long *rules) - { -- unsigned int bit_blink = MTK_PHY_LED_STATE_FORCE_BLINK + -- (index ? 16 : 0); -- unsigned int bit_netdev = MTK_PHY_LED_STATE_NETDEV + (index ? 16 : 0); -- unsigned int bit_on = MTK_PHY_LED_STATE_FORCE_ON + (index ? 16 : 0); -- struct mtk_socphy_priv *priv = phydev->priv; -- int on, blink; -- -- if (index > 1) -- return -EINVAL; -- -- on = phy_read_mmd(phydev, MDIO_MMD_VEND2, -- index ? MTK_PHY_LED1_ON_CTRL : MTK_PHY_LED0_ON_CTRL); -- -- if (on < 0) -- return -EIO; -- -- blink = phy_read_mmd(phydev, MDIO_MMD_VEND2, -- index ? MTK_PHY_LED1_BLINK_CTRL : -- MTK_PHY_LED0_BLINK_CTRL); -- if (blink < 0) -- return -EIO; -- -- if ((on & (MTK_PHY_LED_ON_LINK | MTK_PHY_LED_ON_FDX | -- MTK_PHY_LED_ON_HDX | MTK_PHY_LED_ON_LINKDOWN)) || -- (blink & (MTK_PHY_LED_BLINK_RX | MTK_PHY_LED_BLINK_TX))) -- set_bit(bit_netdev, &priv->led_state); -- else -- clear_bit(bit_netdev, &priv->led_state); -- -- if (on & MTK_PHY_LED_ON_FORCE_ON) -- set_bit(bit_on, &priv->led_state); -- else -- clear_bit(bit_on, &priv->led_state); -- -- if (blink & MTK_PHY_LED_BLINK_FORCE_BLINK) -- set_bit(bit_blink, &priv->led_state); -- else -- clear_bit(bit_blink, &priv->led_state); -- -- if (!rules) -- return 0; -- -- if (on & MTK_PHY_LED_ON_LINK) -- *rules |= BIT(TRIGGER_NETDEV_LINK); -- -- if (on & MTK_PHY_LED_ON_LINK10) -- *rules |= BIT(TRIGGER_NETDEV_LINK_10); -- -- if (on & MTK_PHY_LED_ON_LINK100) -- *rules |= BIT(TRIGGER_NETDEV_LINK_100); -- -- if (on & MTK_PHY_LED_ON_LINK1000) -- *rules |= BIT(TRIGGER_NETDEV_LINK_1000); -- -- if (on & MTK_PHY_LED_ON_FDX) -- *rules |= BIT(TRIGGER_NETDEV_FULL_DUPLEX); -- -- if (on & MTK_PHY_LED_ON_HDX) -- *rules |= BIT(TRIGGER_NETDEV_HALF_DUPLEX); -- -- if (blink & MTK_PHY_LED_BLINK_RX) -- *rules |= BIT(TRIGGER_NETDEV_RX); -- -- if (blink & MTK_PHY_LED_BLINK_TX) -- *rules |= BIT(TRIGGER_NETDEV_TX); -- -- return 0; -+ return mtk_phy_led_hw_ctrl_get(phydev, index, rules, -+ MTK_GPHY_LED_ON_SET, -+ MTK_GPHY_LED_RX_BLINK_SET, -+ MTK_GPHY_LED_TX_BLINK_SET); - }; - - static int mt798x_phy_led_hw_control_set(struct phy_device *phydev, u8 index, - unsigned long rules) - { -- unsigned int bit_netdev = MTK_PHY_LED_STATE_NETDEV + (index ? 16 : 0); -- struct mtk_socphy_priv *priv = phydev->priv; -- u16 on = 0, blink = 0; -- int ret; -- -- if (index > 1) -- return -EINVAL; -- -- if (rules & BIT(TRIGGER_NETDEV_FULL_DUPLEX)) -- on |= MTK_PHY_LED_ON_FDX; -- -- if (rules & BIT(TRIGGER_NETDEV_HALF_DUPLEX)) -- on |= MTK_PHY_LED_ON_HDX; -- -- if (rules & (BIT(TRIGGER_NETDEV_LINK_10) | BIT(TRIGGER_NETDEV_LINK))) -- on |= MTK_PHY_LED_ON_LINK10; -- -- if (rules & (BIT(TRIGGER_NETDEV_LINK_100) | BIT(TRIGGER_NETDEV_LINK))) -- on |= MTK_PHY_LED_ON_LINK100; -- -- if (rules & (BIT(TRIGGER_NETDEV_LINK_1000) | BIT(TRIGGER_NETDEV_LINK))) -- on |= MTK_PHY_LED_ON_LINK1000; -- -- if (rules & BIT(TRIGGER_NETDEV_RX)) { -- blink |= (on & MTK_PHY_LED_ON_LINK) ? -- (((on & MTK_PHY_LED_ON_LINK10) ? -- MTK_PHY_LED_BLINK_10RX : 0) | -- ((on & MTK_PHY_LED_ON_LINK100) ? -- MTK_PHY_LED_BLINK_100RX : 0) | -- ((on & MTK_PHY_LED_ON_LINK1000) ? -- MTK_PHY_LED_BLINK_1000RX : 0)) : -- MTK_PHY_LED_BLINK_RX; -- } -- -- if (rules & BIT(TRIGGER_NETDEV_TX)) { -- blink |= (on & MTK_PHY_LED_ON_LINK) ? -- (((on & MTK_PHY_LED_ON_LINK10) ? -- MTK_PHY_LED_BLINK_10TX : 0) | -- ((on & MTK_PHY_LED_ON_LINK100) ? -- MTK_PHY_LED_BLINK_100TX : 0) | -- ((on & MTK_PHY_LED_ON_LINK1000) ? -- MTK_PHY_LED_BLINK_1000TX : 0)) : -- MTK_PHY_LED_BLINK_TX; -- } -- -- if (blink || on) -- set_bit(bit_netdev, &priv->led_state); -- else -- clear_bit(bit_netdev, &priv->led_state); -- -- ret = phy_modify_mmd(phydev, MDIO_MMD_VEND2, index ? -- MTK_PHY_LED1_ON_CTRL : -- MTK_PHY_LED0_ON_CTRL, -- MTK_PHY_LED_ON_FDX | -- MTK_PHY_LED_ON_HDX | -- MTK_PHY_LED_ON_LINK, -- on); -- -- if (ret) -- return ret; -- -- return phy_write_mmd(phydev, MDIO_MMD_VEND2, index ? -- MTK_PHY_LED1_BLINK_CTRL : -- MTK_PHY_LED0_BLINK_CTRL, blink); -+ return mtk_phy_led_hw_ctrl_set(phydev, index, rules, -+ MTK_GPHY_LED_ON_SET, -+ MTK_GPHY_LED_RX_BLINK_SET, -+ MTK_GPHY_LED_TX_BLINK_SET); - }; - - static bool mt7988_phy_led_get_polarity(struct phy_device *phydev, int led_num) -@@ -1492,14 +1270,6 @@ static int mt7988_phy_probe_shared(struc - return 0; - } - --static void mt798x_phy_leds_state_init(struct phy_device *phydev) --{ -- int i; -- -- for (i = 0; i < 2; ++i) -- mt798x_phy_led_hw_control_get(phydev, i, NULL); --} -- - static int mt7988_phy_probe(struct phy_device *phydev) - { - struct mtk_socphy_shared *shared; -@@ -1525,7 +1295,7 @@ static int mt7988_phy_probe(struct phy_d - - phydev->priv = priv; - -- mt798x_phy_leds_state_init(phydev); -+ mtk_phy_leds_state_init(phydev); - - err = mt7988_phy_fix_leds_polarities(phydev); - if (err) -@@ -1552,7 +1322,7 @@ static int mt7981_phy_probe(struct phy_d - - phydev->priv = priv; - -- mt798x_phy_leds_state_init(phydev); -+ mtk_phy_leds_state_init(phydev); - - return mt798x_phy_calibration(phydev); - } ---- /dev/null -+++ b/drivers/net/phy/mediatek/mtk-phy-lib.c -@@ -0,0 +1,254 @@ -+// SPDX-License-Identifier: GPL-2.0 -+#include -+#include -+ -+#include -+ -+#include "mtk.h" -+ -+int mtk_phy_led_hw_is_supported(struct phy_device *phydev, u8 index, -+ unsigned long rules, -+ unsigned long supported_triggers) -+{ -+ if (index > 1) -+ return -EINVAL; -+ -+ /* All combinations of the supported triggers are allowed */ -+ if (rules & ~supported_triggers) -+ return -EOPNOTSUPP; -+ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(mtk_phy_led_hw_is_supported); -+ -+int mtk_phy_led_hw_ctrl_get(struct phy_device *phydev, u8 index, -+ unsigned long *rules, u16 on_set, -+ u16 rx_blink_set, u16 tx_blink_set) -+{ -+ unsigned int bit_blink = MTK_PHY_LED_STATE_FORCE_BLINK + -+ (index ? 16 : 0); -+ unsigned int bit_netdev = MTK_PHY_LED_STATE_NETDEV + (index ? 16 : 0); -+ unsigned int bit_on = MTK_PHY_LED_STATE_FORCE_ON + (index ? 16 : 0); -+ struct mtk_socphy_priv *priv = phydev->priv; -+ int on, blink; -+ -+ if (index > 1) -+ return -EINVAL; -+ -+ on = phy_read_mmd(phydev, MDIO_MMD_VEND2, -+ index ? MTK_PHY_LED1_ON_CTRL : MTK_PHY_LED0_ON_CTRL); -+ -+ if (on < 0) -+ return -EIO; -+ -+ blink = phy_read_mmd(phydev, MDIO_MMD_VEND2, -+ index ? MTK_PHY_LED1_BLINK_CTRL : -+ MTK_PHY_LED0_BLINK_CTRL); -+ if (blink < 0) -+ return -EIO; -+ -+ if ((on & (on_set | MTK_PHY_LED_ON_FDX | -+ MTK_PHY_LED_ON_HDX | MTK_PHY_LED_ON_LINKDOWN)) || -+ (blink & (rx_blink_set | tx_blink_set))) -+ set_bit(bit_netdev, &priv->led_state); -+ else -+ clear_bit(bit_netdev, &priv->led_state); -+ -+ if (on & MTK_PHY_LED_ON_FORCE_ON) -+ set_bit(bit_on, &priv->led_state); -+ else -+ clear_bit(bit_on, &priv->led_state); -+ -+ if (blink & MTK_PHY_LED_BLINK_FORCE_BLINK) -+ set_bit(bit_blink, &priv->led_state); -+ else -+ clear_bit(bit_blink, &priv->led_state); -+ -+ if (!rules) -+ return 0; -+ -+ if (on & on_set) -+ *rules |= BIT(TRIGGER_NETDEV_LINK); -+ -+ if (on & MTK_PHY_LED_ON_LINK10) -+ *rules |= BIT(TRIGGER_NETDEV_LINK_10); -+ -+ if (on & MTK_PHY_LED_ON_LINK100) -+ *rules |= BIT(TRIGGER_NETDEV_LINK_100); -+ -+ if (on & MTK_PHY_LED_ON_LINK1000) -+ *rules |= BIT(TRIGGER_NETDEV_LINK_1000); -+ -+ if (on & MTK_PHY_LED_ON_LINK2500) -+ *rules |= BIT(TRIGGER_NETDEV_LINK_2500); -+ -+ if (on & MTK_PHY_LED_ON_FDX) -+ *rules |= BIT(TRIGGER_NETDEV_FULL_DUPLEX); -+ -+ if (on & MTK_PHY_LED_ON_HDX) -+ *rules |= BIT(TRIGGER_NETDEV_HALF_DUPLEX); -+ -+ if (blink & rx_blink_set) -+ *rules |= BIT(TRIGGER_NETDEV_RX); -+ -+ if (blink & tx_blink_set) -+ *rules |= BIT(TRIGGER_NETDEV_TX); -+ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(mtk_phy_led_hw_ctrl_get); -+ -+int mtk_phy_led_hw_ctrl_set(struct phy_device *phydev, u8 index, -+ unsigned long rules, u16 on_set, -+ u16 rx_blink_set, u16 tx_blink_set) -+{ -+ unsigned int bit_netdev = MTK_PHY_LED_STATE_NETDEV + (index ? 16 : 0); -+ struct mtk_socphy_priv *priv = phydev->priv; -+ u16 on = 0, blink = 0; -+ int ret; -+ -+ if (index > 1) -+ return -EINVAL; -+ -+ if (rules & BIT(TRIGGER_NETDEV_FULL_DUPLEX)) -+ on |= MTK_PHY_LED_ON_FDX; -+ -+ if (rules & BIT(TRIGGER_NETDEV_HALF_DUPLEX)) -+ on |= MTK_PHY_LED_ON_HDX; -+ -+ if (rules & (BIT(TRIGGER_NETDEV_LINK_10) | BIT(TRIGGER_NETDEV_LINK))) -+ on |= MTK_PHY_LED_ON_LINK10; -+ -+ if (rules & (BIT(TRIGGER_NETDEV_LINK_100) | BIT(TRIGGER_NETDEV_LINK))) -+ on |= MTK_PHY_LED_ON_LINK100; -+ -+ if (rules & (BIT(TRIGGER_NETDEV_LINK_1000) | BIT(TRIGGER_NETDEV_LINK))) -+ on |= MTK_PHY_LED_ON_LINK1000; -+ -+ if (rules & (BIT(TRIGGER_NETDEV_LINK_2500) | BIT(TRIGGER_NETDEV_LINK))) -+ on |= MTK_PHY_LED_ON_LINK2500; -+ -+ if (rules & BIT(TRIGGER_NETDEV_RX)) { -+ blink |= (on & on_set) ? -+ (((on & MTK_PHY_LED_ON_LINK10) ? -+ MTK_PHY_LED_BLINK_10RX : 0) | -+ ((on & MTK_PHY_LED_ON_LINK100) ? -+ MTK_PHY_LED_BLINK_100RX : 0) | -+ ((on & MTK_PHY_LED_ON_LINK1000) ? -+ MTK_PHY_LED_BLINK_1000RX : 0) | -+ ((on & MTK_PHY_LED_ON_LINK2500) ? -+ MTK_PHY_LED_BLINK_2500RX : 0)) : -+ rx_blink_set; -+ } -+ -+ if (rules & BIT(TRIGGER_NETDEV_TX)) { -+ blink |= (on & on_set) ? -+ (((on & MTK_PHY_LED_ON_LINK10) ? -+ MTK_PHY_LED_BLINK_10TX : 0) | -+ ((on & MTK_PHY_LED_ON_LINK100) ? -+ MTK_PHY_LED_BLINK_100TX : 0) | -+ ((on & MTK_PHY_LED_ON_LINK1000) ? -+ MTK_PHY_LED_BLINK_1000TX : 0) | -+ ((on & MTK_PHY_LED_ON_LINK2500) ? -+ MTK_PHY_LED_BLINK_2500TX : 0)) : -+ tx_blink_set; -+ } -+ -+ if (blink || on) -+ set_bit(bit_netdev, &priv->led_state); -+ else -+ clear_bit(bit_netdev, &priv->led_state); -+ -+ ret = phy_modify_mmd(phydev, MDIO_MMD_VEND2, index ? -+ MTK_PHY_LED1_ON_CTRL : MTK_PHY_LED0_ON_CTRL, -+ MTK_PHY_LED_ON_FDX | MTK_PHY_LED_ON_HDX | on_set, -+ on); -+ -+ if (ret) -+ return ret; -+ -+ return phy_write_mmd(phydev, MDIO_MMD_VEND2, index ? -+ MTK_PHY_LED1_BLINK_CTRL : -+ MTK_PHY_LED0_BLINK_CTRL, blink); -+} -+EXPORT_SYMBOL_GPL(mtk_phy_led_hw_ctrl_set); -+ -+int mtk_phy_led_num_dly_cfg(u8 index, unsigned long *delay_on, -+ unsigned long *delay_off, bool *blinking) -+{ -+ if (index > 1) -+ return -EINVAL; -+ -+ if (delay_on && delay_off && (*delay_on > 0) && (*delay_off > 0)) { -+ *blinking = true; -+ *delay_on = 50; -+ *delay_off = 50; -+ } -+ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(mtk_phy_led_num_dly_cfg); -+ -+int mtk_phy_hw_led_on_set(struct phy_device *phydev, u8 index, -+ u16 led_on_mask, bool on) -+{ -+ unsigned int bit_on = MTK_PHY_LED_STATE_FORCE_ON + (index ? 16 : 0); -+ struct mtk_socphy_priv *priv = phydev->priv; -+ bool changed; -+ -+ if (on) -+ changed = !test_and_set_bit(bit_on, &priv->led_state); -+ else -+ changed = !!test_and_clear_bit(bit_on, &priv->led_state); -+ -+ changed |= !!test_and_clear_bit(MTK_PHY_LED_STATE_NETDEV + -+ (index ? 16 : 0), &priv->led_state); -+ if (changed) -+ return phy_modify_mmd(phydev, MDIO_MMD_VEND2, index ? -+ MTK_PHY_LED1_ON_CTRL : -+ MTK_PHY_LED0_ON_CTRL, -+ led_on_mask, -+ on ? MTK_PHY_LED_ON_FORCE_ON : 0); -+ else -+ return 0; -+} -+EXPORT_SYMBOL_GPL(mtk_phy_hw_led_on_set); -+ -+int mtk_phy_hw_led_blink_set(struct phy_device *phydev, u8 index, bool blinking) -+{ -+ unsigned int bit_blink = MTK_PHY_LED_STATE_FORCE_BLINK + -+ (index ? 16 : 0); -+ struct mtk_socphy_priv *priv = phydev->priv; -+ bool changed; -+ -+ if (blinking) -+ changed = !test_and_set_bit(bit_blink, &priv->led_state); -+ else -+ changed = !!test_and_clear_bit(bit_blink, &priv->led_state); -+ -+ changed |= !!test_bit(MTK_PHY_LED_STATE_NETDEV + -+ (index ? 16 : 0), &priv->led_state); -+ if (changed) -+ return phy_write_mmd(phydev, MDIO_MMD_VEND2, index ? -+ MTK_PHY_LED1_BLINK_CTRL : -+ MTK_PHY_LED0_BLINK_CTRL, -+ blinking ? -+ MTK_PHY_LED_BLINK_FORCE_BLINK : 0); -+ else -+ return 0; -+} -+EXPORT_SYMBOL_GPL(mtk_phy_hw_led_blink_set); -+ -+void mtk_phy_leds_state_init(struct phy_device *phydev) -+{ -+ int i; -+ -+ for (i = 0; i < 2; ++i) -+ phydev->drv->led_hw_control_get(phydev, i, NULL); -+} -+EXPORT_SYMBOL_GPL(mtk_phy_leds_state_init); -+ -+MODULE_DESCRIPTION("MediaTek Ethernet PHY driver common"); -+MODULE_AUTHOR("Sky Huang "); -+MODULE_AUTHOR("Daniel Golle "); -+MODULE_LICENSE("GPL"); ---- /dev/null -+++ b/drivers/net/phy/mediatek/mtk.h -@@ -0,0 +1,86 @@ -+/* SPDX-License-Identifier: GPL-2.0 -+ * -+ * Common definition for Mediatek Ethernet PHYs -+ * Author: SkyLake Huang -+ * Copyright (c) 2024 MediaTek Inc. -+ */ -+ -+#ifndef _MTK_EPHY_H_ -+#define _MTK_EPHY_H_ -+ -+#define MTK_EXT_PAGE_ACCESS 0x1f -+ -+/* Registers on MDIO_MMD_VEND2 */ -+#define MTK_PHY_LED0_ON_CTRL 0x24 -+#define MTK_PHY_LED1_ON_CTRL 0x26 -+#define MTK_GPHY_LED_ON_MASK GENMASK(6, 0) -+#define MTK_2P5GPHY_LED_ON_MASK GENMASK(7, 0) -+#define MTK_PHY_LED_ON_LINK1000 BIT(0) -+#define MTK_PHY_LED_ON_LINK100 BIT(1) -+#define MTK_PHY_LED_ON_LINK10 BIT(2) -+#define MTK_PHY_LED_ON_LINKDOWN BIT(3) -+#define MTK_PHY_LED_ON_FDX BIT(4) /* Full duplex */ -+#define MTK_PHY_LED_ON_HDX BIT(5) /* Half duplex */ -+#define MTK_PHY_LED_ON_FORCE_ON BIT(6) -+#define MTK_PHY_LED_ON_LINK2500 BIT(7) -+#define MTK_PHY_LED_ON_POLARITY BIT(14) -+#define MTK_PHY_LED_ON_ENABLE BIT(15) -+ -+#define MTK_PHY_LED0_BLINK_CTRL 0x25 -+#define MTK_PHY_LED1_BLINK_CTRL 0x27 -+#define MTK_PHY_LED_BLINK_1000TX BIT(0) -+#define MTK_PHY_LED_BLINK_1000RX BIT(1) -+#define MTK_PHY_LED_BLINK_100TX BIT(2) -+#define MTK_PHY_LED_BLINK_100RX BIT(3) -+#define MTK_PHY_LED_BLINK_10TX BIT(4) -+#define MTK_PHY_LED_BLINK_10RX BIT(5) -+#define MTK_PHY_LED_BLINK_COLLISION BIT(6) -+#define MTK_PHY_LED_BLINK_RX_CRC_ERR BIT(7) -+#define MTK_PHY_LED_BLINK_RX_IDLE_ERR BIT(8) -+#define MTK_PHY_LED_BLINK_FORCE_BLINK BIT(9) -+#define MTK_PHY_LED_BLINK_2500TX BIT(10) -+#define MTK_PHY_LED_BLINK_2500RX BIT(11) -+ -+#define MTK_GPHY_LED_ON_SET (MTK_PHY_LED_ON_LINK1000 | \ -+ MTK_PHY_LED_ON_LINK100 | \ -+ MTK_PHY_LED_ON_LINK10) -+#define MTK_GPHY_LED_RX_BLINK_SET (MTK_PHY_LED_BLINK_1000RX | \ -+ MTK_PHY_LED_BLINK_100RX | \ -+ MTK_PHY_LED_BLINK_10RX) -+#define MTK_GPHY_LED_TX_BLINK_SET (MTK_PHY_LED_BLINK_1000RX | \ -+ MTK_PHY_LED_BLINK_100RX | \ -+ MTK_PHY_LED_BLINK_10RX) -+ -+#define MTK_2P5GPHY_LED_ON_SET (MTK_PHY_LED_ON_LINK2500 | \ -+ MTK_GPHY_LED_ON_SET) -+#define MTK_2P5GPHY_LED_RX_BLINK_SET (MTK_PHY_LED_BLINK_2500RX | \ -+ MTK_GPHY_LED_RX_BLINK_SET) -+#define MTK_2P5GPHY_LED_TX_BLINK_SET (MTK_PHY_LED_BLINK_2500RX | \ -+ MTK_GPHY_LED_TX_BLINK_SET) -+ -+#define MTK_PHY_LED_STATE_FORCE_ON 0 -+#define MTK_PHY_LED_STATE_FORCE_BLINK 1 -+#define MTK_PHY_LED_STATE_NETDEV 2 -+ -+struct mtk_socphy_priv { -+ unsigned long led_state; -+}; -+ -+int mtk_phy_led_hw_is_supported(struct phy_device *phydev, u8 index, -+ unsigned long rules, -+ unsigned long supported_triggers); -+int mtk_phy_led_hw_ctrl_set(struct phy_device *phydev, u8 index, -+ unsigned long rules, u16 on_set, -+ u16 rx_blink_set, u16 tx_blink_set); -+int mtk_phy_led_hw_ctrl_get(struct phy_device *phydev, u8 index, -+ unsigned long *rules, u16 on_set, -+ u16 rx_blink_set, u16 tx_blink_set); -+int mtk_phy_led_num_dly_cfg(u8 index, unsigned long *delay_on, -+ unsigned long *delay_off, bool *blinking); -+int mtk_phy_hw_led_on_set(struct phy_device *phydev, u8 index, -+ u16 led_on_mask, bool on); -+int mtk_phy_hw_led_blink_set(struct phy_device *phydev, u8 index, -+ bool blinking); -+void mtk_phy_leds_state_init(struct phy_device *phydev); -+ -+#endif /* _MTK_EPHY_H_ */ diff --git a/target/linux/generic/backport-6.18/720-06-v6.13-net-phy-mediatek-Improve-readability-of-mtk-phy-lib..patch b/target/linux/generic/backport-6.18/720-06-v6.13-net-phy-mediatek-Improve-readability-of-mtk-phy-lib..patch deleted file mode 100644 index 19f3a84ad9..0000000000 --- a/target/linux/generic/backport-6.18/720-06-v6.13-net-phy-mediatek-Improve-readability-of-mtk-phy-lib..patch +++ /dev/null @@ -1,72 +0,0 @@ -From 3efd0595fc7aaae300f5d9f4f0ae86f432c8d2c7 Mon Sep 17 00:00:00 2001 -From: "SkyLake.Huang" -Date: Sat, 9 Nov 2024 00:34:53 +0800 -Subject: [PATCH 06/20] net: phy: mediatek: Improve readability of - mtk-phy-lib.c's mtk_phy_led_hw_ctrl_set() - -This patch removes parens around TRIGGER_NETDEV_RX/TRIGGER_NETDEV_TX in -mtk_phy_led_hw_ctrl_set(), which improves readability. - -Reviewed-by: Andrew Lunn -Signed-off-by: SkyLake.Huang -Signed-off-by: David S. Miller ---- - drivers/net/phy/mediatek/mtk-phy-lib.c | 44 ++++++++++++++------------ - 1 file changed, 24 insertions(+), 20 deletions(-) - ---- a/drivers/net/phy/mediatek/mtk-phy-lib.c -+++ b/drivers/net/phy/mediatek/mtk-phy-lib.c -@@ -129,29 +129,33 @@ int mtk_phy_led_hw_ctrl_set(struct phy_d - on |= MTK_PHY_LED_ON_LINK2500; - - if (rules & BIT(TRIGGER_NETDEV_RX)) { -- blink |= (on & on_set) ? -- (((on & MTK_PHY_LED_ON_LINK10) ? -- MTK_PHY_LED_BLINK_10RX : 0) | -- ((on & MTK_PHY_LED_ON_LINK100) ? -- MTK_PHY_LED_BLINK_100RX : 0) | -- ((on & MTK_PHY_LED_ON_LINK1000) ? -- MTK_PHY_LED_BLINK_1000RX : 0) | -- ((on & MTK_PHY_LED_ON_LINK2500) ? -- MTK_PHY_LED_BLINK_2500RX : 0)) : -- rx_blink_set; -+ if (on & on_set) { -+ if (on & MTK_PHY_LED_ON_LINK10) -+ blink |= MTK_PHY_LED_BLINK_10RX; -+ if (on & MTK_PHY_LED_ON_LINK100) -+ blink |= MTK_PHY_LED_BLINK_100RX; -+ if (on & MTK_PHY_LED_ON_LINK1000) -+ blink |= MTK_PHY_LED_BLINK_1000RX; -+ if (on & MTK_PHY_LED_ON_LINK2500) -+ blink |= MTK_PHY_LED_BLINK_2500RX; -+ } else { -+ blink |= rx_blink_set; -+ } - } - - if (rules & BIT(TRIGGER_NETDEV_TX)) { -- blink |= (on & on_set) ? -- (((on & MTK_PHY_LED_ON_LINK10) ? -- MTK_PHY_LED_BLINK_10TX : 0) | -- ((on & MTK_PHY_LED_ON_LINK100) ? -- MTK_PHY_LED_BLINK_100TX : 0) | -- ((on & MTK_PHY_LED_ON_LINK1000) ? -- MTK_PHY_LED_BLINK_1000TX : 0) | -- ((on & MTK_PHY_LED_ON_LINK2500) ? -- MTK_PHY_LED_BLINK_2500TX : 0)) : -- tx_blink_set; -+ if (on & on_set) { -+ if (on & MTK_PHY_LED_ON_LINK10) -+ blink |= MTK_PHY_LED_BLINK_10TX; -+ if (on & MTK_PHY_LED_ON_LINK100) -+ blink |= MTK_PHY_LED_BLINK_100TX; -+ if (on & MTK_PHY_LED_ON_LINK1000) -+ blink |= MTK_PHY_LED_BLINK_1000TX; -+ if (on & MTK_PHY_LED_ON_LINK2500) -+ blink |= MTK_PHY_LED_BLINK_2500TX; -+ } else { -+ blink |= tx_blink_set; -+ } - } - - if (blink || on) diff --git a/target/linux/generic/backport-6.18/720-07-v6.13-net-phy-mediatek-Integrate-read-write-page-helper-fu.patch b/target/linux/generic/backport-6.18/720-07-v6.13-net-phy-mediatek-Integrate-read-write-page-helper-fu.patch deleted file mode 100644 index a5828bc759..0000000000 --- a/target/linux/generic/backport-6.18/720-07-v6.13-net-phy-mediatek-Integrate-read-write-page-helper-fu.patch +++ /dev/null @@ -1,153 +0,0 @@ -From 50a97d716105a5f35aaecca0bdfe8e23cba0e87f Mon Sep 17 00:00:00 2001 -From: "SkyLake.Huang" -Date: Sat, 9 Nov 2024 00:34:54 +0800 -Subject: [PATCH 07/20] net: phy: mediatek: Integrate read/write page helper - functions - -This patch integrates read/write page helper functions as MTK phy lib. -They are basically the same in mtk-ge.c & mtk-ge-soc.c. - -Signed-off-by: SkyLake.Huang -Signed-off-by: David S. Miller ---- - drivers/net/phy/mediatek/Kconfig | 1 + - drivers/net/phy/mediatek/mtk-ge-soc.c | 18 ++++-------------- - drivers/net/phy/mediatek/mtk-ge.c | 20 ++++++-------------- - drivers/net/phy/mediatek/mtk-phy-lib.c | 12 ++++++++++++ - drivers/net/phy/mediatek/mtk.h | 3 +++ - 5 files changed, 26 insertions(+), 28 deletions(-) - ---- a/drivers/net/phy/mediatek/Kconfig -+++ b/drivers/net/phy/mediatek/Kconfig -@@ -4,6 +4,7 @@ config MTK_NET_PHYLIB - - config MEDIATEK_GE_PHY - tristate "MediaTek Gigabit Ethernet PHYs" -+ select MTK_NET_PHYLIB - help - Supports the MediaTek non-built-in Gigabit Ethernet PHYs. - ---- a/drivers/net/phy/mediatek/mtk-ge-soc.c -+++ b/drivers/net/phy/mediatek/mtk-ge-soc.c -@@ -271,16 +271,6 @@ struct mtk_socphy_shared { - struct mtk_socphy_priv priv[4]; - }; - --static int mtk_socphy_read_page(struct phy_device *phydev) --{ -- return __phy_read(phydev, MTK_EXT_PAGE_ACCESS); --} -- --static int mtk_socphy_write_page(struct phy_device *phydev, int page) --{ -- return __phy_write(phydev, MTK_EXT_PAGE_ACCESS, page); --} -- - /* One calibration cycle consists of: - * 1.Set DA_CALIN_FLAG high to start calibration. Keep it high - * until AD_CAL_COMP is ready to output calibration result. -@@ -1337,8 +1327,8 @@ static struct phy_driver mtk_socphy_driv - .probe = mt7981_phy_probe, - .suspend = genphy_suspend, - .resume = genphy_resume, -- .read_page = mtk_socphy_read_page, -- .write_page = mtk_socphy_write_page, -+ .read_page = mtk_phy_read_page, -+ .write_page = mtk_phy_write_page, - .led_blink_set = mt798x_phy_led_blink_set, - .led_brightness_set = mt798x_phy_led_brightness_set, - .led_hw_is_supported = mt798x_phy_led_hw_is_supported, -@@ -1354,8 +1344,8 @@ static struct phy_driver mtk_socphy_driv - .probe = mt7988_phy_probe, - .suspend = genphy_suspend, - .resume = genphy_resume, -- .read_page = mtk_socphy_read_page, -- .write_page = mtk_socphy_write_page, -+ .read_page = mtk_phy_read_page, -+ .write_page = mtk_phy_write_page, - .led_blink_set = mt798x_phy_led_blink_set, - .led_brightness_set = mt798x_phy_led_brightness_set, - .led_hw_is_supported = mt798x_phy_led_hw_is_supported, ---- a/drivers/net/phy/mediatek/mtk-ge.c -+++ b/drivers/net/phy/mediatek/mtk-ge.c -@@ -3,6 +3,8 @@ - #include - #include - -+#include "mtk.h" -+ - #define MTK_EXT_PAGE_ACCESS 0x1f - #define MTK_PHY_PAGE_STANDARD 0x0000 - #define MTK_PHY_PAGE_EXTENDED 0x0001 -@@ -11,16 +13,6 @@ - #define MTK_PHY_PAGE_EXTENDED_2A30 0x2a30 - #define MTK_PHY_PAGE_EXTENDED_52B5 0x52b5 - --static int mtk_gephy_read_page(struct phy_device *phydev) --{ -- return __phy_read(phydev, MTK_EXT_PAGE_ACCESS); --} -- --static int mtk_gephy_write_page(struct phy_device *phydev, int page) --{ -- return __phy_write(phydev, MTK_EXT_PAGE_ACCESS, page); --} -- - static void mtk_gephy_config_init(struct phy_device *phydev) - { - /* Enable HW auto downshift */ -@@ -77,8 +69,8 @@ static struct phy_driver mtk_gephy_drive - .handle_interrupt = genphy_handle_interrupt_no_ack, - .suspend = genphy_suspend, - .resume = genphy_resume, -- .read_page = mtk_gephy_read_page, -- .write_page = mtk_gephy_write_page, -+ .read_page = mtk_phy_read_page, -+ .write_page = mtk_phy_write_page, - }, - { - PHY_ID_MATCH_EXACT(0x03a29441), -@@ -91,8 +83,8 @@ static struct phy_driver mtk_gephy_drive - .handle_interrupt = genphy_handle_interrupt_no_ack, - .suspend = genphy_suspend, - .resume = genphy_resume, -- .read_page = mtk_gephy_read_page, -- .write_page = mtk_gephy_write_page, -+ .read_page = mtk_phy_read_page, -+ .write_page = mtk_phy_write_page, - }, - }; - ---- a/drivers/net/phy/mediatek/mtk-phy-lib.c -+++ b/drivers/net/phy/mediatek/mtk-phy-lib.c -@@ -6,6 +6,18 @@ - - #include "mtk.h" - -+int mtk_phy_read_page(struct phy_device *phydev) -+{ -+ return __phy_read(phydev, MTK_EXT_PAGE_ACCESS); -+} -+EXPORT_SYMBOL_GPL(mtk_phy_read_page); -+ -+int mtk_phy_write_page(struct phy_device *phydev, int page) -+{ -+ return __phy_write(phydev, MTK_EXT_PAGE_ACCESS, page); -+} -+EXPORT_SYMBOL_GPL(mtk_phy_write_page); -+ - int mtk_phy_led_hw_is_supported(struct phy_device *phydev, u8 index, - unsigned long rules, - unsigned long supported_triggers) ---- a/drivers/net/phy/mediatek/mtk.h -+++ b/drivers/net/phy/mediatek/mtk.h -@@ -66,6 +66,9 @@ struct mtk_socphy_priv { - unsigned long led_state; - }; - -+int mtk_phy_read_page(struct phy_device *phydev); -+int mtk_phy_write_page(struct phy_device *phydev, int page); -+ - int mtk_phy_led_hw_is_supported(struct phy_device *phydev, u8 index, - unsigned long rules, - unsigned long supported_triggers); diff --git a/target/linux/generic/backport-6.18/720-08-v6.13-net-phy-mediatek-add-MT7530-MT7531-s-PHY-ID-macros.patch b/target/linux/generic/backport-6.18/720-08-v6.13-net-phy-mediatek-add-MT7530-MT7531-s-PHY-ID-macros.patch deleted file mode 100644 index 1c8738408b..0000000000 --- a/target/linux/generic/backport-6.18/720-08-v6.13-net-phy-mediatek-add-MT7530-MT7531-s-PHY-ID-macros.patch +++ /dev/null @@ -1,56 +0,0 @@ -From e6579df175d5b1baa605c82f8e759542262637cf Mon Sep 17 00:00:00 2001 -From: "SkyLake.Huang" -Date: Sat, 9 Nov 2024 00:34:55 +0800 -Subject: [PATCH 08/20] net: phy: mediatek: add MT7530 & MT7531's PHY ID macros - -This patch adds MT7530 & MT7531's PHY ID macros in mtk-ge.c so that -it follows the same rule of mtk-ge-soc.c. - -Reviewed-by: Andrew Lunn -Signed-off-by: SkyLake.Huang -Signed-off-by: David S. Miller ---- - drivers/net/phy/mediatek/mtk-ge.c | 11 +++++++---- - 1 file changed, 7 insertions(+), 4 deletions(-) - ---- a/drivers/net/phy/mediatek/mtk-ge.c -+++ b/drivers/net/phy/mediatek/mtk-ge.c -@@ -5,6 +5,9 @@ - - #include "mtk.h" - -+#define MTK_GPHY_ID_MT7530 0x03a29412 -+#define MTK_GPHY_ID_MT7531 0x03a29441 -+ - #define MTK_EXT_PAGE_ACCESS 0x1f - #define MTK_PHY_PAGE_STANDARD 0x0000 - #define MTK_PHY_PAGE_EXTENDED 0x0001 -@@ -59,7 +62,7 @@ static int mt7531_phy_config_init(struct - - static struct phy_driver mtk_gephy_driver[] = { - { -- PHY_ID_MATCH_EXACT(0x03a29412), -+ PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7530), - .name = "MediaTek MT7530 PHY", - .config_init = mt7530_phy_config_init, - /* Interrupts are handled by the switch, not the PHY -@@ -73,7 +76,7 @@ static struct phy_driver mtk_gephy_drive - .write_page = mtk_phy_write_page, - }, - { -- PHY_ID_MATCH_EXACT(0x03a29441), -+ PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7531), - .name = "MediaTek MT7531 PHY", - .config_init = mt7531_phy_config_init, - /* Interrupts are handled by the switch, not the PHY -@@ -91,8 +94,8 @@ static struct phy_driver mtk_gephy_drive - module_phy_driver(mtk_gephy_driver); - - static struct mdio_device_id __maybe_unused mtk_gephy_tbl[] = { -- { PHY_ID_MATCH_EXACT(0x03a29441) }, -- { PHY_ID_MATCH_EXACT(0x03a29412) }, -+ { PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7530) }, -+ { PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7531) }, - { } - }; - diff --git a/target/linux/generic/backport-6.18/720-09-v6.14-net-phy-Constify-struct-mdio_device_id.patch b/target/linux/generic/backport-6.18/720-09-v6.14-net-phy-Constify-struct-mdio_device_id.patch deleted file mode 100644 index c0c840d3af..0000000000 --- a/target/linux/generic/backport-6.18/720-09-v6.14-net-phy-Constify-struct-mdio_device_id.patch +++ /dev/null @@ -1,700 +0,0 @@ -From e127f7380aaf2cd1614961d826a4af7ab297d37f Mon Sep 17 00:00:00 2001 -From: Christophe JAILLET -Date: Sun, 12 Jan 2025 15:14:50 +0100 -Subject: [PATCH 09/20] net: phy: Constify struct mdio_device_id - -'struct mdio_device_id' is not modified in these drivers. - -Constifying these structures moves some data to a read-only section, so -increase overall security. - -On a x86_64, with allmodconfig, as an example: -Before: -====== - text data bss dec hex filename - 27014 12792 0 39806 9b7e drivers/net/phy/broadcom.o - -After: -===== - text data bss dec hex filename - 27206 12600 0 39806 9b7e drivers/net/phy/broadcom.o - -Signed-off-by: Christophe JAILLET -Reviewed-by: Andrew Lunn -Link: https://patch.msgid.link/403c381b7d9156b67ad68ffc44b8eee70c5e86a9.1736691226.git.christophe.jaillet@wanadoo.fr -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/adin.c | 2 +- - drivers/net/phy/adin1100.c | 2 +- - drivers/net/phy/air_en8811h.c | 2 +- - drivers/net/phy/amd.c | 2 +- - drivers/net/phy/aquantia/aquantia_main.c | 2 +- - drivers/net/phy/ax88796b.c | 2 +- - drivers/net/phy/bcm-cygnus.c | 2 +- - drivers/net/phy/bcm54140.c | 2 +- - drivers/net/phy/bcm63xx.c | 2 +- - drivers/net/phy/bcm7xxx.c | 2 +- - drivers/net/phy/bcm84881.c | 2 +- - drivers/net/phy/broadcom.c | 2 +- - drivers/net/phy/cicada.c | 2 +- - drivers/net/phy/cortina.c | 2 +- - drivers/net/phy/davicom.c | 2 +- - drivers/net/phy/dp83640.c | 2 +- - drivers/net/phy/dp83822.c | 2 +- - drivers/net/phy/dp83848.c | 2 +- - drivers/net/phy/dp83867.c | 2 +- - drivers/net/phy/dp83869.c | 2 +- - drivers/net/phy/dp83tc811.c | 2 +- - drivers/net/phy/dp83td510.c | 2 +- - drivers/net/phy/dp83tg720.c | 2 +- - drivers/net/phy/et1011c.c | 2 +- - drivers/net/phy/icplus.c | 2 +- - drivers/net/phy/intel-xway.c | 2 +- - drivers/net/phy/lxt.c | 2 +- - drivers/net/phy/marvell-88q2xxx.c | 2 +- - drivers/net/phy/marvell-88x2222.c | 2 +- - drivers/net/phy/marvell.c | 2 +- - drivers/net/phy/marvell10g.c | 2 +- - drivers/net/phy/mediatek/mtk-ge-soc.c | 2 +- - drivers/net/phy/mediatek/mtk-ge.c | 2 +- - drivers/net/phy/meson-gxl.c | 2 +- - drivers/net/phy/micrel.c | 2 +- - drivers/net/phy/microchip.c | 2 +- - drivers/net/phy/microchip_t1.c | 2 +- - drivers/net/phy/microchip_t1s.c | 2 +- - drivers/net/phy/mscc/mscc_main.c | 2 +- - drivers/net/phy/mxl-gpy.c | 2 +- - drivers/net/phy/national.c | 2 +- - drivers/net/phy/ncn26000.c | 2 +- - drivers/net/phy/nxp-c45-tja11xx.c | 2 +- - drivers/net/phy/nxp-cbtx.c | 2 +- - drivers/net/phy/nxp-tja11xx.c | 2 +- - drivers/net/phy/qcom/at803x.c | 2 +- - drivers/net/phy/qcom/qca807x.c | 2 +- - drivers/net/phy/qcom/qca808x.c | 2 +- - drivers/net/phy/qcom/qca83xx.c | 2 +- - drivers/net/phy/qsemi.c | 2 +- - drivers/net/phy/rockchip.c | 2 +- - drivers/net/phy/smsc.c | 2 +- - drivers/net/phy/ste10Xp.c | 2 +- - drivers/net/phy/teranetics.c | 2 +- - drivers/net/phy/uPD60620.c | 2 +- - drivers/net/phy/vitesse.c | 2 +- - 56 files changed, 56 insertions(+), 56 deletions(-) - ---- a/drivers/net/phy/adin.c -+++ b/drivers/net/phy/adin.c -@@ -1040,7 +1040,7 @@ static struct phy_driver adin_driver[] = - - module_phy_driver(adin_driver); - --static struct mdio_device_id __maybe_unused adin_tbl[] = { -+static const struct mdio_device_id __maybe_unused adin_tbl[] = { - { PHY_ID_MATCH_MODEL(PHY_ID_ADIN1200) }, - { PHY_ID_MATCH_MODEL(PHY_ID_ADIN1300) }, - { } ---- a/drivers/net/phy/adin1100.c -+++ b/drivers/net/phy/adin1100.c -@@ -340,7 +340,7 @@ static struct phy_driver adin_driver[] = - - module_phy_driver(adin_driver); - --static struct mdio_device_id __maybe_unused adin_tbl[] = { -+static const struct mdio_device_id __maybe_unused adin_tbl[] = { - { PHY_ID_MATCH_MODEL(PHY_ID_ADIN1100) }, - { PHY_ID_MATCH_MODEL(PHY_ID_ADIN1110) }, - { PHY_ID_MATCH_MODEL(PHY_ID_ADIN2111) }, ---- a/drivers/net/phy/air_en8811h.c -+++ b/drivers/net/phy/air_en8811h.c -@@ -1075,7 +1075,7 @@ static struct phy_driver en8811h_driver[ - - module_phy_driver(en8811h_driver); - --static struct mdio_device_id __maybe_unused en8811h_tbl[] = { -+static const struct mdio_device_id __maybe_unused en8811h_tbl[] = { - { PHY_ID_MATCH_MODEL(EN8811H_PHY_ID) }, - { } - }; ---- a/drivers/net/phy/amd.c -+++ b/drivers/net/phy/amd.c -@@ -111,7 +111,7 @@ static struct phy_driver am79c_drivers[] - - module_phy_driver(am79c_drivers); - --static struct mdio_device_id __maybe_unused amd_tbl[] = { -+static const struct mdio_device_id __maybe_unused amd_tbl[] = { - { PHY_ID_AC101L, 0xfffffff0 }, - { PHY_ID_AM79C874, 0xfffffff0 }, - { } ---- a/drivers/net/phy/aquantia/aquantia_main.c -+++ b/drivers/net/phy/aquantia/aquantia_main.c -@@ -1096,7 +1096,7 @@ static struct phy_driver aqr_driver[] = - - module_phy_driver(aqr_driver); - --static struct mdio_device_id __maybe_unused aqr_tbl[] = { -+static const struct mdio_device_id __maybe_unused aqr_tbl[] = { - { PHY_ID_MATCH_MODEL(PHY_ID_AQ1202) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQ2104) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQR105) }, ---- a/drivers/net/phy/ax88796b.c -+++ b/drivers/net/phy/ax88796b.c -@@ -121,7 +121,7 @@ static struct phy_driver asix_driver[] = - - module_phy_driver(asix_driver); - --static struct mdio_device_id __maybe_unused asix_tbl[] = { -+static const struct mdio_device_id __maybe_unused asix_tbl[] = { - { PHY_ID_MATCH_EXACT(PHY_ID_ASIX_AX88772A) }, - { PHY_ID_MATCH_EXACT(PHY_ID_ASIX_AX88772C) }, - { PHY_ID_ASIX_AX88796B, 0xfffffff0 }, ---- a/drivers/net/phy/bcm-cygnus.c -+++ b/drivers/net/phy/bcm-cygnus.c -@@ -278,7 +278,7 @@ static struct phy_driver bcm_cygnus_phy_ - } - }; - --static struct mdio_device_id __maybe_unused bcm_cygnus_phy_tbl[] = { -+static const struct mdio_device_id __maybe_unused bcm_cygnus_phy_tbl[] = { - { PHY_ID_BCM_CYGNUS, 0xfffffff0, }, - { PHY_ID_BCM_OMEGA, 0xfffffff0, }, - { } ---- a/drivers/net/phy/bcm54140.c -+++ b/drivers/net/phy/bcm54140.c -@@ -883,7 +883,7 @@ static struct phy_driver bcm54140_driver - }; - module_phy_driver(bcm54140_drivers); - --static struct mdio_device_id __maybe_unused bcm54140_tbl[] = { -+static const struct mdio_device_id __maybe_unused bcm54140_tbl[] = { - { PHY_ID_BCM54140, BCM54140_PHY_ID_MASK }, - { } - }; ---- a/drivers/net/phy/bcm63xx.c -+++ b/drivers/net/phy/bcm63xx.c -@@ -93,7 +93,7 @@ static struct phy_driver bcm63xx_driver[ - - module_phy_driver(bcm63xx_driver); - --static struct mdio_device_id __maybe_unused bcm63xx_tbl[] = { -+static const struct mdio_device_id __maybe_unused bcm63xx_tbl[] = { - { 0x00406000, 0xfffffc00 }, - { 0x002bdc00, 0xfffffc00 }, - { } ---- a/drivers/net/phy/bcm7xxx.c -+++ b/drivers/net/phy/bcm7xxx.c -@@ -929,7 +929,7 @@ static struct phy_driver bcm7xxx_driver[ - BCM7XXX_16NM_EPHY(PHY_ID_BCM7712, "Broadcom BCM7712"), - }; - --static struct mdio_device_id __maybe_unused bcm7xxx_tbl[] = { -+static const struct mdio_device_id __maybe_unused bcm7xxx_tbl[] = { - { PHY_ID_BCM72113, 0xfffffff0 }, - { PHY_ID_BCM72116, 0xfffffff0, }, - { PHY_ID_BCM72165, 0xfffffff0, }, ---- a/drivers/net/phy/bcm84881.c -+++ b/drivers/net/phy/bcm84881.c -@@ -262,7 +262,7 @@ static struct phy_driver bcm84881_driver - module_phy_driver(bcm84881_drivers); - - /* FIXME: module auto-loading for Clause 45 PHYs seems non-functional */ --static struct mdio_device_id __maybe_unused bcm84881_tbl[] = { -+static const struct mdio_device_id __maybe_unused bcm84881_tbl[] = { - { 0xae025150, 0xfffffff0 }, - { }, - }; ---- a/drivers/net/phy/broadcom.c -+++ b/drivers/net/phy/broadcom.c -@@ -1734,7 +1734,7 @@ static struct phy_driver broadcom_driver - - module_phy_driver(broadcom_drivers); - --static struct mdio_device_id __maybe_unused broadcom_tbl[] = { -+static const struct mdio_device_id __maybe_unused broadcom_tbl[] = { - { PHY_ID_BCM5411, 0xfffffff0 }, - { PHY_ID_BCM5421, 0xfffffff0 }, - { PHY_ID_BCM54210E, 0xfffffff0 }, ---- a/drivers/net/phy/cicada.c -+++ b/drivers/net/phy/cicada.c -@@ -145,7 +145,7 @@ static struct phy_driver cis820x_driver[ - - module_phy_driver(cis820x_driver); - --static struct mdio_device_id __maybe_unused cicada_tbl[] = { -+static const struct mdio_device_id __maybe_unused cicada_tbl[] = { - { 0x000fc410, 0x000ffff0 }, - { 0x000fc440, 0x000fffc0 }, - { } ---- a/drivers/net/phy/cortina.c -+++ b/drivers/net/phy/cortina.c -@@ -87,7 +87,7 @@ static struct phy_driver cortina_driver[ - - module_phy_driver(cortina_driver); - --static struct mdio_device_id __maybe_unused cortina_tbl[] = { -+static const struct mdio_device_id __maybe_unused cortina_tbl[] = { - { PHY_ID_CS4340, 0xffffffff}, - {}, - }; ---- a/drivers/net/phy/davicom.c -+++ b/drivers/net/phy/davicom.c -@@ -209,7 +209,7 @@ static struct phy_driver dm91xx_driver[] - - module_phy_driver(dm91xx_driver); - --static struct mdio_device_id __maybe_unused davicom_tbl[] = { -+static const struct mdio_device_id __maybe_unused davicom_tbl[] = { - { 0x0181b880, 0x0ffffff0 }, - { 0x0181b8b0, 0x0ffffff0 }, - { 0x0181b8a0, 0x0ffffff0 }, ---- a/drivers/net/phy/dp83640.c -+++ b/drivers/net/phy/dp83640.c -@@ -1548,7 +1548,7 @@ MODULE_LICENSE("GPL"); - module_init(dp83640_init); - module_exit(dp83640_exit); - --static struct mdio_device_id __maybe_unused dp83640_tbl[] = { -+static const struct mdio_device_id __maybe_unused dp83640_tbl[] = { - { DP83640_PHY_ID, 0xfffffff0 }, - { } - }; ---- a/drivers/net/phy/dp83822.c -+++ b/drivers/net/phy/dp83822.c -@@ -825,7 +825,7 @@ static struct phy_driver dp83822_driver[ - }; - module_phy_driver(dp83822_driver); - --static struct mdio_device_id __maybe_unused dp83822_tbl[] = { -+static const struct mdio_device_id __maybe_unused dp83822_tbl[] = { - { DP83822_PHY_ID, 0xfffffff0 }, - { DP83825I_PHY_ID, 0xfffffff0 }, - { DP83826C_PHY_ID, 0xfffffff0 }, ---- a/drivers/net/phy/dp83848.c -+++ b/drivers/net/phy/dp83848.c -@@ -123,7 +123,7 @@ static int dp83848_config_init(struct ph - return 0; - } - --static struct mdio_device_id __maybe_unused dp83848_tbl[] = { -+static const struct mdio_device_id __maybe_unused dp83848_tbl[] = { - { TI_DP83848C_PHY_ID, 0xfffffff0 }, - { NS_DP83848C_PHY_ID, 0xfffffff0 }, - { TI_DP83620_PHY_ID, 0xfffffff0 }, ---- a/drivers/net/phy/dp83867.c -+++ b/drivers/net/phy/dp83867.c -@@ -1210,7 +1210,7 @@ static struct phy_driver dp83867_driver[ - }; - module_phy_driver(dp83867_driver); - --static struct mdio_device_id __maybe_unused dp83867_tbl[] = { -+static const struct mdio_device_id __maybe_unused dp83867_tbl[] = { - { DP83867_PHY_ID, 0xfffffff0 }, - { } - }; ---- a/drivers/net/phy/dp83869.c -+++ b/drivers/net/phy/dp83869.c -@@ -928,7 +928,7 @@ static struct phy_driver dp83869_driver[ - }; - module_phy_driver(dp83869_driver); - --static struct mdio_device_id __maybe_unused dp83869_tbl[] = { -+static const struct mdio_device_id __maybe_unused dp83869_tbl[] = { - { PHY_ID_MATCH_MODEL(DP83869_PHY_ID) }, - { PHY_ID_MATCH_MODEL(DP83561_PHY_ID) }, - { } ---- a/drivers/net/phy/dp83tc811.c -+++ b/drivers/net/phy/dp83tc811.c -@@ -403,7 +403,7 @@ static struct phy_driver dp83811_driver[ - }; - module_phy_driver(dp83811_driver); - --static struct mdio_device_id __maybe_unused dp83811_tbl[] = { -+static const struct mdio_device_id __maybe_unused dp83811_tbl[] = { - { DP83TC811_PHY_ID, 0xfffffff0 }, - { }, - }; ---- a/drivers/net/phy/dp83td510.c -+++ b/drivers/net/phy/dp83td510.c -@@ -605,7 +605,7 @@ static struct phy_driver dp83td510_drive - } }; - module_phy_driver(dp83td510_driver); - --static struct mdio_device_id __maybe_unused dp83td510_tbl[] = { -+static const struct mdio_device_id __maybe_unused dp83td510_tbl[] = { - { PHY_ID_MATCH_MODEL(DP83TD510E_PHY_ID) }, - { } - }; ---- a/drivers/net/phy/dp83tg720.c -+++ b/drivers/net/phy/dp83tg720.c -@@ -361,7 +361,7 @@ static struct phy_driver dp83tg720_drive - } }; - module_phy_driver(dp83tg720_driver); - --static struct mdio_device_id __maybe_unused dp83tg720_tbl[] = { -+static const struct mdio_device_id __maybe_unused dp83tg720_tbl[] = { - { PHY_ID_MATCH_MODEL(DP83TG720S_PHY_ID) }, - { } - }; ---- a/drivers/net/phy/et1011c.c -+++ b/drivers/net/phy/et1011c.c -@@ -94,7 +94,7 @@ static struct phy_driver et1011c_driver[ - - module_phy_driver(et1011c_driver); - --static struct mdio_device_id __maybe_unused et1011c_tbl[] = { -+static const struct mdio_device_id __maybe_unused et1011c_tbl[] = { - { 0x0282f014, 0xfffffff0 }, - { } - }; ---- a/drivers/net/phy/icplus.c -+++ b/drivers/net/phy/icplus.c -@@ -624,7 +624,7 @@ static struct phy_driver icplus_driver[] - - module_phy_driver(icplus_driver); - --static struct mdio_device_id __maybe_unused icplus_tbl[] = { -+static const struct mdio_device_id __maybe_unused icplus_tbl[] = { - { PHY_ID_MATCH_MODEL(IP175C_PHY_ID) }, - { PHY_ID_MATCH_MODEL(IP1001_PHY_ID) }, - { PHY_ID_MATCH_EXACT(IP101A_PHY_ID) }, ---- a/drivers/net/phy/intel-xway.c -+++ b/drivers/net/phy/intel-xway.c -@@ -456,7 +456,7 @@ static struct phy_driver xway_gphy[] = { - }; - module_phy_driver(xway_gphy); - --static struct mdio_device_id __maybe_unused xway_gphy_tbl[] = { -+static const struct mdio_device_id __maybe_unused xway_gphy_tbl[] = { - { PHY_ID_PHY11G_1_3, 0xffffffff }, - { PHY_ID_PHY22F_1_3, 0xffffffff }, - { PHY_ID_PHY11G_1_4, 0xffffffff }, ---- a/drivers/net/phy/lxt.c -+++ b/drivers/net/phy/lxt.c -@@ -348,7 +348,7 @@ static struct phy_driver lxt97x_driver[] - - module_phy_driver(lxt97x_driver); - --static struct mdio_device_id __maybe_unused lxt_tbl[] = { -+static const struct mdio_device_id __maybe_unused lxt_tbl[] = { - { 0x78100000, 0xfffffff0 }, - { 0x001378e0, 0xfffffff0 }, - { 0x00137a10, 0xfffffff0 }, ---- a/drivers/net/phy/marvell-88q2xxx.c -+++ b/drivers/net/phy/marvell-88q2xxx.c -@@ -940,7 +940,7 @@ static struct phy_driver mv88q2xxx_drive - - module_phy_driver(mv88q2xxx_driver); - --static struct mdio_device_id __maybe_unused mv88q2xxx_tbl[] = { -+static const struct mdio_device_id __maybe_unused mv88q2xxx_tbl[] = { - { MARVELL_PHY_ID_88Q2110, MARVELL_PHY_ID_MASK }, - { MARVELL_PHY_ID_88Q2220, MARVELL_PHY_ID_MASK }, - { /*sentinel*/ } ---- a/drivers/net/phy/marvell-88x2222.c -+++ b/drivers/net/phy/marvell-88x2222.c -@@ -613,7 +613,7 @@ static struct phy_driver mv2222_drivers[ - }; - module_phy_driver(mv2222_drivers); - --static struct mdio_device_id __maybe_unused mv2222_tbl[] = { -+static const struct mdio_device_id __maybe_unused mv2222_tbl[] = { - { MARVELL_PHY_ID_88X2222, MARVELL_PHY_ID_MASK }, - { } - }; ---- a/drivers/net/phy/marvell.c -+++ b/drivers/net/phy/marvell.c -@@ -4218,7 +4218,7 @@ static struct phy_driver marvell_drivers - - module_phy_driver(marvell_drivers); - --static struct mdio_device_id __maybe_unused marvell_tbl[] = { -+static const struct mdio_device_id __maybe_unused marvell_tbl[] = { - { MARVELL_PHY_ID_88E1101, MARVELL_PHY_ID_MASK }, - { MARVELL_PHY_ID_88E3082, MARVELL_PHY_ID_MASK }, - { MARVELL_PHY_ID_88E1112, MARVELL_PHY_ID_MASK }, ---- a/drivers/net/phy/marvell10g.c -+++ b/drivers/net/phy/marvell10g.c -@@ -1484,7 +1484,7 @@ static struct phy_driver mv3310_drivers[ - - module_phy_driver(mv3310_drivers); - --static struct mdio_device_id __maybe_unused mv3310_tbl[] = { -+static const struct mdio_device_id __maybe_unused mv3310_tbl[] = { - { MARVELL_PHY_ID_88X3310, MARVELL_PHY_ID_MASK }, - { MARVELL_PHY_ID_88E2110, MARVELL_PHY_ID_MASK }, - { }, ---- a/drivers/net/phy/mediatek/mtk-ge-soc.c -+++ b/drivers/net/phy/mediatek/mtk-ge-soc.c -@@ -1356,7 +1356,7 @@ static struct phy_driver mtk_socphy_driv - - module_phy_driver(mtk_socphy_driver); - --static struct mdio_device_id __maybe_unused mtk_socphy_tbl[] = { -+static const struct mdio_device_id __maybe_unused mtk_socphy_tbl[] = { - { PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7981) }, - { PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7988) }, - { } ---- a/drivers/net/phy/mediatek/mtk-ge.c -+++ b/drivers/net/phy/mediatek/mtk-ge.c -@@ -93,7 +93,7 @@ static struct phy_driver mtk_gephy_drive - - module_phy_driver(mtk_gephy_driver); - --static struct mdio_device_id __maybe_unused mtk_gephy_tbl[] = { -+static const struct mdio_device_id __maybe_unused mtk_gephy_tbl[] = { - { PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7530) }, - { PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7531) }, - { } ---- a/drivers/net/phy/meson-gxl.c -+++ b/drivers/net/phy/meson-gxl.c -@@ -221,7 +221,7 @@ static struct phy_driver meson_gxl_phy[] - }, - }; - --static struct mdio_device_id __maybe_unused meson_gxl_tbl[] = { -+static const struct mdio_device_id __maybe_unused meson_gxl_tbl[] = { - { PHY_ID_MATCH_VENDOR(0x01814400) }, - { PHY_ID_MATCH_VENDOR(0x01803301) }, - { } ---- a/drivers/net/phy/micrel.c -+++ b/drivers/net/phy/micrel.c -@@ -5835,7 +5835,7 @@ MODULE_DESCRIPTION("Micrel PHY driver"); - MODULE_AUTHOR("David J. Choi"); - MODULE_LICENSE("GPL"); - --static struct mdio_device_id __maybe_unused micrel_tbl[] = { -+static const struct mdio_device_id __maybe_unused micrel_tbl[] = { - { PHY_ID_KSZ9021, 0x000ffffe }, - { PHY_ID_KSZ9031, MICREL_PHY_ID_MASK }, - { PHY_ID_KSZ9131, MICREL_PHY_ID_MASK }, ---- a/drivers/net/phy/microchip.c -+++ b/drivers/net/phy/microchip.c -@@ -509,7 +509,7 @@ static struct phy_driver microchip_phy_d - - module_phy_driver(microchip_phy_driver); - --static struct mdio_device_id __maybe_unused microchip_tbl[] = { -+static const struct mdio_device_id __maybe_unused microchip_tbl[] = { - { 0x0007c132, 0xfffffff2 }, - { PHY_ID_MATCH_MODEL(PHY_ID_LAN937X_TX) }, - { } ---- a/drivers/net/phy/microchip_t1.c -+++ b/drivers/net/phy/microchip_t1.c -@@ -1886,7 +1886,7 @@ static struct phy_driver microchip_t1_ph - - module_phy_driver(microchip_t1_phy_driver); - --static struct mdio_device_id __maybe_unused microchip_t1_tbl[] = { -+static const struct mdio_device_id __maybe_unused microchip_t1_tbl[] = { - { PHY_ID_MATCH_MODEL(PHY_ID_LAN87XX) }, - { PHY_ID_MATCH_MODEL(PHY_ID_LAN937X) }, - { PHY_ID_MATCH_MODEL(PHY_ID_LAN887X) }, ---- a/drivers/net/phy/microchip_t1s.c -+++ b/drivers/net/phy/microchip_t1s.c -@@ -323,7 +323,7 @@ static struct phy_driver microchip_t1s_d - - module_phy_driver(microchip_t1s_driver); - --static struct mdio_device_id __maybe_unused tbl[] = { -+static const struct mdio_device_id __maybe_unused tbl[] = { - { PHY_ID_MATCH_EXACT(PHY_ID_LAN867X_REVB1) }, - { PHY_ID_MATCH_EXACT(PHY_ID_LAN865X_REVB0) }, - { } ---- a/drivers/net/phy/mscc/mscc_main.c -+++ b/drivers/net/phy/mscc/mscc_main.c -@@ -2710,7 +2710,7 @@ static struct phy_driver vsc85xx_driver[ - - module_phy_driver(vsc85xx_driver); - --static struct mdio_device_id __maybe_unused vsc85xx_tbl[] = { -+static const struct mdio_device_id __maybe_unused vsc85xx_tbl[] = { - { PHY_ID_MATCH_VENDOR(PHY_VENDOR_MSCC) }, - { } - }; ---- a/drivers/net/phy/mxl-gpy.c -+++ b/drivers/net/phy/mxl-gpy.c -@@ -1047,7 +1047,7 @@ static struct phy_driver gpy_drivers[] = - }; - module_phy_driver(gpy_drivers); - --static struct mdio_device_id __maybe_unused gpy_tbl[] = { -+static const struct mdio_device_id __maybe_unused gpy_tbl[] = { - {PHY_ID_MATCH_MODEL(PHY_ID_GPY2xx)}, - {PHY_ID_GPY115B, PHY_ID_GPYx15B_MASK}, - {PHY_ID_MATCH_MODEL(PHY_ID_GPY115C)}, ---- a/drivers/net/phy/national.c -+++ b/drivers/net/phy/national.c -@@ -173,7 +173,7 @@ MODULE_DESCRIPTION("NatSemi PHY driver") - MODULE_AUTHOR("Stuart Menefy"); - MODULE_LICENSE("GPL"); - --static struct mdio_device_id __maybe_unused ns_tbl[] = { -+static const struct mdio_device_id __maybe_unused ns_tbl[] = { - { DP83865_PHY_ID, 0xfffffff0 }, - { } - }; ---- a/drivers/net/phy/ncn26000.c -+++ b/drivers/net/phy/ncn26000.c -@@ -159,7 +159,7 @@ static struct phy_driver ncn26000_driver - - module_phy_driver(ncn26000_driver); - --static struct mdio_device_id __maybe_unused ncn26000_tbl[] = { -+static const struct mdio_device_id __maybe_unused ncn26000_tbl[] = { - { PHY_ID_MATCH_MODEL(PHY_ID_NCN26000) }, - { } - }; ---- a/drivers/net/phy/nxp-c45-tja11xx.c -+++ b/drivers/net/phy/nxp-c45-tja11xx.c -@@ -2102,7 +2102,7 @@ static struct phy_driver nxp_c45_driver[ - - module_phy_driver(nxp_c45_driver); - --static struct mdio_device_id __maybe_unused nxp_c45_tbl[] = { -+static const struct mdio_device_id __maybe_unused nxp_c45_tbl[] = { - { PHY_ID_MATCH_MODEL(PHY_ID_TJA_1103) }, - { PHY_ID_MATCH_MODEL(PHY_ID_TJA_1120) }, - { /*sentinel*/ }, ---- a/drivers/net/phy/nxp-cbtx.c -+++ b/drivers/net/phy/nxp-cbtx.c -@@ -215,7 +215,7 @@ static struct phy_driver cbtx_driver[] = - - module_phy_driver(cbtx_driver); - --static struct mdio_device_id __maybe_unused cbtx_tbl[] = { -+static const struct mdio_device_id __maybe_unused cbtx_tbl[] = { - { PHY_ID_MATCH_MODEL(PHY_ID_CBTX_SJA1110) }, - { }, - }; ---- a/drivers/net/phy/nxp-tja11xx.c -+++ b/drivers/net/phy/nxp-tja11xx.c -@@ -888,7 +888,7 @@ static struct phy_driver tja11xx_driver[ - - module_phy_driver(tja11xx_driver); - --static struct mdio_device_id __maybe_unused tja11xx_tbl[] = { -+static const struct mdio_device_id __maybe_unused tja11xx_tbl[] = { - { PHY_ID_MATCH_MODEL(PHY_ID_TJA1100) }, - { PHY_ID_MATCH_MODEL(PHY_ID_TJA1101) }, - { PHY_ID_MATCH_MODEL(PHY_ID_TJA1102) }, ---- a/drivers/net/phy/qcom/at803x.c -+++ b/drivers/net/phy/qcom/at803x.c -@@ -1071,7 +1071,7 @@ static struct phy_driver at803x_driver[] - - module_phy_driver(at803x_driver); - --static struct mdio_device_id __maybe_unused atheros_tbl[] = { -+static const struct mdio_device_id __maybe_unused atheros_tbl[] = { - { ATH8030_PHY_ID, AT8030_PHY_ID_MASK }, - { PHY_ID_MATCH_EXACT(ATH8031_PHY_ID) }, - { PHY_ID_MATCH_EXACT(ATH8032_PHY_ID) }, ---- a/drivers/net/phy/qcom/qca807x.c -+++ b/drivers/net/phy/qcom/qca807x.c -@@ -828,7 +828,7 @@ static struct phy_driver qca807x_drivers - }; - module_phy_driver(qca807x_drivers); - --static struct mdio_device_id __maybe_unused qca807x_tbl[] = { -+static const struct mdio_device_id __maybe_unused qca807x_tbl[] = { - { PHY_ID_MATCH_EXACT(PHY_ID_QCA8072) }, - { PHY_ID_MATCH_EXACT(PHY_ID_QCA8075) }, - { } ---- a/drivers/net/phy/qcom/qca808x.c -+++ b/drivers/net/phy/qcom/qca808x.c -@@ -655,7 +655,7 @@ static struct phy_driver qca808x_driver[ - - module_phy_driver(qca808x_driver); - --static struct mdio_device_id __maybe_unused qca808x_tbl[] = { -+static const struct mdio_device_id __maybe_unused qca808x_tbl[] = { - { PHY_ID_MATCH_EXACT(QCA8081_PHY_ID) }, - { } - }; ---- a/drivers/net/phy/qcom/qca83xx.c -+++ b/drivers/net/phy/qcom/qca83xx.c -@@ -261,7 +261,7 @@ static struct phy_driver qca83xx_driver[ - - module_phy_driver(qca83xx_driver); - --static struct mdio_device_id __maybe_unused qca83xx_tbl[] = { -+static const struct mdio_device_id __maybe_unused qca83xx_tbl[] = { - { PHY_ID_MATCH_EXACT(QCA8337_PHY_ID) }, - { PHY_ID_MATCH_EXACT(QCA8327_A_PHY_ID) }, - { PHY_ID_MATCH_EXACT(QCA8327_B_PHY_ID) }, ---- a/drivers/net/phy/qsemi.c -+++ b/drivers/net/phy/qsemi.c -@@ -155,7 +155,7 @@ static struct phy_driver qs6612_driver[] - - module_phy_driver(qs6612_driver); - --static struct mdio_device_id __maybe_unused qs6612_tbl[] = { -+static const struct mdio_device_id __maybe_unused qs6612_tbl[] = { - { 0x00181440, 0xfffffff0 }, - { } - }; ---- a/drivers/net/phy/rockchip.c -+++ b/drivers/net/phy/rockchip.c -@@ -188,7 +188,7 @@ static struct phy_driver rockchip_phy_dr - - module_phy_driver(rockchip_phy_driver); - --static struct mdio_device_id __maybe_unused rockchip_phy_tbl[] = { -+static const struct mdio_device_id __maybe_unused rockchip_phy_tbl[] = { - { INTERNAL_EPHY_ID, 0xfffffff0 }, - { } - }; ---- a/drivers/net/phy/smsc.c -+++ b/drivers/net/phy/smsc.c -@@ -885,7 +885,7 @@ MODULE_DESCRIPTION("SMSC PHY driver"); - MODULE_AUTHOR("Herbert Valerio Riedel"); - MODULE_LICENSE("GPL"); - --static struct mdio_device_id __maybe_unused smsc_tbl[] = { -+static const struct mdio_device_id __maybe_unused smsc_tbl[] = { - { 0x0007c0a0, 0xfffffff0 }, - { 0x0007c0b0, 0xfffffff0 }, - { 0x0007c0c0, 0xfffffff0 }, ---- a/drivers/net/phy/ste10Xp.c -+++ b/drivers/net/phy/ste10Xp.c -@@ -124,7 +124,7 @@ static struct phy_driver ste10xp_pdriver - - module_phy_driver(ste10xp_pdriver); - --static struct mdio_device_id __maybe_unused ste10Xp_tbl[] = { -+static const struct mdio_device_id __maybe_unused ste10Xp_tbl[] = { - { STE101P_PHY_ID, 0xfffffff0 }, - { STE100P_PHY_ID, 0xffffffff }, - { } ---- a/drivers/net/phy/teranetics.c -+++ b/drivers/net/phy/teranetics.c -@@ -87,7 +87,7 @@ static struct phy_driver teranetics_driv - - module_phy_driver(teranetics_driver); - --static struct mdio_device_id __maybe_unused teranetics_tbl[] = { -+static const struct mdio_device_id __maybe_unused teranetics_tbl[] = { - { PHY_ID_TN2020, 0xffffffff }, - { } - }; ---- a/drivers/net/phy/uPD60620.c -+++ b/drivers/net/phy/uPD60620.c -@@ -90,7 +90,7 @@ static struct phy_driver upd60620_driver - - module_phy_driver(upd60620_driver); - --static struct mdio_device_id __maybe_unused upd60620_tbl[] = { -+static const struct mdio_device_id __maybe_unused upd60620_tbl[] = { - { UPD60620_PHY_ID, 0xfffffffe }, - { } - }; ---- a/drivers/net/phy/vitesse.c -+++ b/drivers/net/phy/vitesse.c -@@ -674,7 +674,7 @@ static struct phy_driver vsc82xx_driver[ - - module_phy_driver(vsc82xx_driver); - --static struct mdio_device_id __maybe_unused vitesse_tbl[] = { -+static const struct mdio_device_id __maybe_unused vitesse_tbl[] = { - { PHY_ID_VSC8234, 0x000ffff0 }, - { PHY_ID_VSC8244, 0x000fffc0 }, - { PHY_ID_VSC8572, 0x000ffff0 }, diff --git a/target/linux/generic/backport-6.18/720-10-v6.15-net-phy-mediatek-Change-to-more-meaningful-macros.patch b/target/linux/generic/backport-6.18/720-10-v6.15-net-phy-mediatek-Change-to-more-meaningful-macros.patch deleted file mode 100644 index 545e92987f..0000000000 --- a/target/linux/generic/backport-6.18/720-10-v6.15-net-phy-mediatek-Change-to-more-meaningful-macros.patch +++ /dev/null @@ -1,146 +0,0 @@ -From 7e06c3dbfa5f1e39eba92eb79d854fab2a7ad5fe Mon Sep 17 00:00:00 2001 -From: Sky Huang -Date: Thu, 13 Feb 2025 16:05:49 +0800 -Subject: [PATCH 10/20] net: phy: mediatek: Change to more meaningful macros - -Replace magic number with more meaningful macros in mtk-ge.c. -Also, move some common macros into mtk-phy-lib.c. - -Signed-off-by: Sky Huang -Reviewed-by: Andrew Lunn -Link: https://patch.msgid.link/20250213080553.921434-2-SkyLake.Huang@mediatek.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/mediatek/mtk-ge-soc.c | 1 - - drivers/net/phy/mediatek/mtk-ge.c | 71 +++++++++++++++++++++------ - drivers/net/phy/mediatek/mtk.h | 2 + - 3 files changed, 57 insertions(+), 17 deletions(-) - ---- a/drivers/net/phy/mediatek/mtk-ge-soc.c -+++ b/drivers/net/phy/mediatek/mtk-ge-soc.c -@@ -24,7 +24,6 @@ - #define MTK_PHY_SMI_DET_ON_THRESH_MASK GENMASK(13, 8) - - #define MTK_PHY_PAGE_EXTENDED_2A30 0x2a30 --#define MTK_PHY_PAGE_EXTENDED_52B5 0x52b5 - - #define ANALOG_INTERNAL_OPERATION_MAX_US 20 - #define TXRESERVE_MIN 0 ---- a/drivers/net/phy/mediatek/mtk-ge.c -+++ b/drivers/net/phy/mediatek/mtk-ge.c -@@ -8,18 +8,38 @@ - #define MTK_GPHY_ID_MT7530 0x03a29412 - #define MTK_GPHY_ID_MT7531 0x03a29441 - --#define MTK_EXT_PAGE_ACCESS 0x1f --#define MTK_PHY_PAGE_STANDARD 0x0000 --#define MTK_PHY_PAGE_EXTENDED 0x0001 --#define MTK_PHY_PAGE_EXTENDED_2 0x0002 --#define MTK_PHY_PAGE_EXTENDED_3 0x0003 --#define MTK_PHY_PAGE_EXTENDED_2A30 0x2a30 --#define MTK_PHY_PAGE_EXTENDED_52B5 0x52b5 -+#define MTK_PHY_PAGE_EXTENDED_1 0x0001 -+#define MTK_PHY_AUX_CTRL_AND_STATUS 0x14 -+#define MTK_PHY_ENABLE_DOWNSHIFT BIT(4) -+ -+#define MTK_PHY_PAGE_EXTENDED_2 0x0002 -+#define MTK_PHY_PAGE_EXTENDED_3 0x0003 -+#define MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG11 0x11 -+ -+#define MTK_PHY_PAGE_EXTENDED_2A30 0x2a30 -+ -+/* Registers on MDIO_MMD_VEND1 */ -+#define MTK_PHY_GBE_MODE_TX_DELAY_SEL 0x13 -+#define MTK_PHY_TEST_MODE_TX_DELAY_SEL 0x14 -+#define MTK_TX_DELAY_PAIR_B_MASK GENMASK(10, 8) -+#define MTK_TX_DELAY_PAIR_D_MASK GENMASK(2, 0) -+ -+#define MTK_PHY_MCC_CTRL_AND_TX_POWER_CTRL 0xa6 -+#define MTK_MCC_NEARECHO_OFFSET_MASK GENMASK(15, 8) -+ -+#define MTK_PHY_RXADC_CTRL_RG7 0xc6 -+#define MTK_PHY_DA_AD_BUF_BIAS_LP_MASK GENMASK(9, 8) -+ -+#define MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG123 0x123 -+#define MTK_PHY_LPI_NORM_MSE_LO_THRESH100_MASK GENMASK(15, 8) -+#define MTK_PHY_LPI_NORM_MSE_HI_THRESH100_MASK GENMASK(7, 0) - - static void mtk_gephy_config_init(struct phy_device *phydev) - { - /* Enable HW auto downshift */ -- phy_modify_paged(phydev, MTK_PHY_PAGE_EXTENDED, 0x14, 0, BIT(4)); -+ phy_modify_paged(phydev, MTK_PHY_PAGE_EXTENDED_1, -+ MTK_PHY_AUX_CTRL_AND_STATUS, -+ 0, MTK_PHY_ENABLE_DOWNSHIFT); - - /* Increase SlvDPSready time */ - phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5); -@@ -29,10 +49,20 @@ static void mtk_gephy_config_init(struct - phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0); - - /* Adjust 100_mse_threshold */ -- phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x123, 0xffff); -- -- /* Disable mcc */ -- phy_write_mmd(phydev, MDIO_MMD_VEND1, 0xa6, 0x300); -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, -+ MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG123, -+ MTK_PHY_LPI_NORM_MSE_LO_THRESH100_MASK | -+ MTK_PHY_LPI_NORM_MSE_HI_THRESH100_MASK, -+ FIELD_PREP(MTK_PHY_LPI_NORM_MSE_LO_THRESH100_MASK, -+ 0xff) | -+ FIELD_PREP(MTK_PHY_LPI_NORM_MSE_HI_THRESH100_MASK, -+ 0xff)); -+ -+ /* If echo time is narrower than 0x3, it will be regarded as noise */ -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, -+ MTK_PHY_MCC_CTRL_AND_TX_POWER_CTRL, -+ MTK_MCC_NEARECHO_OFFSET_MASK, -+ FIELD_PREP(MTK_MCC_NEARECHO_OFFSET_MASK, 0x3)); - } - - static int mt7530_phy_config_init(struct phy_device *phydev) -@@ -40,7 +70,8 @@ static int mt7530_phy_config_init(struct - mtk_gephy_config_init(phydev); - - /* Increase post_update_timer */ -- phy_write_paged(phydev, MTK_PHY_PAGE_EXTENDED_3, 0x11, 0x4b); -+ phy_write_paged(phydev, MTK_PHY_PAGE_EXTENDED_3, -+ MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG11, 0x4b); - - return 0; - } -@@ -51,11 +82,19 @@ static int mt7531_phy_config_init(struct - - /* PHY link down power saving enable */ - phy_set_bits(phydev, 0x17, BIT(4)); -- phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, 0xc6, 0x300); -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RXADC_CTRL_RG7, -+ MTK_PHY_DA_AD_BUF_BIAS_LP_MASK, -+ FIELD_PREP(MTK_PHY_DA_AD_BUF_BIAS_LP_MASK, 0x3)); - - /* Set TX Pair delay selection */ -- phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x13, 0x404); -- phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x14, 0x404); -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_GBE_MODE_TX_DELAY_SEL, -+ MTK_TX_DELAY_PAIR_B_MASK | MTK_TX_DELAY_PAIR_D_MASK, -+ FIELD_PREP(MTK_TX_DELAY_PAIR_B_MASK, 0x4) | -+ FIELD_PREP(MTK_TX_DELAY_PAIR_D_MASK, 0x4)); -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TEST_MODE_TX_DELAY_SEL, -+ MTK_TX_DELAY_PAIR_B_MASK | MTK_TX_DELAY_PAIR_D_MASK, -+ FIELD_PREP(MTK_TX_DELAY_PAIR_B_MASK, 0x4) | -+ FIELD_PREP(MTK_TX_DELAY_PAIR_D_MASK, 0x4)); - - return 0; - } ---- a/drivers/net/phy/mediatek/mtk.h -+++ b/drivers/net/phy/mediatek/mtk.h -@@ -9,6 +9,8 @@ - #define _MTK_EPHY_H_ - - #define MTK_EXT_PAGE_ACCESS 0x1f -+#define MTK_PHY_PAGE_STANDARD 0x0000 -+#define MTK_PHY_PAGE_EXTENDED_52B5 0x52b5 - - /* Registers on MDIO_MMD_VEND2 */ - #define MTK_PHY_LED0_ON_CTRL 0x24 diff --git a/target/linux/generic/backport-6.18/720-11-v6.15-net-phy-mediatek-Add-token-ring-access-helper-functi.patch b/target/linux/generic/backport-6.18/720-11-v6.15-net-phy-mediatek-Add-token-ring-access-helper-functi.patch deleted file mode 100644 index 40ce29fc51..0000000000 --- a/target/linux/generic/backport-6.18/720-11-v6.15-net-phy-mediatek-Add-token-ring-access-helper-functi.patch +++ /dev/null @@ -1,448 +0,0 @@ -From 6e7370079669b0d55c9464bb7c3fb8fb7368b912 Mon Sep 17 00:00:00 2001 -From: Sky Huang -Date: Thu, 13 Feb 2025 16:05:50 +0800 -Subject: [PATCH 11/20] net: phy: mediatek: Add token ring access helper - functions in mtk-phy-lib - -This patch adds TR(token ring) manipulations and adds correct -macro names for those magic numbers. TR is a way to access -proprietary registers on page 52b5. Use these helper functions -so we can see which fields we're going to modify/set/clear. - -TR functions with __* prefix mean that the operations inside -aren't wrapped by page select/restore functions. - -This patch doesn't really change registers' settings but just -enhances readability and maintainability. - -Signed-off-by: Sky Huang -Reviewed-by: Andrew Lunn -Link: https://patch.msgid.link/20250213080553.921434-3-SkyLake.Huang@mediatek.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/mediatek/mtk-ge-soc.c | 231 +++++++++++++++++-------- - drivers/net/phy/mediatek/mtk-ge.c | 11 +- - drivers/net/phy/mediatek/mtk-phy-lib.c | 63 +++++++ - drivers/net/phy/mediatek/mtk.h | 5 + - 4 files changed, 230 insertions(+), 80 deletions(-) - ---- a/drivers/net/phy/mediatek/mtk-ge-soc.c -+++ b/drivers/net/phy/mediatek/mtk-ge-soc.c -@@ -25,6 +25,90 @@ - - #define MTK_PHY_PAGE_EXTENDED_2A30 0x2a30 - -+/* Registers on Token Ring debug nodes */ -+/* ch_addr = 0x0, node_addr = 0x7, data_addr = 0x15 */ -+/* NormMseLoThresh */ -+#define NORMAL_MSE_LO_THRESH_MASK GENMASK(15, 8) -+ -+/* ch_addr = 0x0, node_addr = 0xf, data_addr = 0x3c */ -+/* RemAckCntLimitCtrl */ -+#define REMOTE_ACK_COUNT_LIMIT_CTRL_MASK GENMASK(2, 1) -+ -+/* ch_addr = 0x1, node_addr = 0xd, data_addr = 0x20 */ -+/* VcoSlicerThreshBitsHigh */ -+#define VCO_SLICER_THRESH_HIGH_MASK GENMASK(23, 0) -+ -+/* ch_addr = 0x1, node_addr = 0xf, data_addr = 0x0 */ -+/* DfeTailEnableVgaThresh1000 */ -+#define DFE_TAIL_EANBLE_VGA_TRHESH_1000 GENMASK(5, 1) -+ -+/* ch_addr = 0x1, node_addr = 0xf, data_addr = 0x1 */ -+/* MrvlTrFix100Kp */ -+#define MRVL_TR_FIX_100KP_MASK GENMASK(22, 20) -+/* MrvlTrFix100Kf */ -+#define MRVL_TR_FIX_100KF_MASK GENMASK(19, 17) -+/* MrvlTrFix1000Kp */ -+#define MRVL_TR_FIX_1000KP_MASK GENMASK(16, 14) -+/* MrvlTrFix1000Kf */ -+#define MRVL_TR_FIX_1000KF_MASK GENMASK(13, 11) -+ -+/* ch_addr = 0x1, node_addr = 0xf, data_addr = 0x12 */ -+/* VgaDecRate */ -+#define VGA_DECIMATION_RATE_MASK GENMASK(8, 5) -+ -+/* ch_addr = 0x1, node_addr = 0xf, data_addr = 0x17 */ -+/* SlvDSPreadyTime */ -+#define SLAVE_DSP_READY_TIME_MASK GENMASK(22, 15) -+/* MasDSPreadyTime */ -+#define MASTER_DSP_READY_TIME_MASK GENMASK(14, 7) -+ -+/* ch_addr = 0x1, node_addr = 0xf, data_addr = 0x20 */ -+/* ResetSyncOffset */ -+#define RESET_SYNC_OFFSET_MASK GENMASK(11, 8) -+ -+/* ch_addr = 0x2, node_addr = 0xd, data_addr = 0x0 */ -+/* FfeUpdGainForceVal */ -+#define FFE_UPDATE_GAIN_FORCE_VAL_MASK GENMASK(9, 7) -+/* FfeUpdGainForce */ -+#define FFE_UPDATE_GAIN_FORCE BIT(6) -+ -+/* ch_addr = 0x2, node_addr = 0xd, data_addr = 0x6 */ -+/* SS: Steady-state, KP: Proportional Gain */ -+/* SSTrKp100 */ -+#define SS_TR_KP100_MASK GENMASK(21, 19) -+/* SSTrKf100 */ -+#define SS_TR_KF100_MASK GENMASK(18, 16) -+/* SSTrKp1000Mas */ -+#define SS_TR_KP1000_MASTER_MASK GENMASK(15, 13) -+/* SSTrKf1000Mas */ -+#define SS_TR_KF1000_MASTER_MASK GENMASK(12, 10) -+/* SSTrKp1000Slv */ -+#define SS_TR_KP1000_SLAVE_MASK GENMASK(9, 7) -+/* SSTrKf1000Slv */ -+#define SS_TR_KF1000_SLAVE_MASK GENMASK(6, 4) -+ -+/* ch_addr = 0x2, node_addr = 0xd, data_addr = 0xd */ -+/* RegEEE_st2TrKf1000 */ -+#define EEE1000_STAGE2_TR_KF_MASK GENMASK(13, 11) -+ -+/* ch_addr = 0x2, node_addr = 0xd, data_addr = 0xf */ -+/* RegEEE_slv_waketr_timer_tar */ -+#define SLAVE_WAKETR_TIMER_MASK GENMASK(20, 11) -+/* RegEEE_slv_remtx_timer_tar */ -+#define SLAVE_REMTX_TIMER_MASK GENMASK(10, 1) -+ -+/* ch_addr = 0x2, node_addr = 0xd, data_addr = 0x10 */ -+/* RegEEE_slv_wake_int_timer_tar */ -+#define SLAVE_WAKEINT_TIMER_MASK GENMASK(10, 1) -+ -+/* ch_addr = 0x2, node_addr = 0xd, data_addr = 0x14 */ -+/* RegEEE_trfreeze_timer2 */ -+#define TR_FREEZE_TIMER2_MASK GENMASK(9, 0) -+ -+/* ch_addr = 0x2, node_addr = 0xd, data_addr = 0x1c */ -+/* RegEEE100Stg1_tar */ -+#define EEE100_LPSYNC_STAGE1_UPDATE_TIMER_MASK GENMASK(8, 0) -+ - #define ANALOG_INTERNAL_OPERATION_MAX_US 20 - #define TXRESERVE_MIN 0 - #define TXRESERVE_MAX 7 -@@ -700,40 +784,41 @@ restore: - static void mt798x_phy_common_finetune(struct phy_device *phydev) - { - phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5); -- /* SlvDSPreadyTime = 24, MasDSPreadyTime = 24 */ -- __phy_write(phydev, 0x11, 0xc71); -- __phy_write(phydev, 0x12, 0xc); -- __phy_write(phydev, 0x10, 0x8fae); -+ __mtk_tr_modify(phydev, 0x1, 0xf, 0x17, -+ SLAVE_DSP_READY_TIME_MASK | MASTER_DSP_READY_TIME_MASK, -+ FIELD_PREP(SLAVE_DSP_READY_TIME_MASK, 0x18) | -+ FIELD_PREP(MASTER_DSP_READY_TIME_MASK, 0x18)); - - /* EnabRandUpdTrig = 1 */ - __phy_write(phydev, 0x11, 0x2f00); - __phy_write(phydev, 0x12, 0xe); - __phy_write(phydev, 0x10, 0x8fb0); - -- /* NormMseLoThresh = 85 */ -- __phy_write(phydev, 0x11, 0x55a0); -- __phy_write(phydev, 0x12, 0x0); -- __phy_write(phydev, 0x10, 0x83aa); -- -- /* FfeUpdGainForce = 1(Enable), FfeUpdGainForceVal = 4 */ -- __phy_write(phydev, 0x11, 0x240); -- __phy_write(phydev, 0x12, 0x0); -- __phy_write(phydev, 0x10, 0x9680); -+ __mtk_tr_modify(phydev, 0x0, 0x7, 0x15, -+ NORMAL_MSE_LO_THRESH_MASK, -+ FIELD_PREP(NORMAL_MSE_LO_THRESH_MASK, 0x55)); -+ -+ __mtk_tr_modify(phydev, 0x2, 0xd, 0x0, -+ FFE_UPDATE_GAIN_FORCE_VAL_MASK, -+ FIELD_PREP(FFE_UPDATE_GAIN_FORCE_VAL_MASK, 0x4) | -+ FFE_UPDATE_GAIN_FORCE); - - /* TrFreeze = 0 (mt7988 default) */ - __phy_write(phydev, 0x11, 0x0); - __phy_write(phydev, 0x12, 0x0); - __phy_write(phydev, 0x10, 0x9686); - -- /* SSTrKp100 = 5 */ -- /* SSTrKf100 = 6 */ -- /* SSTrKp1000Mas = 5 */ -- /* SSTrKf1000Mas = 6 */ -- /* SSTrKp1000Slv = 5 */ -- /* SSTrKf1000Slv = 6 */ -- __phy_write(phydev, 0x11, 0xbaef); -- __phy_write(phydev, 0x12, 0x2e); -- __phy_write(phydev, 0x10, 0x968c); -+ __mtk_tr_modify(phydev, 0x2, 0xd, 0x6, -+ SS_TR_KP100_MASK | SS_TR_KF100_MASK | -+ SS_TR_KP1000_MASTER_MASK | SS_TR_KF1000_MASTER_MASK | -+ SS_TR_KP1000_SLAVE_MASK | SS_TR_KF1000_SLAVE_MASK, -+ FIELD_PREP(SS_TR_KP100_MASK, 0x5) | -+ FIELD_PREP(SS_TR_KF100_MASK, 0x6) | -+ FIELD_PREP(SS_TR_KP1000_MASTER_MASK, 0x5) | -+ FIELD_PREP(SS_TR_KF1000_MASTER_MASK, 0x6) | -+ FIELD_PREP(SS_TR_KP1000_SLAVE_MASK, 0x5) | -+ FIELD_PREP(SS_TR_KF1000_SLAVE_MASK, 0x6)); -+ - phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0); - } - -@@ -756,27 +841,29 @@ static void mt7981_phy_finetune(struct p - } - - phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5); -- /* ResetSyncOffset = 6 */ -- __phy_write(phydev, 0x11, 0x600); -- __phy_write(phydev, 0x12, 0x0); -- __phy_write(phydev, 0x10, 0x8fc0); -- -- /* VgaDecRate = 1 */ -- __phy_write(phydev, 0x11, 0x4c2a); -- __phy_write(phydev, 0x12, 0x3e); -- __phy_write(phydev, 0x10, 0x8fa4); -+ __mtk_tr_modify(phydev, 0x1, 0xf, 0x20, -+ RESET_SYNC_OFFSET_MASK, -+ FIELD_PREP(RESET_SYNC_OFFSET_MASK, 0x6)); -+ -+ __mtk_tr_modify(phydev, 0x1, 0xf, 0x12, -+ VGA_DECIMATION_RATE_MASK, -+ FIELD_PREP(VGA_DECIMATION_RATE_MASK, 0x1)); - - /* MrvlTrFix100Kp = 3, MrvlTrFix100Kf = 2, - * MrvlTrFix1000Kp = 3, MrvlTrFix1000Kf = 2 - */ -- __phy_write(phydev, 0x11, 0xd10a); -- __phy_write(phydev, 0x12, 0x34); -- __phy_write(phydev, 0x10, 0x8f82); -+ __mtk_tr_modify(phydev, 0x1, 0xf, 0x1, -+ MRVL_TR_FIX_100KP_MASK | MRVL_TR_FIX_100KF_MASK | -+ MRVL_TR_FIX_1000KP_MASK | MRVL_TR_FIX_1000KF_MASK, -+ FIELD_PREP(MRVL_TR_FIX_100KP_MASK, 0x3) | -+ FIELD_PREP(MRVL_TR_FIX_100KF_MASK, 0x2) | -+ FIELD_PREP(MRVL_TR_FIX_1000KP_MASK, 0x3) | -+ FIELD_PREP(MRVL_TR_FIX_1000KF_MASK, 0x2)); - - /* VcoSlicerThreshBitsHigh */ -- __phy_write(phydev, 0x11, 0x5555); -- __phy_write(phydev, 0x12, 0x55); -- __phy_write(phydev, 0x10, 0x8ec0); -+ __mtk_tr_modify(phydev, 0x1, 0xd, 0x20, -+ VCO_SLICER_THRESH_HIGH_MASK, -+ FIELD_PREP(VCO_SLICER_THRESH_HIGH_MASK, 0x555555)); - phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0); - - /* TR_OPEN_LOOP_EN = 1, lpf_x_average = 9 */ -@@ -828,25 +915,23 @@ static void mt7988_phy_finetune(struct p - phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_TX_FILTER, 0x5); - - phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5); -- /* ResetSyncOffset = 5 */ -- __phy_write(phydev, 0x11, 0x500); -- __phy_write(phydev, 0x12, 0x0); -- __phy_write(phydev, 0x10, 0x8fc0); -+ __mtk_tr_modify(phydev, 0x1, 0xf, 0x20, -+ RESET_SYNC_OFFSET_MASK, -+ FIELD_PREP(RESET_SYNC_OFFSET_MASK, 0x5)); - - /* VgaDecRate is 1 at default on mt7988 */ - -- /* MrvlTrFix100Kp = 6, MrvlTrFix100Kf = 7, -- * MrvlTrFix1000Kp = 6, MrvlTrFix1000Kf = 7 -- */ -- __phy_write(phydev, 0x11, 0xb90a); -- __phy_write(phydev, 0x12, 0x6f); -- __phy_write(phydev, 0x10, 0x8f82); -- -- /* RemAckCntLimitCtrl = 1 */ -- __phy_write(phydev, 0x11, 0xfbba); -- __phy_write(phydev, 0x12, 0xc3); -- __phy_write(phydev, 0x10, 0x87f8); -- -+ __mtk_tr_modify(phydev, 0x1, 0xf, 0x1, -+ MRVL_TR_FIX_100KP_MASK | MRVL_TR_FIX_100KF_MASK | -+ MRVL_TR_FIX_1000KP_MASK | MRVL_TR_FIX_1000KF_MASK, -+ FIELD_PREP(MRVL_TR_FIX_100KP_MASK, 0x6) | -+ FIELD_PREP(MRVL_TR_FIX_100KF_MASK, 0x7) | -+ FIELD_PREP(MRVL_TR_FIX_1000KP_MASK, 0x6) | -+ FIELD_PREP(MRVL_TR_FIX_1000KF_MASK, 0x7)); -+ -+ __mtk_tr_modify(phydev, 0x0, 0xf, 0x3c, -+ REMOTE_ACK_COUNT_LIMIT_CTRL_MASK, -+ FIELD_PREP(REMOTE_ACK_COUNT_LIMIT_CTRL_MASK, 0x1)); - phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0); - - /* TR_OPEN_LOOP_EN = 1, lpf_x_average = 10 */ -@@ -927,40 +1012,36 @@ static void mt798x_phy_eee(struct phy_de - __phy_write(phydev, 0x12, 0x0); - __phy_write(phydev, 0x10, 0x9690); - -- /* REG_EEE_st2TrKf1000 = 2 */ -- __phy_write(phydev, 0x11, 0x114f); -- __phy_write(phydev, 0x12, 0x2); -- __phy_write(phydev, 0x10, 0x969a); -- -- /* RegEEE_slv_wake_tr_timer_tar = 6, RegEEE_slv_remtx_timer_tar = 20 */ -- __phy_write(phydev, 0x11, 0x3028); -- __phy_write(phydev, 0x12, 0x0); -- __phy_write(phydev, 0x10, 0x969e); -- -- /* RegEEE_slv_wake_int_timer_tar = 8 */ -- __phy_write(phydev, 0x11, 0x5010); -- __phy_write(phydev, 0x12, 0x0); -- __phy_write(phydev, 0x10, 0x96a0); -- -- /* RegEEE_trfreeze_timer2 = 586 */ -- __phy_write(phydev, 0x11, 0x24a); -- __phy_write(phydev, 0x12, 0x0); -- __phy_write(phydev, 0x10, 0x96a8); -- -- /* RegEEE100Stg1_tar = 16 */ -- __phy_write(phydev, 0x11, 0x3210); -- __phy_write(phydev, 0x12, 0x0); -- __phy_write(phydev, 0x10, 0x96b8); -+ __mtk_tr_modify(phydev, 0x2, 0xd, 0xd, -+ EEE1000_STAGE2_TR_KF_MASK, -+ FIELD_PREP(EEE1000_STAGE2_TR_KF_MASK, 0x2)); -+ -+ __mtk_tr_modify(phydev, 0x2, 0xd, 0xf, -+ SLAVE_WAKETR_TIMER_MASK | SLAVE_REMTX_TIMER_MASK, -+ FIELD_PREP(SLAVE_WAKETR_TIMER_MASK, 0x6) | -+ FIELD_PREP(SLAVE_REMTX_TIMER_MASK, 0x14)); -+ -+ __mtk_tr_modify(phydev, 0x2, 0xd, 0x10, -+ SLAVE_WAKEINT_TIMER_MASK, -+ FIELD_PREP(SLAVE_WAKEINT_TIMER_MASK, 0x8)); -+ -+ __mtk_tr_modify(phydev, 0x2, 0xd, 0x14, -+ TR_FREEZE_TIMER2_MASK, -+ FIELD_PREP(TR_FREEZE_TIMER2_MASK, 0x24a)); -+ -+ __mtk_tr_modify(phydev, 0x2, 0xd, 0x1c, -+ EEE100_LPSYNC_STAGE1_UPDATE_TIMER_MASK, -+ FIELD_PREP(EEE100_LPSYNC_STAGE1_UPDATE_TIMER_MASK, -+ 0x10)); - - /* REGEEE_wake_slv_tr_wait_dfesigdet_en = 0 */ - __phy_write(phydev, 0x11, 0x1463); - __phy_write(phydev, 0x12, 0x0); - __phy_write(phydev, 0x10, 0x96ca); - -- /* DfeTailEnableVgaThresh1000 = 27 */ -- __phy_write(phydev, 0x11, 0x36); -- __phy_write(phydev, 0x12, 0x0); -- __phy_write(phydev, 0x10, 0x8f80); -+ __mtk_tr_modify(phydev, 0x1, 0xf, 0x0, -+ DFE_TAIL_EANBLE_VGA_TRHESH_1000, -+ FIELD_PREP(DFE_TAIL_EANBLE_VGA_TRHESH_1000, 0x1b)); - phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0); - - phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_3); ---- a/drivers/net/phy/mediatek/mtk-ge.c -+++ b/drivers/net/phy/mediatek/mtk-ge.c -@@ -18,6 +18,10 @@ - - #define MTK_PHY_PAGE_EXTENDED_2A30 0x2a30 - -+/* Registers on Token Ring debug nodes */ -+/* ch_addr = 0x1, node_addr = 0xf, data_addr = 0x17 */ -+#define SLAVE_DSP_READY_TIME_MASK GENMASK(22, 15) -+ - /* Registers on MDIO_MMD_VEND1 */ - #define MTK_PHY_GBE_MODE_TX_DELAY_SEL 0x13 - #define MTK_PHY_TEST_MODE_TX_DELAY_SEL 0x14 -@@ -42,11 +46,8 @@ static void mtk_gephy_config_init(struct - 0, MTK_PHY_ENABLE_DOWNSHIFT); - - /* Increase SlvDPSready time */ -- phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5); -- __phy_write(phydev, 0x10, 0xafae); -- __phy_write(phydev, 0x12, 0x2f); -- __phy_write(phydev, 0x10, 0x8fae); -- phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0); -+ mtk_tr_modify(phydev, 0x1, 0xf, 0x17, SLAVE_DSP_READY_TIME_MASK, -+ FIELD_PREP(SLAVE_DSP_READY_TIME_MASK, 0x5e)); - - /* Adjust 100_mse_threshold */ - phy_modify_mmd(phydev, MDIO_MMD_VEND1, ---- a/drivers/net/phy/mediatek/mtk-phy-lib.c -+++ b/drivers/net/phy/mediatek/mtk-phy-lib.c -@@ -6,6 +6,69 @@ - - #include "mtk.h" - -+/* Difference between functions with mtk_tr* and __mtk_tr* prefixes is -+ * mtk_tr* functions: wrapped by page switching operations -+ * __mtk_tr* functions: no page switching operations -+ */ -+ -+static void __mtk_tr_access(struct phy_device *phydev, bool read, u8 ch_addr, -+ u8 node_addr, u8 data_addr) -+{ -+ u16 tr_cmd = BIT(15); /* bit 14 & 0 are reserved */ -+ -+ if (read) -+ tr_cmd |= BIT(13); -+ -+ tr_cmd |= (((ch_addr & 0x3) << 11) | -+ ((node_addr & 0xf) << 7) | -+ ((data_addr & 0x3f) << 1)); -+ dev_dbg(&phydev->mdio.dev, "tr_cmd: 0x%x\n", tr_cmd); -+ __phy_write(phydev, 0x10, tr_cmd); -+} -+ -+static void __mtk_tr_read(struct phy_device *phydev, u8 ch_addr, u8 node_addr, -+ u8 data_addr, u16 *tr_high, u16 *tr_low) -+{ -+ __mtk_tr_access(phydev, true, ch_addr, node_addr, data_addr); -+ *tr_low = __phy_read(phydev, 0x11); -+ *tr_high = __phy_read(phydev, 0x12); -+ dev_dbg(&phydev->mdio.dev, "tr_high read: 0x%x, tr_low read: 0x%x\n", -+ *tr_high, *tr_low); -+} -+ -+static void __mtk_tr_write(struct phy_device *phydev, u8 ch_addr, u8 node_addr, -+ u8 data_addr, u32 tr_data) -+{ -+ __phy_write(phydev, 0x11, tr_data & 0xffff); -+ __phy_write(phydev, 0x12, tr_data >> 16); -+ dev_dbg(&phydev->mdio.dev, "tr_high write: 0x%x, tr_low write: 0x%x\n", -+ tr_data >> 16, tr_data & 0xffff); -+ __mtk_tr_access(phydev, false, ch_addr, node_addr, data_addr); -+} -+ -+void __mtk_tr_modify(struct phy_device *phydev, u8 ch_addr, u8 node_addr, -+ u8 data_addr, u32 mask, u32 set) -+{ -+ u32 tr_data; -+ u16 tr_high; -+ u16 tr_low; -+ -+ __mtk_tr_read(phydev, ch_addr, node_addr, data_addr, &tr_high, &tr_low); -+ tr_data = (tr_high << 16) | tr_low; -+ tr_data = (tr_data & ~mask) | set; -+ __mtk_tr_write(phydev, ch_addr, node_addr, data_addr, tr_data); -+} -+EXPORT_SYMBOL_GPL(__mtk_tr_modify); -+ -+void mtk_tr_modify(struct phy_device *phydev, u8 ch_addr, u8 node_addr, -+ u8 data_addr, u32 mask, u32 set) -+{ -+ phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5); -+ __mtk_tr_modify(phydev, ch_addr, node_addr, data_addr, mask, set); -+ phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0); -+} -+EXPORT_SYMBOL_GPL(mtk_tr_modify); -+ - int mtk_phy_read_page(struct phy_device *phydev) - { - return __phy_read(phydev, MTK_EXT_PAGE_ACCESS); ---- a/drivers/net/phy/mediatek/mtk.h -+++ b/drivers/net/phy/mediatek/mtk.h -@@ -68,6 +68,11 @@ struct mtk_socphy_priv { - unsigned long led_state; - }; - -+void __mtk_tr_modify(struct phy_device *phydev, u8 ch_addr, u8 node_addr, -+ u8 data_addr, u32 mask, u32 set); -+void mtk_tr_modify(struct phy_device *phydev, u8 ch_addr, u8 node_addr, -+ u8 data_addr, u32 mask, u32 set); -+ - int mtk_phy_read_page(struct phy_device *phydev); - int mtk_phy_write_page(struct phy_device *phydev, int page); - diff --git a/target/linux/generic/backport-6.18/720-12-v6.15-net-phy-mediatek-Add-token-ring-set-bit-operation-su.patch b/target/linux/generic/backport-6.18/720-12-v6.15-net-phy-mediatek-Add-token-ring-set-bit-operation-su.patch deleted file mode 100644 index 972a9c0a7e..0000000000 --- a/target/linux/generic/backport-6.18/720-12-v6.15-net-phy-mediatek-Add-token-ring-set-bit-operation-su.patch +++ /dev/null @@ -1,73 +0,0 @@ -From c7e2fb3421ef5ebbb4c91f44bd735ab10edd755a Mon Sep 17 00:00:00 2001 -From: Sky Huang -Date: Thu, 13 Feb 2025 16:05:51 +0800 -Subject: [PATCH 12/20] net: phy: mediatek: Add token ring set bit operation - support - -Previously in mtk-ge-soc.c, we set some register bits via token -ring, which were implemented in three __phy_write(). -Now we can do the same thing via __mtk_tr_set_bits() helper. - -Signed-off-by: Sky Huang -Reviewed-by: Andrew Lunn -Link: https://patch.msgid.link/20250213080553.921434-4-SkyLake.Huang@mediatek.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/mediatek/mtk-ge-soc.c | 10 ++++++---- - drivers/net/phy/mediatek/mtk-phy-lib.c | 7 +++++++ - drivers/net/phy/mediatek/mtk.h | 2 ++ - 3 files changed, 15 insertions(+), 4 deletions(-) - ---- a/drivers/net/phy/mediatek/mtk-ge-soc.c -+++ b/drivers/net/phy/mediatek/mtk-ge-soc.c -@@ -62,6 +62,10 @@ - /* MasDSPreadyTime */ - #define MASTER_DSP_READY_TIME_MASK GENMASK(14, 7) - -+/* ch_addr = 0x1, node_addr = 0xf, data_addr = 0x18 */ -+/* EnabRandUpdTrig */ -+#define ENABLE_RANDOM_UPDOWN_COUNTER_TRIGGER BIT(8) -+ - /* ch_addr = 0x1, node_addr = 0xf, data_addr = 0x20 */ - /* ResetSyncOffset */ - #define RESET_SYNC_OFFSET_MASK GENMASK(11, 8) -@@ -789,10 +793,8 @@ static void mt798x_phy_common_finetune(s - FIELD_PREP(SLAVE_DSP_READY_TIME_MASK, 0x18) | - FIELD_PREP(MASTER_DSP_READY_TIME_MASK, 0x18)); - -- /* EnabRandUpdTrig = 1 */ -- __phy_write(phydev, 0x11, 0x2f00); -- __phy_write(phydev, 0x12, 0xe); -- __phy_write(phydev, 0x10, 0x8fb0); -+ __mtk_tr_set_bits(phydev, 0x1, 0xf, 0x18, -+ ENABLE_RANDOM_UPDOWN_COUNTER_TRIGGER); - - __mtk_tr_modify(phydev, 0x0, 0x7, 0x15, - NORMAL_MSE_LO_THRESH_MASK, ---- a/drivers/net/phy/mediatek/mtk-phy-lib.c -+++ b/drivers/net/phy/mediatek/mtk-phy-lib.c -@@ -69,6 +69,13 @@ void mtk_tr_modify(struct phy_device *ph - } - EXPORT_SYMBOL_GPL(mtk_tr_modify); - -+void __mtk_tr_set_bits(struct phy_device *phydev, u8 ch_addr, u8 node_addr, -+ u8 data_addr, u32 set) -+{ -+ __mtk_tr_modify(phydev, ch_addr, node_addr, data_addr, 0, set); -+} -+EXPORT_SYMBOL_GPL(__mtk_tr_set_bits); -+ - int mtk_phy_read_page(struct phy_device *phydev) - { - return __phy_read(phydev, MTK_EXT_PAGE_ACCESS); ---- a/drivers/net/phy/mediatek/mtk.h -+++ b/drivers/net/phy/mediatek/mtk.h -@@ -72,6 +72,8 @@ void __mtk_tr_modify(struct phy_device * - u8 data_addr, u32 mask, u32 set); - void mtk_tr_modify(struct phy_device *phydev, u8 ch_addr, u8 node_addr, - u8 data_addr, u32 mask, u32 set); -+void __mtk_tr_set_bits(struct phy_device *phydev, u8 ch_addr, u8 node_addr, -+ u8 data_addr, u32 set); - - int mtk_phy_read_page(struct phy_device *phydev); - int mtk_phy_write_page(struct phy_device *phydev, int page); diff --git a/target/linux/generic/backport-6.18/720-13-v6.15-net-phy-mediatek-Add-token-ring-clear-bit-operation-.patch b/target/linux/generic/backport-6.18/720-13-v6.15-net-phy-mediatek-Add-token-ring-clear-bit-operation-.patch deleted file mode 100644 index 47d891ea69..0000000000 --- a/target/linux/generic/backport-6.18/720-13-v6.15-net-phy-mediatek-Add-token-ring-clear-bit-operation-.patch +++ /dev/null @@ -1,122 +0,0 @@ -From 7851c73a416b15aff6f9ada9c88affc5f48ff011 Mon Sep 17 00:00:00 2001 -From: Sky Huang -Date: Thu, 13 Feb 2025 16:05:52 +0800 -Subject: [PATCH 13/20] net: phy: mediatek: Add token ring clear bit operation - support - -Similar to __mtk_tr_set_bits() support. Previously in mtk-ge-soc.c, -we clear some register bits via token ring, which were also implemented -in three __phy_write(). Now we can do the same thing via -__mtk_tr_clr_bits() helper. - -Signed-off-by: Sky Huang -Reviewed-by: Andrew Lunn -Link: https://patch.msgid.link/20250213080553.921434-5-SkyLake.Huang@mediatek.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/mediatek/mtk-ge-soc.c | 30 +++++++++++++++----------- - drivers/net/phy/mediatek/mtk-phy-lib.c | 7 ++++++ - drivers/net/phy/mediatek/mtk.h | 2 ++ - 3 files changed, 27 insertions(+), 12 deletions(-) - ---- a/drivers/net/phy/mediatek/mtk-ge-soc.c -+++ b/drivers/net/phy/mediatek/mtk-ge-soc.c -@@ -76,6 +76,10 @@ - /* FfeUpdGainForce */ - #define FFE_UPDATE_GAIN_FORCE BIT(6) - -+/* ch_addr = 0x2, node_addr = 0xd, data_addr = 0x3 */ -+/* TrFreeze */ -+#define TR_FREEZE_MASK GENMASK(11, 0) -+ - /* ch_addr = 0x2, node_addr = 0xd, data_addr = 0x6 */ - /* SS: Steady-state, KP: Proportional Gain */ - /* SSTrKp100 */ -@@ -91,6 +95,11 @@ - /* SSTrKf1000Slv */ - #define SS_TR_KF1000_SLAVE_MASK GENMASK(6, 4) - -+/* ch_addr = 0x2, node_addr = 0xd, data_addr = 0x8 */ -+/* clear this bit if wanna select from AFE */ -+/* Regsigdet_sel_1000 */ -+#define EEE1000_SELECT_SIGNAL_DETECTION_FROM_DFE BIT(4) -+ - /* ch_addr = 0x2, node_addr = 0xd, data_addr = 0xd */ - /* RegEEE_st2TrKf1000 */ - #define EEE1000_STAGE2_TR_KF_MASK GENMASK(13, 11) -@@ -113,6 +122,10 @@ - /* RegEEE100Stg1_tar */ - #define EEE100_LPSYNC_STAGE1_UPDATE_TIMER_MASK GENMASK(8, 0) - -+/* ch_addr = 0x2, node_addr = 0xd, data_addr = 0x25 */ -+/* REGEEE_wake_slv_tr_wait_dfesigdet_en */ -+#define WAKE_SLAVE_TR_WAIT_DFE_DETECTION_EN BIT(11) -+ - #define ANALOG_INTERNAL_OPERATION_MAX_US 20 - #define TXRESERVE_MIN 0 - #define TXRESERVE_MAX 7 -@@ -805,10 +818,7 @@ static void mt798x_phy_common_finetune(s - FIELD_PREP(FFE_UPDATE_GAIN_FORCE_VAL_MASK, 0x4) | - FFE_UPDATE_GAIN_FORCE); - -- /* TrFreeze = 0 (mt7988 default) */ -- __phy_write(phydev, 0x11, 0x0); -- __phy_write(phydev, 0x12, 0x0); -- __phy_write(phydev, 0x10, 0x9686); -+ __mtk_tr_clr_bits(phydev, 0x2, 0xd, 0x3, TR_FREEZE_MASK); - - __mtk_tr_modify(phydev, 0x2, 0xd, 0x6, - SS_TR_KP100_MASK | SS_TR_KF100_MASK | -@@ -1009,10 +1019,8 @@ static void mt798x_phy_eee(struct phy_de - MTK_PHY_TR_READY_SKIP_AFE_WAKEUP); - - phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5); -- /* Regsigdet_sel_1000 = 0 */ -- __phy_write(phydev, 0x11, 0xb); -- __phy_write(phydev, 0x12, 0x0); -- __phy_write(phydev, 0x10, 0x9690); -+ __mtk_tr_clr_bits(phydev, 0x2, 0xd, 0x8, -+ EEE1000_SELECT_SIGNAL_DETECTION_FROM_DFE); - - __mtk_tr_modify(phydev, 0x2, 0xd, 0xd, - EEE1000_STAGE2_TR_KF_MASK, -@@ -1036,10 +1044,8 @@ static void mt798x_phy_eee(struct phy_de - FIELD_PREP(EEE100_LPSYNC_STAGE1_UPDATE_TIMER_MASK, - 0x10)); - -- /* REGEEE_wake_slv_tr_wait_dfesigdet_en = 0 */ -- __phy_write(phydev, 0x11, 0x1463); -- __phy_write(phydev, 0x12, 0x0); -- __phy_write(phydev, 0x10, 0x96ca); -+ __mtk_tr_clr_bits(phydev, 0x2, 0xd, 0x25, -+ WAKE_SLAVE_TR_WAIT_DFE_DETECTION_EN); - - __mtk_tr_modify(phydev, 0x1, 0xf, 0x0, - DFE_TAIL_EANBLE_VGA_TRHESH_1000, ---- a/drivers/net/phy/mediatek/mtk-phy-lib.c -+++ b/drivers/net/phy/mediatek/mtk-phy-lib.c -@@ -76,6 +76,13 @@ void __mtk_tr_set_bits(struct phy_device - } - EXPORT_SYMBOL_GPL(__mtk_tr_set_bits); - -+void __mtk_tr_clr_bits(struct phy_device *phydev, u8 ch_addr, u8 node_addr, -+ u8 data_addr, u32 clr) -+{ -+ __mtk_tr_modify(phydev, ch_addr, node_addr, data_addr, clr, 0); -+} -+EXPORT_SYMBOL_GPL(__mtk_tr_clr_bits); -+ - int mtk_phy_read_page(struct phy_device *phydev) - { - return __phy_read(phydev, MTK_EXT_PAGE_ACCESS); ---- a/drivers/net/phy/mediatek/mtk.h -+++ b/drivers/net/phy/mediatek/mtk.h -@@ -74,6 +74,8 @@ void mtk_tr_modify(struct phy_device *ph - u8 data_addr, u32 mask, u32 set); - void __mtk_tr_set_bits(struct phy_device *phydev, u8 ch_addr, u8 node_addr, - u8 data_addr, u32 set); -+void __mtk_tr_clr_bits(struct phy_device *phydev, u8 ch_addr, u8 node_addr, -+ u8 data_addr, u32 clr); - - int mtk_phy_read_page(struct phy_device *phydev); - int mtk_phy_write_page(struct phy_device *phydev, int page); diff --git a/target/linux/generic/backport-6.18/720-14-v6.15-net-phy-mediatek-Move-some-macros-to-phy-lib-for-lat.patch b/target/linux/generic/backport-6.18/720-14-v6.15-net-phy-mediatek-Move-some-macros-to-phy-lib-for-lat.patch deleted file mode 100644 index 858de093a2..0000000000 --- a/target/linux/generic/backport-6.18/720-14-v6.15-net-phy-mediatek-Move-some-macros-to-phy-lib-for-lat.patch +++ /dev/null @@ -1,45 +0,0 @@ -From bae8c61522c4d5a5250a24dcb57d120ea593fab1 Mon Sep 17 00:00:00 2001 -From: Sky Huang -Date: Thu, 13 Feb 2025 16:05:53 +0800 -Subject: [PATCH 14/20] net: phy: mediatek: Move some macros to phy-lib for - later use - -Move some macros to phy-lib because MediaTek's 2.5G built-in -ethernet PHY will also use them. - -Signed-off-by: Sky Huang -Reviewed-by: Andrew Lunn -Link: https://patch.msgid.link/20250213080553.921434-6-SkyLake.Huang@mediatek.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/mediatek/mtk-ge.c | 4 ---- - drivers/net/phy/mediatek/mtk.h | 4 ++++ - 2 files changed, 4 insertions(+), 4 deletions(-) - ---- a/drivers/net/phy/mediatek/mtk-ge.c -+++ b/drivers/net/phy/mediatek/mtk-ge.c -@@ -8,10 +8,6 @@ - #define MTK_GPHY_ID_MT7530 0x03a29412 - #define MTK_GPHY_ID_MT7531 0x03a29441 - --#define MTK_PHY_PAGE_EXTENDED_1 0x0001 --#define MTK_PHY_AUX_CTRL_AND_STATUS 0x14 --#define MTK_PHY_ENABLE_DOWNSHIFT BIT(4) -- - #define MTK_PHY_PAGE_EXTENDED_2 0x0002 - #define MTK_PHY_PAGE_EXTENDED_3 0x0003 - #define MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG11 0x11 ---- a/drivers/net/phy/mediatek/mtk.h -+++ b/drivers/net/phy/mediatek/mtk.h -@@ -8,7 +8,11 @@ - #ifndef _MTK_EPHY_H_ - #define _MTK_EPHY_H_ - -+#define MTK_PHY_AUX_CTRL_AND_STATUS 0x14 -+#define MTK_PHY_ENABLE_DOWNSHIFT BIT(4) -+ - #define MTK_EXT_PAGE_ACCESS 0x1f -+#define MTK_PHY_PAGE_EXTENDED_1 0x0001 - #define MTK_PHY_PAGE_STANDARD 0x0000 - #define MTK_PHY_PAGE_EXTENDED_52B5 0x52b5 - diff --git a/target/linux/generic/backport-6.18/720-15-v6.16-net-phy-mediatek-permit-to-compile-test-GE-SOC-PHY-d.patch b/target/linux/generic/backport-6.18/720-15-v6.16-net-phy-mediatek-permit-to-compile-test-GE-SOC-PHY-d.patch deleted file mode 100644 index 9778ea158b..0000000000 --- a/target/linux/generic/backport-6.18/720-15-v6.16-net-phy-mediatek-permit-to-compile-test-GE-SOC-PHY-d.patch +++ /dev/null @@ -1,37 +0,0 @@ -From e5566162af8b9690e096d2e6089e4ed955a0d13d Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Thu, 10 Apr 2025 12:04:03 +0200 -Subject: [PATCH] net: phy: mediatek: permit to compile test GE SOC PHY driver - -When commit 462a3daad679 ("net: phy: mediatek: fix compile-test -dependencies") fixed the dependency, it should have also introduced -an or on COMPILE_TEST to permit this driver to be compile-tested even if -NVMEM_MTK_EFUSE wasn't selected. The driver makes use of NVMEM API that -are always compiled (return error) so the driver can actually be -compiled even without that config. - -Fix and simplify the dependency condition of this kernel config. - -Fixes: 462a3daad679 ("net: phy: mediatek: fix compile-test dependencies") -Acked-by: Daniel Golle -Reviewed-by: Andrew Lunn -Signed-off-by: Christian Marangi -Acked-by: Arnd Bergmann -Link: https://patch.msgid.link/20250410100410.348-1-ansuelsmth@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/mediatek/Kconfig | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - ---- a/drivers/net/phy/mediatek/Kconfig -+++ b/drivers/net/phy/mediatek/Kconfig -@@ -15,8 +15,7 @@ config MEDIATEK_GE_PHY - - config MEDIATEK_GE_SOC_PHY - tristate "MediaTek SoC Ethernet PHYs" -- depends on (ARM64 && ARCH_MEDIATEK) || COMPILE_TEST -- depends on NVMEM_MTK_EFUSE -+ depends on (ARM64 && ARCH_MEDIATEK && NVMEM_MTK_EFUSE) || COMPILE_TEST - select MTK_NET_PHYLIB - help - Supports MediaTek SoC built-in Gigabit Ethernet PHYs. diff --git a/target/linux/generic/backport-6.18/720-16-v6.16-net-phy-mediatek-add-Airoha-PHY-ID-to-SoC-driver.patch b/target/linux/generic/backport-6.18/720-16-v6.16-net-phy-mediatek-add-Airoha-PHY-ID-to-SoC-driver.patch deleted file mode 100644 index 5498ecbd21..0000000000 --- a/target/linux/generic/backport-6.18/720-16-v6.16-net-phy-mediatek-add-Airoha-PHY-ID-to-SoC-driver.patch +++ /dev/null @@ -1,129 +0,0 @@ -From 4590c8bc10951feee3e439bf7fff1b458c2e6fad Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Thu, 10 Apr 2025 12:04:04 +0200 -Subject: [PATCH 17/20] net: phy: mediatek: add Airoha PHY ID to SoC driver - -Airoha AN7581 SoC ship with a Switch based on the MT753x Switch embedded -in other SoC like the MT7581 and the MT7988. Similar to these they -require configuring some pin to enable LED PHYs. - -Add support for the PHY ID for the Airoha embedded Switch and define a -simple probe function to toggle these pins. Also fill the LED functions -and add dedicated function to define LED polarity. - -Reviewed-by: Andrew Lunn -Signed-off-by: Christian Marangi -Link: https://patch.msgid.link/20250410100410.348-2-ansuelsmth@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/mediatek/Kconfig | 4 +- - drivers/net/phy/mediatek/mtk-ge-soc.c | 62 +++++++++++++++++++++++++++ - 2 files changed, 65 insertions(+), 1 deletion(-) - ---- a/drivers/net/phy/mediatek/Kconfig -+++ b/drivers/net/phy/mediatek/Kconfig -@@ -15,7 +15,9 @@ config MEDIATEK_GE_PHY - - config MEDIATEK_GE_SOC_PHY - tristate "MediaTek SoC Ethernet PHYs" -- depends on (ARM64 && ARCH_MEDIATEK && NVMEM_MTK_EFUSE) || COMPILE_TEST -+ depends on ARM64 || COMPILE_TEST -+ depends on ARCH_AIROHA || (ARCH_MEDIATEK && NVMEM_MTK_EFUSE) || \ -+ COMPILE_TEST - select MTK_NET_PHYLIB - help - Supports MediaTek SoC built-in Gigabit Ethernet PHYs. ---- a/drivers/net/phy/mediatek/mtk-ge-soc.c -+++ b/drivers/net/phy/mediatek/mtk-ge-soc.c -@@ -10,8 +10,11 @@ - - #include "mtk.h" - -+#define MTK_PHY_MAX_LEDS 2 -+ - #define MTK_GPHY_ID_MT7981 0x03a29461 - #define MTK_GPHY_ID_MT7988 0x03a29481 -+#define MTK_GPHY_ID_AN7581 0x03a294c1 - - #define MTK_EXT_PAGE_ACCESS 0x1f - #define MTK_PHY_PAGE_STANDARD 0x0000 -@@ -1405,6 +1408,53 @@ static int mt7981_phy_probe(struct phy_d - return mt798x_phy_calibration(phydev); - } - -+static int an7581_phy_probe(struct phy_device *phydev) -+{ -+ struct mtk_socphy_priv *priv; -+ struct pinctrl *pinctrl; -+ -+ /* Toggle pinctrl to enable PHY LED */ -+ pinctrl = devm_pinctrl_get_select(&phydev->mdio.dev, "gbe-led"); -+ if (IS_ERR(pinctrl)) -+ dev_err(&phydev->mdio.bus->dev, -+ "Failed to setup PHY LED pinctrl\n"); -+ -+ priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL); -+ if (!priv) -+ return -ENOMEM; -+ -+ phydev->priv = priv; -+ -+ return 0; -+} -+ -+static int an7581_phy_led_polarity_set(struct phy_device *phydev, int index, -+ unsigned long modes) -+{ -+ u32 mode; -+ u16 val; -+ -+ if (index >= MTK_PHY_MAX_LEDS) -+ return -EINVAL; -+ -+ for_each_set_bit(mode, &modes, __PHY_LED_MODES_NUM) { -+ switch (mode) { -+ case PHY_LED_ACTIVE_LOW: -+ val = MTK_PHY_LED_ON_POLARITY; -+ break; -+ case PHY_LED_ACTIVE_HIGH: -+ val = 0; -+ break; -+ default: -+ return -EINVAL; -+ } -+ } -+ -+ return phy_modify_mmd(phydev, MDIO_MMD_VEND2, index ? -+ MTK_PHY_LED1_ON_CTRL : MTK_PHY_LED0_ON_CTRL, -+ MTK_PHY_LED_ON_POLARITY, val); -+} -+ - static struct phy_driver mtk_socphy_driver[] = { - { - PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7981), -@@ -1440,6 +1490,17 @@ static struct phy_driver mtk_socphy_driv - .led_hw_control_set = mt798x_phy_led_hw_control_set, - .led_hw_control_get = mt798x_phy_led_hw_control_get, - }, -+ { -+ PHY_ID_MATCH_EXACT(MTK_GPHY_ID_AN7581), -+ .name = "Airoha AN7581 PHY", -+ .probe = an7581_phy_probe, -+ .led_blink_set = mt798x_phy_led_blink_set, -+ .led_brightness_set = mt798x_phy_led_brightness_set, -+ .led_hw_is_supported = mt798x_phy_led_hw_is_supported, -+ .led_hw_control_set = mt798x_phy_led_hw_control_set, -+ .led_hw_control_get = mt798x_phy_led_hw_control_get, -+ .led_polarity_set = an7581_phy_led_polarity_set, -+ }, - }; - - module_phy_driver(mtk_socphy_driver); -@@ -1447,6 +1508,7 @@ module_phy_driver(mtk_socphy_driver); - static const struct mdio_device_id __maybe_unused mtk_socphy_tbl[] = { - { PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7981) }, - { PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7988) }, -+ { PHY_ID_MATCH_EXACT(MTK_GPHY_ID_AN7581) }, - { } - }; - diff --git a/target/linux/generic/backport-6.18/720-17-v6.16-net-phy-mediatek-init-val-in-.phy_led_polarity_set-f.patch b/target/linux/generic/backport-6.18/720-17-v6.16-net-phy-mediatek-init-val-in-.phy_led_polarity_set-f.patch deleted file mode 100644 index 1b1dda2327..0000000000 --- a/target/linux/generic/backport-6.18/720-17-v6.16-net-phy-mediatek-init-val-in-.phy_led_polarity_set-f.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 34501d047ac0a6cbb13285ba9d15f75c1deb7da7 Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Tue, 15 Apr 2025 12:53:05 +0200 -Subject: [PATCH 18/20] net: phy: mediatek: init val in .phy_led_polarity_set - for AN7581 - -Fix smatch warning for uninitialised val in .phy_led_polarity_set for -AN7581 driver. - -Correctly init to 0 to set polarity high by default. - -Reported-by: Simon Horman -Fixes: 6a325aed130b ("net: phy: mediatek: add Airoha PHY ID to SoC driver") -Signed-off-by: Christian Marangi -Link: https://patch.msgid.link/20250415105313.3409-1-ansuelsmth@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/mediatek/mtk-ge-soc.c | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - ---- a/drivers/net/phy/mediatek/mtk-ge-soc.c -+++ b/drivers/net/phy/mediatek/mtk-ge-soc.c -@@ -1431,8 +1431,8 @@ static int an7581_phy_probe(struct phy_d - static int an7581_phy_led_polarity_set(struct phy_device *phydev, int index, - unsigned long modes) - { -+ u16 val = 0; - u32 mode; -- u16 val; - - if (index >= MTK_PHY_MAX_LEDS) - return -EINVAL; -@@ -1443,7 +1443,6 @@ static int an7581_phy_led_polarity_set(s - val = MTK_PHY_LED_ON_POLARITY; - break; - case PHY_LED_ACTIVE_HIGH: -- val = 0; - break; - default: - return -EINVAL; diff --git a/target/linux/generic/backport-6.18/721-01-v6.15-net-ethernet-mediatek-add-EEE-support.patch b/target/linux/generic/backport-6.18/721-01-v6.15-net-ethernet-mediatek-add-EEE-support.patch deleted file mode 100644 index 7a94897c02..0000000000 --- a/target/linux/generic/backport-6.18/721-01-v6.15-net-ethernet-mediatek-add-EEE-support.patch +++ /dev/null @@ -1,157 +0,0 @@ -From 952d7325362ffbefa6ce5619fb4e53c2159ec7a7 Mon Sep 17 00:00:00 2001 -From: Qingfang Deng -Date: Mon, 17 Feb 2025 17:40:21 +0800 -Subject: [PATCH] net: ethernet: mediatek: add EEE support - -Add EEE support to MediaTek SoC Ethernet. The register fields are -similar to the ones in MT7531, except that the LPI threshold is in -milliseconds. - -Signed-off-by: Qingfang Deng ---- - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 64 +++++++++++++++++++++ - drivers/net/ethernet/mediatek/mtk_eth_soc.h | 11 ++++ - 2 files changed, 75 insertions(+) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -782,6 +782,7 @@ static void mtk_mac_link_up(struct phyli - - mcr = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id)); - mcr &= ~(MAC_MCR_SPEED_100 | MAC_MCR_SPEED_1000 | -+ MAC_MCR_EEE100M | MAC_MCR_EEE1G | - MAC_MCR_FORCE_DPX | MAC_MCR_FORCE_TX_FC | - MAC_MCR_FORCE_RX_FC); - -@@ -807,6 +808,15 @@ static void mtk_mac_link_up(struct phyli - if (rx_pause) - mcr |= MAC_MCR_FORCE_RX_FC; - -+ if (mode == MLO_AN_PHY && phy && mac->tx_lpi_enabled && phy_init_eee(phy, false) >= 0) { -+ mcr |= MAC_MCR_EEE100M | MAC_MCR_EEE1G; -+ mtk_w32(mac->hw, -+ FIELD_PREP(MAC_EEE_WAKEUP_TIME_1000, 17) | -+ FIELD_PREP(MAC_EEE_WAKEUP_TIME_100, 36) | -+ FIELD_PREP(MAC_EEE_LPI_TXIDLE_THD, mac->txidle_thd_ms), -+ MTK_MAC_EEECR(mac->id)); -+ } -+ - mcr |= MAC_MCR_TX_EN | MAC_MCR_RX_EN | MAC_MCR_FORCE_LINK; - mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id)); - } -@@ -4523,6 +4533,61 @@ static int mtk_set_pauseparam(struct net - return phylink_ethtool_set_pauseparam(mac->phylink, pause); - } - -+static int mtk_get_eee(struct net_device *dev, struct ethtool_keee *eee) -+{ -+ struct mtk_mac *mac = netdev_priv(dev); -+ u32 reg; -+ int ret; -+ -+ ret = phylink_ethtool_get_eee(mac->phylink, eee); -+ if (ret) -+ return ret; -+ -+ reg = mtk_r32(mac->hw, MTK_MAC_EEECR(mac->id)); -+ eee->tx_lpi_enabled = mac->tx_lpi_enabled; -+ eee->tx_lpi_timer = FIELD_GET(MAC_EEE_LPI_TXIDLE_THD, reg) * 1000; -+ -+ return 0; -+} -+ -+static int mtk_set_eee(struct net_device *dev, struct ethtool_keee *eee) -+{ -+ struct mtk_mac *mac = netdev_priv(dev); -+ u32 txidle_thd_ms, reg; -+ int ret; -+ -+ /* Tx idle timer in ms */ -+ txidle_thd_ms = DIV_ROUND_UP(eee->tx_lpi_timer, 1000); -+ if (!FIELD_FIT(MAC_EEE_LPI_TXIDLE_THD, txidle_thd_ms)) -+ return -EINVAL; -+ -+ reg = FIELD_PREP(MAC_EEE_LPI_TXIDLE_THD, txidle_thd_ms); -+ -+ /* PHY Wake-up time, this field does not have a reset value, so use the -+ * reset value from MT7531 (36us for 100BaseT and 17us for 1000BaseT). -+ */ -+ reg |= FIELD_PREP(MAC_EEE_WAKEUP_TIME_1000, 17) | -+ FIELD_PREP(MAC_EEE_WAKEUP_TIME_100, 36); -+ -+ if (!txidle_thd_ms) -+ /* Force LPI Mode without a delay */ -+ reg |= MAC_EEE_LPI_MODE; -+ -+ ret = phylink_ethtool_set_eee(mac->phylink, eee); -+ if (ret) -+ return ret; -+ -+ mac->tx_lpi_enabled = eee->tx_lpi_enabled; -+ mac->txidle_thd_ms = txidle_thd_ms; -+ mtk_w32(mac->hw, reg, MTK_MAC_EEECR(mac->id)); -+ if (eee->eee_enabled && eee->eee_active && eee->tx_lpi_enabled) -+ mtk_m32(mac->hw, 0, MAC_MCR_EEE100M | MAC_MCR_EEE1G, MTK_MAC_MCR(mac->id)); -+ else -+ mtk_m32(mac->hw, MAC_MCR_EEE100M | MAC_MCR_EEE1G, 0, MTK_MAC_MCR(mac->id)); -+ -+ return 0; -+} -+ - static u16 mtk_select_queue(struct net_device *dev, struct sk_buff *skb, - struct net_device *sb_dev) - { -@@ -4555,6 +4620,8 @@ static const struct ethtool_ops mtk_etht - .set_pauseparam = mtk_set_pauseparam, - .get_rxnfc = mtk_get_rxnfc, - .set_rxnfc = mtk_set_rxnfc, -+ .get_eee = mtk_get_eee, -+ .set_eee = mtk_set_eee, - }; - - static const struct net_device_ops mtk_netdev_ops = { -@@ -4615,6 +4682,8 @@ static int mtk_add_mac(struct mtk_eth *e - } - mac = netdev_priv(eth->netdev[id]); - eth->mac[id] = mac; -+ mac->tx_lpi_enabled = true; -+ mac->txidle_thd_ms = 1; - mac->id = id; - mac->hw = eth; - mac->of_node = np; ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -461,6 +461,8 @@ - #define MAC_MCR_RX_FIFO_CLR_DIS BIT(12) - #define MAC_MCR_BACKOFF_EN BIT(9) - #define MAC_MCR_BACKPR_EN BIT(8) -+#define MAC_MCR_EEE1G BIT(7) -+#define MAC_MCR_EEE100M BIT(6) - #define MAC_MCR_FORCE_RX_FC BIT(5) - #define MAC_MCR_FORCE_TX_FC BIT(4) - #define MAC_MCR_SPEED_1000 BIT(3) -@@ -469,6 +471,15 @@ - #define MAC_MCR_FORCE_LINK BIT(0) - #define MAC_MCR_FORCE_LINK_DOWN (MAC_MCR_FORCE_MODE) - -+/* Mac EEE control registers */ -+#define MTK_MAC_EEECR(x) (0x10104 + (x * 0x100)) -+#define MAC_EEE_WAKEUP_TIME_1000 GENMASK(31, 24) -+#define MAC_EEE_WAKEUP_TIME_100 GENMASK(23, 16) -+#define MAC_EEE_LPI_TXIDLE_THD GENMASK(15, 8) -+#define MAC_EEE_CKG_TXIDLE BIT(3) -+#define MAC_EEE_CKG_RXLPI BIT(2) -+#define MAC_EEE_LPI_MODE BIT(0) -+ - /* Mac status registers */ - #define MTK_MAC_MSR(x) (0x10108 + (x * 0x100)) - #define MAC_MSR_EEE1G BIT(7) -@@ -1316,6 +1327,8 @@ struct mtk_mac { - int id; - phy_interface_t interface; - u8 ppe_idx; -+ bool tx_lpi_enabled; -+ u8 txidle_thd_ms; - int speed; - struct device_node *of_node; - struct phylink *phylink; diff --git a/target/linux/generic/backport-6.18/730-01-v6.13-net-phy-aquantia-allow-forcing-order-of-MDI-pairs.patch b/target/linux/generic/backport-6.18/730-01-v6.13-net-phy-aquantia-allow-forcing-order-of-MDI-pairs.patch deleted file mode 100644 index aabaa33e2c..0000000000 --- a/target/linux/generic/backport-6.18/730-01-v6.13-net-phy-aquantia-allow-forcing-order-of-MDI-pairs.patch +++ /dev/null @@ -1,107 +0,0 @@ -From a2e1ba275eae96a8171deb19e9c7c2f5978fee7b Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Fri, 4 Oct 2024 17:18:16 +0100 -Subject: [PATCH] net: phy: aquantia: allow forcing order of MDI pairs - -Despite supporting Auto MDI-X, it looks like Aquantia only supports -swapping pair (1,2) with pair (3,6) like it used to be for MDI-X on -100MBit/s networks. - -When all 4 pairs are in use (for 1000MBit/s or faster) the link does not -come up with pair order is not configured correctly, either using -MDI_CFG pin or using the "PMA Receive Reserved Vendor Provisioning 1" -register. - -Normally, the order of MDI pairs being either ABCD or DCBA is configured -by pulling the MDI_CFG pin. - -However, some hardware designs require overriding the value configured -by that bootstrap pin. The PHY allows doing that by setting a bit in -"PMA Receive Reserved Vendor Provisioning 1" register which allows -ignoring the state of the MDI_CFG pin and another bit configuring -whether the order of MDI pairs should be normal (ABCD) or reverse -(DCBA). Pair polarity is not affected and remains identical in both -settings. - -Introduce property "marvell,mdi-cfg-order" which allows forcing either -normal or reverse order of the MDI pairs from DT. - -If the property isn't present, the behavior is unchanged and MDI pair -order configuration is untouched (ie. either the result of MDI_CFG pin -pull-up/pull-down, or pair order override already configured by the -bootloader before Linux is started). - -Forcing normal pair order is required on the Adtran SDG-8733A Wi-Fi 7 -residential gateway. - -Signed-off-by: Daniel Golle -Reviewed-by: Andrew Lunn -Link: https://patch.msgid.link/9ed760ff87d5fc456f31e407ead548bbb754497d.1728058550.git.daniel@makrotopia.org -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/aquantia/aquantia_main.c | 33 ++++++++++++++++++++++++ - 1 file changed, 33 insertions(+) - ---- a/drivers/net/phy/aquantia/aquantia_main.c -+++ b/drivers/net/phy/aquantia/aquantia_main.c -@@ -11,6 +11,7 @@ - #include - #include - #include -+#include - #include - - #include "aquantia.h" -@@ -71,6 +72,11 @@ - #define MDIO_AN_TX_VEND_INT_MASK2 0xd401 - #define MDIO_AN_TX_VEND_INT_MASK2_LINK BIT(0) - -+#define PMAPMD_RSVD_VEND_PROV 0xe400 -+#define PMAPMD_RSVD_VEND_PROV_MDI_CONF GENMASK(1, 0) -+#define PMAPMD_RSVD_VEND_PROV_MDI_REVERSE BIT(0) -+#define PMAPMD_RSVD_VEND_PROV_MDI_FORCE BIT(1) -+ - #define MDIO_AN_RX_LP_STAT1 0xe820 - #define MDIO_AN_RX_LP_STAT1_1000BASET_FULL BIT(15) - #define MDIO_AN_RX_LP_STAT1_1000BASET_HALF BIT(14) -@@ -485,6 +491,29 @@ static void aqr107_chip_info(struct phy_ - fw_major, fw_minor, build_id, prov_id); - } - -+static int aqr107_config_mdi(struct phy_device *phydev) -+{ -+ struct device_node *np = phydev->mdio.dev.of_node; -+ u32 mdi_conf; -+ int ret; -+ -+ ret = of_property_read_u32(np, "marvell,mdi-cfg-order", &mdi_conf); -+ -+ /* Do nothing in case property "marvell,mdi-cfg-order" is not present */ -+ if (ret == -ENOENT) -+ return 0; -+ -+ if (ret) -+ return ret; -+ -+ if (mdi_conf & ~PMAPMD_RSVD_VEND_PROV_MDI_REVERSE) -+ return -EINVAL; -+ -+ return phy_modify_mmd(phydev, MDIO_MMD_PMAPMD, PMAPMD_RSVD_VEND_PROV, -+ PMAPMD_RSVD_VEND_PROV_MDI_CONF, -+ mdi_conf | PMAPMD_RSVD_VEND_PROV_MDI_FORCE); -+} -+ - static int aqr107_config_init(struct phy_device *phydev) - { - struct aqr107_priv *priv = phydev->priv; -@@ -514,6 +543,10 @@ static int aqr107_config_init(struct phy - if (ret) - return ret; - -+ ret = aqr107_config_mdi(phydev); -+ if (ret) -+ return ret; -+ - /* Restore LED polarity state after reset */ - for_each_set_bit(led_active_low, &priv->leds_active_low, AQR_MAX_LEDS) { - ret = aqr_phy_led_active_low_set(phydev, led_active_low, true); diff --git a/target/linux/generic/backport-6.18/730-02-v6.13-net-phy-aquantia-fix-return-value-check-in-aqr107_co.patch b/target/linux/generic/backport-6.18/730-02-v6.13-net-phy-aquantia-fix-return-value-check-in-aqr107_co.patch deleted file mode 100644 index 565edbd388..0000000000 --- a/target/linux/generic/backport-6.18/730-02-v6.13-net-phy-aquantia-fix-return-value-check-in-aqr107_co.patch +++ /dev/null @@ -1,31 +0,0 @@ -From ce21b8fb255ebf0b49913fb4c62741d7eb05c6f6 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Fri, 11 Oct 2024 22:28:43 +0100 -Subject: [PATCH] net: phy: aquantia: fix return value check in - aqr107_config_mdi() - -of_property_read_u32() returns -EINVAL in case the property cannot be -found rather than -ENOENT. Fix the check to not abort probing in case -of the property being missing, and also in case CONFIG_OF is not set -which will result in -ENOSYS. - -Fixes: a2e1ba275eae ("net: phy: aquantia: allow forcing order of MDI pairs") -Reported-by: Jon Hunter -Closes: https://lore.kernel.org/all/114b4c03-5d16-42ed-945d-cf78eabea12b@nvidia.com/ -Suggested-by: Hans-Frieder Vogt -Signed-off-by: Daniel Golle ---- - drivers/net/phy/aquantia/aquantia_main.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/net/phy/aquantia/aquantia_main.c -+++ b/drivers/net/phy/aquantia/aquantia_main.c -@@ -500,7 +500,7 @@ static int aqr107_config_mdi(struct phy_ - ret = of_property_read_u32(np, "marvell,mdi-cfg-order", &mdi_conf); - - /* Do nothing in case property "marvell,mdi-cfg-order" is not present */ -- if (ret == -ENOENT) -+ if (ret == -EINVAL || ret == -ENOSYS) - return 0; - - if (ret) diff --git a/target/linux/generic/backport-6.18/730-03-v6.13-net-phy-support-active-high-property-for-PHY-LEDs.patch b/target/linux/generic/backport-6.18/730-03-v6.13-net-phy-support-active-high-property-for-PHY-LEDs.patch deleted file mode 100644 index 6822dc0f22..0000000000 --- a/target/linux/generic/backport-6.18/730-03-v6.13-net-phy-support-active-high-property-for-PHY-LEDs.patch +++ /dev/null @@ -1,53 +0,0 @@ -From a274465cc3bef2dfd9c9ea5100848dda0a8641e1 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Thu, 10 Oct 2024 13:54:19 +0100 -Subject: [PATCH 1/4] net: phy: support 'active-high' property for PHY LEDs - -In addition to 'active-low' and 'inactive-high-impedance' also -support 'active-high' property for PHY LED pin configuration. -As only either 'active-high' or 'active-low' can be set at the -same time, WARN and return an error in case both are set. - -Signed-off-by: Daniel Golle -Reviewed-by: Andrew Lunn -Link: https://patch.msgid.link/91598487773d768f254d5faf06cf65b13e972f0e.1728558223.git.daniel@makrotopia.org -Signed-off-by: Paolo Abeni ---- - drivers/net/phy/phy_device.c | 6 ++++++ - include/linux/phy.h | 5 +++-- - 2 files changed, 9 insertions(+), 2 deletions(-) - ---- a/drivers/net/phy/phy_device.c -+++ b/drivers/net/phy/phy_device.c -@@ -3387,11 +3387,17 @@ static int of_phy_led(struct phy_device - if (index > U8_MAX) - return -EINVAL; - -+ if (of_property_read_bool(led, "active-high")) -+ set_bit(PHY_LED_ACTIVE_HIGH, &modes); - if (of_property_read_bool(led, "active-low")) - set_bit(PHY_LED_ACTIVE_LOW, &modes); - if (of_property_read_bool(led, "inactive-high-impedance")) - set_bit(PHY_LED_INACTIVE_HIGH_IMPEDANCE, &modes); - -+ if (WARN_ON(modes & BIT(PHY_LED_ACTIVE_LOW) && -+ modes & BIT(PHY_LED_ACTIVE_HIGH))) -+ return -EINVAL; -+ - if (modes) { - /* Return error if asked to set polarity modes but not supported */ - if (!phydev->drv->led_polarity_set) ---- a/include/linux/phy.h -+++ b/include/linux/phy.h -@@ -902,8 +902,9 @@ struct phy_plca_status { - - /* Modes for PHY LED configuration */ - enum phy_led_modes { -- PHY_LED_ACTIVE_LOW = 0, -- PHY_LED_INACTIVE_HIGH_IMPEDANCE = 1, -+ PHY_LED_ACTIVE_HIGH = 0, -+ PHY_LED_ACTIVE_LOW = 1, -+ PHY_LED_INACTIVE_HIGH_IMPEDANCE = 2, - - /* keep it last */ - __PHY_LED_MODES_NUM, diff --git a/target/linux/generic/backport-6.18/730-04-v6.13-net-phy-aquantia-correctly-describe-LED-polarity-ove.patch b/target/linux/generic/backport-6.18/730-04-v6.13-net-phy-aquantia-correctly-describe-LED-polarity-ove.patch deleted file mode 100644 index 155f796f8c..0000000000 --- a/target/linux/generic/backport-6.18/730-04-v6.13-net-phy-aquantia-correctly-describe-LED-polarity-ove.patch +++ /dev/null @@ -1,108 +0,0 @@ -From 9d55e68b19f222e6334ef4021c5527998f5ab537 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Thu, 10 Oct 2024 13:55:00 +0100 -Subject: [PATCH 2/4] net: phy: aquantia: correctly describe LED polarity - override - -Use newly defined 'active-high' property to set the -VEND1_GLOBAL_LED_DRIVE_VDD bit and let 'active-low' clear that bit. This -reflects the technical reality which was inverted in the previous -description in which the 'active-low' property was used to actually set -the VEND1_GLOBAL_LED_DRIVE_VDD bit, which means that VDD (ie. supply -voltage) of the LED is driven rather than GND. - -Signed-off-by: Daniel Golle -Reviewed-by: Andrew Lunn -Link: https://patch.msgid.link/86a413b4387c42dcb54f587cc2433a06f16aae83.1728558223.git.daniel@makrotopia.org -Signed-off-by: Paolo Abeni ---- - drivers/net/phy/aquantia/aquantia.h | 1 + - drivers/net/phy/aquantia/aquantia_leds.c | 19 ++++++++++++++----- - drivers/net/phy/aquantia/aquantia_main.c | 12 +++++++++--- - 3 files changed, 24 insertions(+), 8 deletions(-) - ---- a/drivers/net/phy/aquantia/aquantia.h -+++ b/drivers/net/phy/aquantia/aquantia.h -@@ -177,6 +177,7 @@ static const struct aqr107_hw_stat aqr10 - struct aqr107_priv { - u64 sgmii_stats[AQR107_SGMII_STAT_SZ]; - unsigned long leds_active_low; -+ unsigned long leds_active_high; - }; - - #if IS_REACHABLE(CONFIG_HWMON) ---- a/drivers/net/phy/aquantia/aquantia_leds.c -+++ b/drivers/net/phy/aquantia/aquantia_leds.c -@@ -121,13 +121,13 @@ int aqr_phy_led_active_low_set(struct ph - { - return phy_modify_mmd(phydev, MDIO_MMD_VEND1, AQR_LED_DRIVE(index), - VEND1_GLOBAL_LED_DRIVE_VDD, -- enable ? VEND1_GLOBAL_LED_DRIVE_VDD : 0); -+ enable ? 0 : VEND1_GLOBAL_LED_DRIVE_VDD); - } - - int aqr_phy_led_polarity_set(struct phy_device *phydev, int index, unsigned long modes) - { -+ bool force_active_low = false, force_active_high = false; - struct aqr107_priv *priv = phydev->priv; -- bool active_low = false; - u32 mode; - - if (index >= AQR_MAX_LEDS) -@@ -136,7 +136,10 @@ int aqr_phy_led_polarity_set(struct phy_ - for_each_set_bit(mode, &modes, __PHY_LED_MODES_NUM) { - switch (mode) { - case PHY_LED_ACTIVE_LOW: -- active_low = true; -+ force_active_low = true; -+ break; -+ case PHY_LED_ACTIVE_HIGH: -+ force_active_high = true; - break; - default: - return -EINVAL; -@@ -144,8 +147,14 @@ int aqr_phy_led_polarity_set(struct phy_ - } - - /* Save LED driver vdd state to restore on SW reset */ -- if (active_low) -+ if (force_active_low) - priv->leds_active_low |= BIT(index); - -- return aqr_phy_led_active_low_set(phydev, index, active_low); -+ if (force_active_high) -+ priv->leds_active_high |= BIT(index); -+ -+ if (force_active_high || force_active_low) -+ return aqr_phy_led_active_low_set(phydev, index, force_active_low); -+ -+ unreachable(); - } ---- a/drivers/net/phy/aquantia/aquantia_main.c -+++ b/drivers/net/phy/aquantia/aquantia_main.c -@@ -517,7 +517,7 @@ static int aqr107_config_mdi(struct phy_ - static int aqr107_config_init(struct phy_device *phydev) - { - struct aqr107_priv *priv = phydev->priv; -- u32 led_active_low; -+ u32 led_idx; - int ret; - - /* Check that the PHY interface type is compatible */ -@@ -548,8 +548,14 @@ static int aqr107_config_init(struct phy - return ret; - - /* Restore LED polarity state after reset */ -- for_each_set_bit(led_active_low, &priv->leds_active_low, AQR_MAX_LEDS) { -- ret = aqr_phy_led_active_low_set(phydev, led_active_low, true); -+ for_each_set_bit(led_idx, &priv->leds_active_low, AQR_MAX_LEDS) { -+ ret = aqr_phy_led_active_low_set(phydev, led_idx, true); -+ if (ret) -+ return ret; -+ } -+ -+ for_each_set_bit(led_idx, &priv->leds_active_high, AQR_MAX_LEDS) { -+ ret = aqr_phy_led_active_low_set(phydev, led_idx, false); - if (ret) - return ret; - } diff --git a/target/linux/generic/backport-6.18/730-05-v6.13-net-phy-mxl-gpy-add-basic-LED-support.patch b/target/linux/generic/backport-6.18/730-05-v6.13-net-phy-mxl-gpy-add-basic-LED-support.patch deleted file mode 100644 index c785f8a98a..0000000000 --- a/target/linux/generic/backport-6.18/730-05-v6.13-net-phy-mxl-gpy-add-basic-LED-support.patch +++ /dev/null @@ -1,332 +0,0 @@ -From 78997e9a5e4d8a4df561e083a92c91ae23010e07 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Tue, 1 Oct 2024 01:17:18 +0100 -Subject: [PATCH] net: phy: mxl-gpy: add basic LED support - -Add basic support for LEDs connected to MaxLinear GPY2xx and GPY115 PHYs. -The PHYs allow up to 4 LEDs to be connected. -Implement controlling LEDs in software as well as netdev trigger offloading -and LED polarity setup. - -The hardware claims to support 16 PWM brightness levels but there is no -documentation on how to use that feature, hence this is not supported. - -Signed-off-by: Daniel Golle -Reviewed-by: Andrew Lunn -Link: https://patch.msgid.link/b6ec9050339f8244ff898898a1cecc33b13a48fc.1727741563.git.daniel@makrotopia.org -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/mxl-gpy.c | 218 ++++++++++++++++++++++++++++++++++++++ - 1 file changed, 218 insertions(+) - ---- a/drivers/net/phy/mxl-gpy.c -+++ b/drivers/net/phy/mxl-gpy.c -@@ -38,6 +38,7 @@ - #define PHY_MIISTAT 0x18 /* MII state */ - #define PHY_IMASK 0x19 /* interrupt mask */ - #define PHY_ISTAT 0x1A /* interrupt status */ -+#define PHY_LED 0x1B /* LEDs */ - #define PHY_FWV 0x1E /* firmware version */ - - #define PHY_MIISTAT_SPD_MASK GENMASK(2, 0) -@@ -61,6 +62,11 @@ - PHY_IMASK_ADSC | \ - PHY_IMASK_ANC) - -+#define GPY_MAX_LEDS 4 -+#define PHY_LED_POLARITY(idx) BIT(12 + (idx)) -+#define PHY_LED_HWCONTROL(idx) BIT(8 + (idx)) -+#define PHY_LED_ON(idx) BIT(idx) -+ - #define PHY_FWV_REL_MASK BIT(15) - #define PHY_FWV_MAJOR_MASK GENMASK(11, 8) - #define PHY_FWV_MINOR_MASK GENMASK(7, 0) -@@ -72,6 +78,23 @@ - #define PHY_MDI_MDI_X_CD 0x1 - #define PHY_MDI_MDI_X_CROSS 0x0 - -+/* LED */ -+#define VSPEC1_LED(idx) (1 + (idx)) -+#define VSPEC1_LED_BLINKS GENMASK(15, 12) -+#define VSPEC1_LED_PULSE GENMASK(11, 8) -+#define VSPEC1_LED_CON GENMASK(7, 4) -+#define VSPEC1_LED_BLINKF GENMASK(3, 0) -+ -+#define VSPEC1_LED_LINK10 BIT(0) -+#define VSPEC1_LED_LINK100 BIT(1) -+#define VSPEC1_LED_LINK1000 BIT(2) -+#define VSPEC1_LED_LINK2500 BIT(3) -+ -+#define VSPEC1_LED_TXACT BIT(0) -+#define VSPEC1_LED_RXACT BIT(1) -+#define VSPEC1_LED_COL BIT(2) -+#define VSPEC1_LED_NO_CON BIT(3) -+ - /* SGMII */ - #define VSPEC1_SGMII_CTRL 0x08 - #define VSPEC1_SGMII_CTRL_ANEN BIT(12) /* Aneg enable */ -@@ -835,6 +858,156 @@ static int gpy115_loopback(struct phy_de - return genphy_soft_reset(phydev); - } - -+static int gpy_led_brightness_set(struct phy_device *phydev, -+ u8 index, enum led_brightness value) -+{ -+ int ret; -+ -+ if (index >= GPY_MAX_LEDS) -+ return -EINVAL; -+ -+ /* clear HWCONTROL and set manual LED state */ -+ ret = phy_modify(phydev, PHY_LED, -+ ((value == LED_OFF) ? PHY_LED_HWCONTROL(index) : 0) | -+ PHY_LED_ON(index), -+ (value == LED_OFF) ? 0 : PHY_LED_ON(index)); -+ if (ret) -+ return ret; -+ -+ /* ToDo: set PWM brightness */ -+ -+ /* clear HW LED setup */ -+ if (value == LED_OFF) -+ return phy_write_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_LED(index), 0); -+ else -+ return 0; -+} -+ -+static const unsigned long supported_triggers = (BIT(TRIGGER_NETDEV_LINK) | -+ BIT(TRIGGER_NETDEV_LINK_100) | -+ BIT(TRIGGER_NETDEV_LINK_1000) | -+ BIT(TRIGGER_NETDEV_LINK_2500) | -+ BIT(TRIGGER_NETDEV_RX) | -+ BIT(TRIGGER_NETDEV_TX)); -+ -+static int gpy_led_hw_is_supported(struct phy_device *phydev, u8 index, -+ unsigned long rules) -+{ -+ if (index >= GPY_MAX_LEDS) -+ return -EINVAL; -+ -+ /* All combinations of the supported triggers are allowed */ -+ if (rules & ~supported_triggers) -+ return -EOPNOTSUPP; -+ -+ return 0; -+} -+ -+static int gpy_led_hw_control_get(struct phy_device *phydev, u8 index, -+ unsigned long *rules) -+{ -+ int val; -+ -+ if (index >= GPY_MAX_LEDS) -+ return -EINVAL; -+ -+ val = phy_read_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_LED(index)); -+ if (val < 0) -+ return val; -+ -+ if (FIELD_GET(VSPEC1_LED_CON, val) & VSPEC1_LED_LINK10) -+ *rules |= BIT(TRIGGER_NETDEV_LINK_10); -+ -+ if (FIELD_GET(VSPEC1_LED_CON, val) & VSPEC1_LED_LINK100) -+ *rules |= BIT(TRIGGER_NETDEV_LINK_100); -+ -+ if (FIELD_GET(VSPEC1_LED_CON, val) & VSPEC1_LED_LINK1000) -+ *rules |= BIT(TRIGGER_NETDEV_LINK_1000); -+ -+ if (FIELD_GET(VSPEC1_LED_CON, val) & VSPEC1_LED_LINK2500) -+ *rules |= BIT(TRIGGER_NETDEV_LINK_2500); -+ -+ if (FIELD_GET(VSPEC1_LED_CON, val) == (VSPEC1_LED_LINK10 | -+ VSPEC1_LED_LINK100 | -+ VSPEC1_LED_LINK1000 | -+ VSPEC1_LED_LINK2500)) -+ *rules |= BIT(TRIGGER_NETDEV_LINK); -+ -+ if (FIELD_GET(VSPEC1_LED_PULSE, val) & VSPEC1_LED_TXACT) -+ *rules |= BIT(TRIGGER_NETDEV_TX); -+ -+ if (FIELD_GET(VSPEC1_LED_PULSE, val) & VSPEC1_LED_RXACT) -+ *rules |= BIT(TRIGGER_NETDEV_RX); -+ -+ return 0; -+} -+ -+static int gpy_led_hw_control_set(struct phy_device *phydev, u8 index, -+ unsigned long rules) -+{ -+ u16 val = 0; -+ int ret; -+ -+ if (index >= GPY_MAX_LEDS) -+ return -EINVAL; -+ -+ if (rules & BIT(TRIGGER_NETDEV_LINK) || -+ rules & BIT(TRIGGER_NETDEV_LINK_10)) -+ val |= FIELD_PREP(VSPEC1_LED_CON, VSPEC1_LED_LINK10); -+ -+ if (rules & BIT(TRIGGER_NETDEV_LINK) || -+ rules & BIT(TRIGGER_NETDEV_LINK_100)) -+ val |= FIELD_PREP(VSPEC1_LED_CON, VSPEC1_LED_LINK100); -+ -+ if (rules & BIT(TRIGGER_NETDEV_LINK) || -+ rules & BIT(TRIGGER_NETDEV_LINK_1000)) -+ val |= FIELD_PREP(VSPEC1_LED_CON, VSPEC1_LED_LINK1000); -+ -+ if (rules & BIT(TRIGGER_NETDEV_LINK) || -+ rules & BIT(TRIGGER_NETDEV_LINK_2500)) -+ val |= FIELD_PREP(VSPEC1_LED_CON, VSPEC1_LED_LINK2500); -+ -+ if (rules & BIT(TRIGGER_NETDEV_TX)) -+ val |= FIELD_PREP(VSPEC1_LED_PULSE, VSPEC1_LED_TXACT); -+ -+ if (rules & BIT(TRIGGER_NETDEV_RX)) -+ val |= FIELD_PREP(VSPEC1_LED_PULSE, VSPEC1_LED_RXACT); -+ -+ /* allow RX/TX pulse without link indication */ -+ if ((rules & BIT(TRIGGER_NETDEV_TX) || rules & BIT(TRIGGER_NETDEV_RX)) && -+ !(val & VSPEC1_LED_CON)) -+ val |= FIELD_PREP(VSPEC1_LED_PULSE, VSPEC1_LED_NO_CON) | VSPEC1_LED_CON; -+ -+ ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_LED(index), val); -+ if (ret) -+ return ret; -+ -+ return phy_set_bits(phydev, PHY_LED, PHY_LED_HWCONTROL(index)); -+} -+ -+static int gpy_led_polarity_set(struct phy_device *phydev, int index, -+ unsigned long modes) -+{ -+ bool active_low = false; -+ u32 mode; -+ -+ if (index >= GPY_MAX_LEDS) -+ return -EINVAL; -+ -+ for_each_set_bit(mode, &modes, __PHY_LED_MODES_NUM) { -+ switch (mode) { -+ case PHY_LED_ACTIVE_LOW: -+ active_low = true; -+ break; -+ default: -+ return -EINVAL; -+ } -+ } -+ -+ return phy_modify(phydev, PHY_LED, PHY_LED_POLARITY(index), -+ active_low ? 0 : PHY_LED_POLARITY(index)); -+} -+ - static struct phy_driver gpy_drivers[] = { - { - PHY_ID_MATCH_MODEL(PHY_ID_GPY2xx), -@@ -852,6 +1025,11 @@ static struct phy_driver gpy_drivers[] = - .set_wol = gpy_set_wol, - .get_wol = gpy_get_wol, - .set_loopback = gpy_loopback, -+ .led_brightness_set = gpy_led_brightness_set, -+ .led_hw_is_supported = gpy_led_hw_is_supported, -+ .led_hw_control_get = gpy_led_hw_control_get, -+ .led_hw_control_set = gpy_led_hw_control_set, -+ .led_polarity_set = gpy_led_polarity_set, - }, - { - .phy_id = PHY_ID_GPY115B, -@@ -870,6 +1048,11 @@ static struct phy_driver gpy_drivers[] = - .set_wol = gpy_set_wol, - .get_wol = gpy_get_wol, - .set_loopback = gpy115_loopback, -+ .led_brightness_set = gpy_led_brightness_set, -+ .led_hw_is_supported = gpy_led_hw_is_supported, -+ .led_hw_control_get = gpy_led_hw_control_get, -+ .led_hw_control_set = gpy_led_hw_control_set, -+ .led_polarity_set = gpy_led_polarity_set, - }, - { - PHY_ID_MATCH_MODEL(PHY_ID_GPY115C), -@@ -887,6 +1070,11 @@ static struct phy_driver gpy_drivers[] = - .set_wol = gpy_set_wol, - .get_wol = gpy_get_wol, - .set_loopback = gpy115_loopback, -+ .led_brightness_set = gpy_led_brightness_set, -+ .led_hw_is_supported = gpy_led_hw_is_supported, -+ .led_hw_control_get = gpy_led_hw_control_get, -+ .led_hw_control_set = gpy_led_hw_control_set, -+ .led_polarity_set = gpy_led_polarity_set, - }, - { - .phy_id = PHY_ID_GPY211B, -@@ -905,6 +1093,11 @@ static struct phy_driver gpy_drivers[] = - .set_wol = gpy_set_wol, - .get_wol = gpy_get_wol, - .set_loopback = gpy_loopback, -+ .led_brightness_set = gpy_led_brightness_set, -+ .led_hw_is_supported = gpy_led_hw_is_supported, -+ .led_hw_control_get = gpy_led_hw_control_get, -+ .led_hw_control_set = gpy_led_hw_control_set, -+ .led_polarity_set = gpy_led_polarity_set, - }, - { - PHY_ID_MATCH_MODEL(PHY_ID_GPY211C), -@@ -922,6 +1115,11 @@ static struct phy_driver gpy_drivers[] = - .set_wol = gpy_set_wol, - .get_wol = gpy_get_wol, - .set_loopback = gpy_loopback, -+ .led_brightness_set = gpy_led_brightness_set, -+ .led_hw_is_supported = gpy_led_hw_is_supported, -+ .led_hw_control_get = gpy_led_hw_control_get, -+ .led_hw_control_set = gpy_led_hw_control_set, -+ .led_polarity_set = gpy_led_polarity_set, - }, - { - .phy_id = PHY_ID_GPY212B, -@@ -940,6 +1138,11 @@ static struct phy_driver gpy_drivers[] = - .set_wol = gpy_set_wol, - .get_wol = gpy_get_wol, - .set_loopback = gpy_loopback, -+ .led_brightness_set = gpy_led_brightness_set, -+ .led_hw_is_supported = gpy_led_hw_is_supported, -+ .led_hw_control_get = gpy_led_hw_control_get, -+ .led_hw_control_set = gpy_led_hw_control_set, -+ .led_polarity_set = gpy_led_polarity_set, - }, - { - PHY_ID_MATCH_MODEL(PHY_ID_GPY212C), -@@ -957,6 +1160,11 @@ static struct phy_driver gpy_drivers[] = - .set_wol = gpy_set_wol, - .get_wol = gpy_get_wol, - .set_loopback = gpy_loopback, -+ .led_brightness_set = gpy_led_brightness_set, -+ .led_hw_is_supported = gpy_led_hw_is_supported, -+ .led_hw_control_get = gpy_led_hw_control_get, -+ .led_hw_control_set = gpy_led_hw_control_set, -+ .led_polarity_set = gpy_led_polarity_set, - }, - { - .phy_id = PHY_ID_GPY215B, -@@ -975,6 +1183,11 @@ static struct phy_driver gpy_drivers[] = - .set_wol = gpy_set_wol, - .get_wol = gpy_get_wol, - .set_loopback = gpy_loopback, -+ .led_brightness_set = gpy_led_brightness_set, -+ .led_hw_is_supported = gpy_led_hw_is_supported, -+ .led_hw_control_get = gpy_led_hw_control_get, -+ .led_hw_control_set = gpy_led_hw_control_set, -+ .led_polarity_set = gpy_led_polarity_set, - }, - { - PHY_ID_MATCH_MODEL(PHY_ID_GPY215C), -@@ -992,6 +1205,11 @@ static struct phy_driver gpy_drivers[] = - .set_wol = gpy_set_wol, - .get_wol = gpy_get_wol, - .set_loopback = gpy_loopback, -+ .led_brightness_set = gpy_led_brightness_set, -+ .led_hw_is_supported = gpy_led_hw_is_supported, -+ .led_hw_control_get = gpy_led_hw_control_get, -+ .led_hw_control_set = gpy_led_hw_control_set, -+ .led_polarity_set = gpy_led_polarity_set, - }, - { - PHY_ID_MATCH_MODEL(PHY_ID_GPY241B), diff --git a/target/linux/generic/backport-6.18/730-06-v6.13-net-phy-mxl-gpy-add-missing-support-for-TRIGGER_NETD.patch b/target/linux/generic/backport-6.18/730-06-v6.13-net-phy-mxl-gpy-add-missing-support-for-TRIGGER_NETD.patch deleted file mode 100644 index 39bef9b982..0000000000 --- a/target/linux/generic/backport-6.18/730-06-v6.13-net-phy-mxl-gpy-add-missing-support-for-TRIGGER_NETD.patch +++ /dev/null @@ -1,28 +0,0 @@ -From f95b4725e796b12e5f347a0d161e1d3843142aa8 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Fri, 4 Oct 2024 16:56:35 +0100 -Subject: [PATCH] net: phy: mxl-gpy: add missing support for - TRIGGER_NETDEV_LINK_10 - -The PHY also support 10MBit/s links as well as the corresponding link -indication trigger to be offloaded. Add TRIGGER_NETDEV_LINK_10 to the -supported triggers. - -Signed-off-by: Daniel Golle -Reviewed-by: Andrew Lunn -Link: https://patch.msgid.link/cc5da0a989af8b0d49d823656d88053c4de2ab98.1728057367.git.daniel@makrotopia.org -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/mxl-gpy.c | 1 + - 1 file changed, 1 insertion(+) - ---- a/drivers/net/phy/mxl-gpy.c -+++ b/drivers/net/phy/mxl-gpy.c -@@ -884,6 +884,7 @@ static int gpy_led_brightness_set(struct - } - - static const unsigned long supported_triggers = (BIT(TRIGGER_NETDEV_LINK) | -+ BIT(TRIGGER_NETDEV_LINK_10) | - BIT(TRIGGER_NETDEV_LINK_100) | - BIT(TRIGGER_NETDEV_LINK_1000) | - BIT(TRIGGER_NETDEV_LINK_2500) | diff --git a/target/linux/generic/backport-6.18/730-07-v6.13-net-phy-mxl-gpy-correctly-describe-LED-polarity.patch b/target/linux/generic/backport-6.18/730-07-v6.13-net-phy-mxl-gpy-correctly-describe-LED-polarity.patch deleted file mode 100644 index 5fd3dcc77b..0000000000 --- a/target/linux/generic/backport-6.18/730-07-v6.13-net-phy-mxl-gpy-correctly-describe-LED-polarity.patch +++ /dev/null @@ -1,58 +0,0 @@ -From eb89c79c1b8f17fc1611540768678e60df89ac42 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Thu, 10 Oct 2024 13:55:17 +0100 -Subject: [PATCH 3/4] net: phy: mxl-gpy: correctly describe LED polarity - -According the datasheet covering the LED (0x1b) register: -0B Active High LEDx pin driven high when activated -1B Active Low LEDx pin driven low when activated - -Make use of the now available 'active-high' property and correctly -reflect the polarity setting which was previously inverted. - -Signed-off-by: Daniel Golle -Reviewed-by: Andrew Lunn -Link: https://patch.msgid.link/180ccafa837f09908b852a8a874a3808c5ecd2d0.1728558223.git.daniel@makrotopia.org -Signed-off-by: Paolo Abeni ---- - drivers/net/phy/mxl-gpy.c | 16 ++++++++++++---- - 1 file changed, 12 insertions(+), 4 deletions(-) - ---- a/drivers/net/phy/mxl-gpy.c -+++ b/drivers/net/phy/mxl-gpy.c -@@ -989,7 +989,7 @@ static int gpy_led_hw_control_set(struct - static int gpy_led_polarity_set(struct phy_device *phydev, int index, - unsigned long modes) - { -- bool active_low = false; -+ bool force_active_low = false, force_active_high = false; - u32 mode; - - if (index >= GPY_MAX_LEDS) -@@ -998,15 +998,23 @@ static int gpy_led_polarity_set(struct p - for_each_set_bit(mode, &modes, __PHY_LED_MODES_NUM) { - switch (mode) { - case PHY_LED_ACTIVE_LOW: -- active_low = true; -+ force_active_low = true; -+ break; -+ case PHY_LED_ACTIVE_HIGH: -+ force_active_high = true; - break; - default: - return -EINVAL; - } - } - -- return phy_modify(phydev, PHY_LED, PHY_LED_POLARITY(index), -- active_low ? 0 : PHY_LED_POLARITY(index)); -+ if (force_active_low) -+ return phy_set_bits(phydev, PHY_LED, PHY_LED_POLARITY(index)); -+ -+ if (force_active_high) -+ return phy_clear_bits(phydev, PHY_LED, PHY_LED_POLARITY(index)); -+ -+ unreachable(); - } - - static struct phy_driver gpy_drivers[] = { diff --git a/target/linux/generic/backport-6.18/730-08-v6.13-net-phy-intel-xway-add-support-for-PHY-LEDs.patch b/target/linux/generic/backport-6.18/730-08-v6.13-net-phy-intel-xway-add-support-for-PHY-LEDs.patch deleted file mode 100644 index c57b5777ad..0000000000 --- a/target/linux/generic/backport-6.18/730-08-v6.13-net-phy-intel-xway-add-support-for-PHY-LEDs.patch +++ /dev/null @@ -1,379 +0,0 @@ -From 1758af47b98c17da464cb45f476875150955dd48 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Thu, 10 Oct 2024 13:55:29 +0100 -Subject: [PATCH 4/4] net: phy: intel-xway: add support for PHY LEDs - -The intel-xway PHY driver predates the PHY LED framework and currently -initializes all LED pins to equal default values. - -Add PHY LED functions to the drivers and don't set default values if -LEDs are defined in device tree. - -According the datasheets 3 LEDs are supported on all Intel XWAY PHYs. - -Signed-off-by: Daniel Golle -Reviewed-by: Andrew Lunn -Link: https://patch.msgid.link/81f4717ab9acf38f3239727a4540ae96fd01109b.1728558223.git.daniel@makrotopia.org -Signed-off-by: Paolo Abeni ---- - drivers/net/phy/intel-xway.c | 253 +++++++++++++++++++++++++++++++++-- - 1 file changed, 244 insertions(+), 9 deletions(-) - ---- a/drivers/net/phy/intel-xway.c -+++ b/drivers/net/phy/intel-xway.c -@@ -151,6 +151,13 @@ - #define XWAY_MMD_LED3H 0x01E8 - #define XWAY_MMD_LED3L 0x01E9 - -+#define XWAY_GPHY_MAX_LEDS 3 -+#define XWAY_GPHY_LED_INV(idx) BIT(12 + (idx)) -+#define XWAY_GPHY_LED_EN(idx) BIT(8 + (idx)) -+#define XWAY_GPHY_LED_DA(idx) BIT(idx) -+#define XWAY_MMD_LEDxH(idx) (XWAY_MMD_LED0H + 2 * (idx)) -+#define XWAY_MMD_LEDxL(idx) (XWAY_MMD_LED0L + 2 * (idx)) -+ - #define PHY_ID_PHY11G_1_3 0x030260D1 - #define PHY_ID_PHY22F_1_3 0x030260E1 - #define PHY_ID_PHY11G_1_4 0xD565A400 -@@ -229,20 +236,12 @@ static int xway_gphy_rgmii_init(struct p - XWAY_MDIO_MIICTRL_TXSKEW_MASK, val); - } - --static int xway_gphy_config_init(struct phy_device *phydev) -+static int xway_gphy_init_leds(struct phy_device *phydev) - { - int err; - u32 ledxh; - u32 ledxl; - -- /* Mask all interrupts */ -- err = phy_write(phydev, XWAY_MDIO_IMASK, 0); -- if (err) -- return err; -- -- /* Clear all pending interrupts */ -- phy_read(phydev, XWAY_MDIO_ISTAT); -- - /* Ensure that integrated led function is enabled for all leds */ - err = phy_write(phydev, XWAY_MDIO_LED, - XWAY_MDIO_LED_LED0_EN | -@@ -276,6 +275,26 @@ static int xway_gphy_config_init(struct - phy_write_mmd(phydev, MDIO_MMD_VEND2, XWAY_MMD_LED2H, ledxh); - phy_write_mmd(phydev, MDIO_MMD_VEND2, XWAY_MMD_LED2L, ledxl); - -+ return 0; -+} -+ -+static int xway_gphy_config_init(struct phy_device *phydev) -+{ -+ struct device_node *np = phydev->mdio.dev.of_node; -+ int err; -+ -+ /* Mask all interrupts */ -+ err = phy_write(phydev, XWAY_MDIO_IMASK, 0); -+ if (err) -+ return err; -+ -+ /* Use default LED configuration if 'leds' node isn't defined */ -+ if (!of_get_child_by_name(np, "leds")) -+ xway_gphy_init_leds(phydev); -+ -+ /* Clear all pending interrupts */ -+ phy_read(phydev, XWAY_MDIO_ISTAT); -+ - err = xway_gphy_rgmii_init(phydev); - if (err) - return err; -@@ -347,6 +366,172 @@ static irqreturn_t xway_gphy_handle_inte - return IRQ_HANDLED; - } - -+static int xway_gphy_led_brightness_set(struct phy_device *phydev, -+ u8 index, enum led_brightness value) -+{ -+ int ret; -+ -+ if (index >= XWAY_GPHY_MAX_LEDS) -+ return -EINVAL; -+ -+ /* clear EN and set manual LED state */ -+ ret = phy_modify(phydev, XWAY_MDIO_LED, -+ ((value == LED_OFF) ? XWAY_GPHY_LED_EN(index) : 0) | -+ XWAY_GPHY_LED_DA(index), -+ (value == LED_OFF) ? 0 : XWAY_GPHY_LED_DA(index)); -+ if (ret) -+ return ret; -+ -+ /* clear HW LED setup */ -+ if (value == LED_OFF) { -+ ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, XWAY_MMD_LEDxH(index), 0); -+ if (ret) -+ return ret; -+ -+ return phy_write_mmd(phydev, MDIO_MMD_VEND2, XWAY_MMD_LEDxL(index), 0); -+ } else { -+ return 0; -+ } -+} -+ -+static const unsigned long supported_triggers = (BIT(TRIGGER_NETDEV_LINK) | -+ BIT(TRIGGER_NETDEV_LINK_10) | -+ BIT(TRIGGER_NETDEV_LINK_100) | -+ BIT(TRIGGER_NETDEV_LINK_1000) | -+ BIT(TRIGGER_NETDEV_RX) | -+ BIT(TRIGGER_NETDEV_TX)); -+ -+static int xway_gphy_led_hw_is_supported(struct phy_device *phydev, u8 index, -+ unsigned long rules) -+{ -+ if (index >= XWAY_GPHY_MAX_LEDS) -+ return -EINVAL; -+ -+ /* activity triggers are not possible without combination with a link -+ * trigger. -+ */ -+ if (rules & (BIT(TRIGGER_NETDEV_RX) | BIT(TRIGGER_NETDEV_TX)) && -+ !(rules & (BIT(TRIGGER_NETDEV_LINK) | -+ BIT(TRIGGER_NETDEV_LINK_10) | -+ BIT(TRIGGER_NETDEV_LINK_100) | -+ BIT(TRIGGER_NETDEV_LINK_1000)))) -+ return -EOPNOTSUPP; -+ -+ /* All other combinations of the supported triggers are allowed */ -+ if (rules & ~supported_triggers) -+ return -EOPNOTSUPP; -+ -+ return 0; -+} -+ -+static int xway_gphy_led_hw_control_get(struct phy_device *phydev, u8 index, -+ unsigned long *rules) -+{ -+ int lval, hval; -+ -+ if (index >= XWAY_GPHY_MAX_LEDS) -+ return -EINVAL; -+ -+ hval = phy_read_mmd(phydev, MDIO_MMD_VEND2, XWAY_MMD_LEDxH(index)); -+ if (hval < 0) -+ return hval; -+ -+ lval = phy_read_mmd(phydev, MDIO_MMD_VEND2, XWAY_MMD_LEDxL(index)); -+ if (lval < 0) -+ return lval; -+ -+ if (hval & XWAY_MMD_LEDxH_CON_LINK10) -+ *rules |= BIT(TRIGGER_NETDEV_LINK_10); -+ -+ if (hval & XWAY_MMD_LEDxH_CON_LINK100) -+ *rules |= BIT(TRIGGER_NETDEV_LINK_100); -+ -+ if (hval & XWAY_MMD_LEDxH_CON_LINK1000) -+ *rules |= BIT(TRIGGER_NETDEV_LINK_1000); -+ -+ if ((hval & XWAY_MMD_LEDxH_CON_LINK10) && -+ (hval & XWAY_MMD_LEDxH_CON_LINK100) && -+ (hval & XWAY_MMD_LEDxH_CON_LINK1000)) -+ *rules |= BIT(TRIGGER_NETDEV_LINK); -+ -+ if (lval & XWAY_MMD_LEDxL_PULSE_TXACT) -+ *rules |= BIT(TRIGGER_NETDEV_TX); -+ -+ if (lval & XWAY_MMD_LEDxL_PULSE_RXACT) -+ *rules |= BIT(TRIGGER_NETDEV_RX); -+ -+ return 0; -+} -+ -+static int xway_gphy_led_hw_control_set(struct phy_device *phydev, u8 index, -+ unsigned long rules) -+{ -+ u16 hval = 0, lval = 0; -+ int ret; -+ -+ if (index >= XWAY_GPHY_MAX_LEDS) -+ return -EINVAL; -+ -+ if (rules & BIT(TRIGGER_NETDEV_LINK) || -+ rules & BIT(TRIGGER_NETDEV_LINK_10)) -+ hval |= XWAY_MMD_LEDxH_CON_LINK10; -+ -+ if (rules & BIT(TRIGGER_NETDEV_LINK) || -+ rules & BIT(TRIGGER_NETDEV_LINK_100)) -+ hval |= XWAY_MMD_LEDxH_CON_LINK100; -+ -+ if (rules & BIT(TRIGGER_NETDEV_LINK) || -+ rules & BIT(TRIGGER_NETDEV_LINK_1000)) -+ hval |= XWAY_MMD_LEDxH_CON_LINK1000; -+ -+ if (rules & BIT(TRIGGER_NETDEV_TX)) -+ lval |= XWAY_MMD_LEDxL_PULSE_TXACT; -+ -+ if (rules & BIT(TRIGGER_NETDEV_RX)) -+ lval |= XWAY_MMD_LEDxL_PULSE_RXACT; -+ -+ ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, XWAY_MMD_LEDxH(index), hval); -+ if (ret) -+ return ret; -+ -+ ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, XWAY_MMD_LEDxL(index), lval); -+ if (ret) -+ return ret; -+ -+ return phy_set_bits(phydev, XWAY_MDIO_LED, XWAY_GPHY_LED_EN(index)); -+} -+ -+static int xway_gphy_led_polarity_set(struct phy_device *phydev, int index, -+ unsigned long modes) -+{ -+ bool force_active_low = false, force_active_high = false; -+ u32 mode; -+ -+ if (index >= XWAY_GPHY_MAX_LEDS) -+ return -EINVAL; -+ -+ for_each_set_bit(mode, &modes, __PHY_LED_MODES_NUM) { -+ switch (mode) { -+ case PHY_LED_ACTIVE_LOW: -+ force_active_low = true; -+ break; -+ case PHY_LED_ACTIVE_HIGH: -+ force_active_high = true; -+ break; -+ default: -+ return -EINVAL; -+ } -+ } -+ -+ if (force_active_low) -+ return phy_set_bits(phydev, XWAY_MDIO_LED, XWAY_GPHY_LED_INV(index)); -+ -+ if (force_active_high) -+ return phy_clear_bits(phydev, XWAY_MDIO_LED, XWAY_GPHY_LED_INV(index)); -+ -+ unreachable(); -+} -+ - static struct phy_driver xway_gphy[] = { - { - .phy_id = PHY_ID_PHY11G_1_3, -@@ -359,6 +544,11 @@ static struct phy_driver xway_gphy[] = { - .config_intr = xway_gphy_config_intr, - .suspend = genphy_suspend, - .resume = genphy_resume, -+ .led_brightness_set = xway_gphy_led_brightness_set, -+ .led_hw_is_supported = xway_gphy_led_hw_is_supported, -+ .led_hw_control_get = xway_gphy_led_hw_control_get, -+ .led_hw_control_set = xway_gphy_led_hw_control_set, -+ .led_polarity_set = xway_gphy_led_polarity_set, - }, { - .phy_id = PHY_ID_PHY22F_1_3, - .phy_id_mask = 0xffffffff, -@@ -370,6 +560,11 @@ static struct phy_driver xway_gphy[] = { - .config_intr = xway_gphy_config_intr, - .suspend = genphy_suspend, - .resume = genphy_resume, -+ .led_brightness_set = xway_gphy_led_brightness_set, -+ .led_hw_is_supported = xway_gphy_led_hw_is_supported, -+ .led_hw_control_get = xway_gphy_led_hw_control_get, -+ .led_hw_control_set = xway_gphy_led_hw_control_set, -+ .led_polarity_set = xway_gphy_led_polarity_set, - }, { - .phy_id = PHY_ID_PHY11G_1_4, - .phy_id_mask = 0xffffffff, -@@ -381,6 +576,11 @@ static struct phy_driver xway_gphy[] = { - .config_intr = xway_gphy_config_intr, - .suspend = genphy_suspend, - .resume = genphy_resume, -+ .led_brightness_set = xway_gphy_led_brightness_set, -+ .led_hw_is_supported = xway_gphy_led_hw_is_supported, -+ .led_hw_control_get = xway_gphy_led_hw_control_get, -+ .led_hw_control_set = xway_gphy_led_hw_control_set, -+ .led_polarity_set = xway_gphy_led_polarity_set, - }, { - .phy_id = PHY_ID_PHY22F_1_4, - .phy_id_mask = 0xffffffff, -@@ -392,6 +592,11 @@ static struct phy_driver xway_gphy[] = { - .config_intr = xway_gphy_config_intr, - .suspend = genphy_suspend, - .resume = genphy_resume, -+ .led_brightness_set = xway_gphy_led_brightness_set, -+ .led_hw_is_supported = xway_gphy_led_hw_is_supported, -+ .led_hw_control_get = xway_gphy_led_hw_control_get, -+ .led_hw_control_set = xway_gphy_led_hw_control_set, -+ .led_polarity_set = xway_gphy_led_polarity_set, - }, { - .phy_id = PHY_ID_PHY11G_1_5, - .phy_id_mask = 0xffffffff, -@@ -402,6 +607,11 @@ static struct phy_driver xway_gphy[] = { - .config_intr = xway_gphy_config_intr, - .suspend = genphy_suspend, - .resume = genphy_resume, -+ .led_brightness_set = xway_gphy_led_brightness_set, -+ .led_hw_is_supported = xway_gphy_led_hw_is_supported, -+ .led_hw_control_get = xway_gphy_led_hw_control_get, -+ .led_hw_control_set = xway_gphy_led_hw_control_set, -+ .led_polarity_set = xway_gphy_led_polarity_set, - }, { - .phy_id = PHY_ID_PHY22F_1_5, - .phy_id_mask = 0xffffffff, -@@ -412,6 +622,11 @@ static struct phy_driver xway_gphy[] = { - .config_intr = xway_gphy_config_intr, - .suspend = genphy_suspend, - .resume = genphy_resume, -+ .led_brightness_set = xway_gphy_led_brightness_set, -+ .led_hw_is_supported = xway_gphy_led_hw_is_supported, -+ .led_hw_control_get = xway_gphy_led_hw_control_get, -+ .led_hw_control_set = xway_gphy_led_hw_control_set, -+ .led_polarity_set = xway_gphy_led_polarity_set, - }, { - .phy_id = PHY_ID_PHY11G_VR9_1_1, - .phy_id_mask = 0xffffffff, -@@ -422,6 +637,11 @@ static struct phy_driver xway_gphy[] = { - .config_intr = xway_gphy_config_intr, - .suspend = genphy_suspend, - .resume = genphy_resume, -+ .led_brightness_set = xway_gphy_led_brightness_set, -+ .led_hw_is_supported = xway_gphy_led_hw_is_supported, -+ .led_hw_control_get = xway_gphy_led_hw_control_get, -+ .led_hw_control_set = xway_gphy_led_hw_control_set, -+ .led_polarity_set = xway_gphy_led_polarity_set, - }, { - .phy_id = PHY_ID_PHY22F_VR9_1_1, - .phy_id_mask = 0xffffffff, -@@ -432,6 +652,11 @@ static struct phy_driver xway_gphy[] = { - .config_intr = xway_gphy_config_intr, - .suspend = genphy_suspend, - .resume = genphy_resume, -+ .led_brightness_set = xway_gphy_led_brightness_set, -+ .led_hw_is_supported = xway_gphy_led_hw_is_supported, -+ .led_hw_control_get = xway_gphy_led_hw_control_get, -+ .led_hw_control_set = xway_gphy_led_hw_control_set, -+ .led_polarity_set = xway_gphy_led_polarity_set, - }, { - .phy_id = PHY_ID_PHY11G_VR9_1_2, - .phy_id_mask = 0xffffffff, -@@ -442,6 +667,11 @@ static struct phy_driver xway_gphy[] = { - .config_intr = xway_gphy_config_intr, - .suspend = genphy_suspend, - .resume = genphy_resume, -+ .led_brightness_set = xway_gphy_led_brightness_set, -+ .led_hw_is_supported = xway_gphy_led_hw_is_supported, -+ .led_hw_control_get = xway_gphy_led_hw_control_get, -+ .led_hw_control_set = xway_gphy_led_hw_control_set, -+ .led_polarity_set = xway_gphy_led_polarity_set, - }, { - .phy_id = PHY_ID_PHY22F_VR9_1_2, - .phy_id_mask = 0xffffffff, -@@ -452,6 +682,11 @@ static struct phy_driver xway_gphy[] = { - .config_intr = xway_gphy_config_intr, - .suspend = genphy_suspend, - .resume = genphy_resume, -+ .led_brightness_set = xway_gphy_led_brightness_set, -+ .led_hw_is_supported = xway_gphy_led_hw_is_supported, -+ .led_hw_control_get = xway_gphy_led_hw_control_get, -+ .led_hw_control_set = xway_gphy_led_hw_control_set, -+ .led_polarity_set = xway_gphy_led_polarity_set, - }, - }; - module_phy_driver(xway_gphy); diff --git a/target/linux/generic/backport-6.18/730-09-v6.18-net-phy-mxl-gpy-fix-link-properties-on-USXGMII-and-i.patch b/target/linux/generic/backport-6.18/730-09-v6.18-net-phy-mxl-gpy-fix-link-properties-on-USXGMII-and-i.patch deleted file mode 100644 index 6f3bbfcc0e..0000000000 --- a/target/linux/generic/backport-6.18/730-09-v6.18-net-phy-mxl-gpy-fix-link-properties-on-USXGMII-and-i.patch +++ /dev/null @@ -1,56 +0,0 @@ -From 081156ce13f8fa4e97b5148dc54d8c0ddf02117b Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Thu, 20 Nov 2025 15:02:19 +0000 -Subject: [PATCH] net: phy: mxl-gpy: fix link properties on USXGMII and - internal PHYs - -gpy_update_interface() returns early in case the PHY is internal or -connected via USXGMII. In this case the gigabit master/slave property -as well as MDI/MDI-X status also won't be read which seems wrong. -Always read those properties by moving the logic to retrieve them to -gpy_read_status(). - -Fixes: fd8825cd8c6fc ("net: phy: mxl-gpy: Add PHY Auto/MDI/MDI-X set driver for GPY211 chips") -Fixes: 311abcdddc00a ("net: phy: add support to get Master-Slave configuration") -Suggested-by: "Russell King (Oracle)" -Signed-off-by: Daniel Golle -Link: https://patch.msgid.link/71fccf3f56742116eb18cc070d2a9810479ea7f9.1763650701.git.daniel@makrotopia.org -Signed-off-by: Paolo Abeni ---- - drivers/net/phy/mxl-gpy.c | 18 +++++++++++------- - 1 file changed, 11 insertions(+), 7 deletions(-) - ---- a/drivers/net/phy/mxl-gpy.c -+++ b/drivers/net/phy/mxl-gpy.c -@@ -584,13 +584,7 @@ static int gpy_update_interface(struct p - break; - } - -- if (phydev->speed == SPEED_2500 || phydev->speed == SPEED_1000) { -- ret = genphy_read_master_slave(phydev); -- if (ret < 0) -- return ret; -- } -- -- return gpy_update_mdix(phydev); -+ return 0; - } - - static int gpy_read_status(struct phy_device *phydev) -@@ -645,6 +639,16 @@ static int gpy_read_status(struct phy_de - ret = gpy_update_interface(phydev); - if (ret < 0) - return ret; -+ -+ if (phydev->speed == SPEED_2500 || phydev->speed == SPEED_1000) { -+ ret = genphy_read_master_slave(phydev); -+ if (ret < 0) -+ return ret; -+ } -+ -+ ret = gpy_update_mdix(phydev); -+ if (ret < 0) -+ return ret; - } - - return 0; diff --git a/target/linux/generic/backport-6.18/731-v6.18-net-mediatek-wed-Introduce-MT7992-WED-support-to-MT7.patch b/target/linux/generic/backport-6.18/731-v6.18-net-mediatek-wed-Introduce-MT7992-WED-support-to-MT7.patch deleted file mode 100644 index 8b1844df67..0000000000 --- a/target/linux/generic/backport-6.18/731-v6.18-net-mediatek-wed-Introduce-MT7992-WED-support-to-MT7.patch +++ /dev/null @@ -1,116 +0,0 @@ -From: Lorenzo Bianconi -Date: Tue, 12 Aug 2025 06:57:23 +0200 -Subject: [PATCH] net: mediatek: wed: Introduce MT7992 WED support to MT7988 - SoC - -Introduce the second WDMA RX ring in WED driver for MT7988 SoC since the -Mediatek MT7992 WiFi chipset supports two separated WDMA rings. -Add missing MT7988 configurations to properly support WED for MT7992 in -MT76 driver. - -Co-developed-by: Rex Lu -Signed-off-by: Rex Lu -Signed-off-by: Lorenzo Bianconi -Link: https://patch.msgid.link/20250812-mt7992-wed-support-v3-1-9ada78a819a4@kernel.org -Signed-off-by: Jakub Kicinski ---- - ---- a/drivers/net/ethernet/mediatek/mtk_wed.c -+++ b/drivers/net/ethernet/mediatek/mtk_wed.c -@@ -59,7 +59,9 @@ struct mtk_wed_flow_block_priv { - static const struct mtk_wed_soc_data mt7622_data = { - .regmap = { - .tx_bm_tkid = 0x088, -- .wpdma_rx_ring0 = 0x770, -+ .wpdma_rx_ring = { -+ 0x770, -+ }, - .reset_idx_tx_mask = GENMASK(3, 0), - .reset_idx_rx_mask = GENMASK(17, 16), - }, -@@ -70,7 +72,9 @@ static const struct mtk_wed_soc_data mt7 - static const struct mtk_wed_soc_data mt7986_data = { - .regmap = { - .tx_bm_tkid = 0x0c8, -- .wpdma_rx_ring0 = 0x770, -+ .wpdma_rx_ring = { -+ 0x770, -+ }, - .reset_idx_tx_mask = GENMASK(1, 0), - .reset_idx_rx_mask = GENMASK(7, 6), - }, -@@ -81,7 +85,10 @@ static const struct mtk_wed_soc_data mt7 - static const struct mtk_wed_soc_data mt7988_data = { - .regmap = { - .tx_bm_tkid = 0x0c8, -- .wpdma_rx_ring0 = 0x7d0, -+ .wpdma_rx_ring = { -+ 0x7d0, -+ 0x7d8, -+ }, - .reset_idx_tx_mask = GENMASK(1, 0), - .reset_idx_rx_mask = GENMASK(7, 6), - }, -@@ -621,8 +628,8 @@ mtk_wed_amsdu_init(struct mtk_wed_device - return ret; - } - -- /* eagle E1 PCIE1 tx ring 22 flow control issue */ -- if (dev->wlan.id == 0x7991) -+ /* Kite and Eagle E1 PCIE1 tx ring 22 flow control issue */ -+ if (dev->wlan.id == 0x7991 || dev->wlan.id == 0x7992) - wed_clr(dev, MTK_WED_AMSDU_FIFO, MTK_WED_AMSDU_IS_PRIOR0_RING); - - wed_set(dev, MTK_WED_CTRL, MTK_WED_CTRL_TX_AMSDU_EN); -@@ -1239,7 +1246,11 @@ mtk_wed_set_wpdma(struct mtk_wed_device - return; - - wed_w32(dev, MTK_WED_WPDMA_RX_GLO_CFG, dev->wlan.wpdma_rx_glo); -- wed_w32(dev, dev->hw->soc->regmap.wpdma_rx_ring0, dev->wlan.wpdma_rx); -+ wed_w32(dev, dev->hw->soc->regmap.wpdma_rx_ring[0], -+ dev->wlan.wpdma_rx[0]); -+ if (mtk_wed_is_v3_or_greater(dev->hw)) -+ wed_w32(dev, dev->hw->soc->regmap.wpdma_rx_ring[1], -+ dev->wlan.wpdma_rx[1]); - - if (!dev->wlan.hw_rro) - return; -@@ -2335,6 +2346,16 @@ mtk_wed_start(struct mtk_wed_device *dev - if (!dev->rx_wdma[i].desc) - mtk_wed_wdma_rx_ring_setup(dev, i, 16, false); - -+ if (dev->wlan.hw_rro) { -+ for (i = 0; i < MTK_WED_RX_PAGE_QUEUES; i++) { -+ u32 addr = MTK_WED_RRO_MSDU_PG_CTRL0(i) + -+ MTK_WED_RING_OFS_COUNT; -+ -+ if (!wed_r32(dev, addr)) -+ wed_w32(dev, addr, 1); -+ } -+ } -+ - mtk_wed_hw_init(dev); - mtk_wed_configure_irq(dev, irq_mask); - ---- a/drivers/net/ethernet/mediatek/mtk_wed.h -+++ b/drivers/net/ethernet/mediatek/mtk_wed.h -@@ -17,7 +17,7 @@ struct mtk_wed_wo; - struct mtk_wed_soc_data { - struct { - u32 tx_bm_tkid; -- u32 wpdma_rx_ring0; -+ u32 wpdma_rx_ring[MTK_WED_RX_QUEUES]; - u32 reset_idx_tx_mask; - u32 reset_idx_rx_mask; - } regmap; ---- a/include/linux/soc/mediatek/mtk_wed.h -+++ b/include/linux/soc/mediatek/mtk_wed.h -@@ -147,7 +147,7 @@ struct mtk_wed_device { - u32 wpdma_tx; - u32 wpdma_txfree; - u32 wpdma_rx_glo; -- u32 wpdma_rx; -+ u32 wpdma_rx[MTK_WED_RX_QUEUES]; - u32 wpdma_rx_rro[MTK_WED_RX_QUEUES]; - u32 wpdma_rx_pg; - diff --git a/target/linux/generic/backport-6.18/732-v6.18-wifi-mt76-wed-use-proper-wed-reference-in-mt76-wed-d.patch b/target/linux/generic/backport-6.18/732-v6.18-wifi-mt76-wed-use-proper-wed-reference-in-mt76-wed-d.patch deleted file mode 100644 index 883de549cd..0000000000 --- a/target/linux/generic/backport-6.18/732-v6.18-wifi-mt76-wed-use-proper-wed-reference-in-mt76-wed-d.patch +++ /dev/null @@ -1,79 +0,0 @@ -From: Lorenzo Bianconi -Date: Wed, 8 Oct 2025 12:41:48 +0200 -Subject: [PATCH] wifi: mt76: wed: use proper wed reference in mt76 wed driver - callabacks - -MT7996 driver can use both wed and wed_hif2 devices to offload traffic -from/to the wireless NIC. In the current codebase we assume to always -use the primary wed device in wed callbacks resulting in the following -crash if the hw runs wed_hif2 (e.g. 6GHz link). - -[ 297.455876] Unable to handle kernel read from unreadable memory at virtual address 000000000000080a -[ 297.464928] Mem abort info: -[ 297.467722] ESR = 0x0000000096000005 -[ 297.471461] EC = 0x25: DABT (current EL), IL = 32 bits -[ 297.476766] SET = 0, FnV = 0 -[ 297.479809] EA = 0, S1PTW = 0 -[ 297.482940] FSC = 0x05: level 1 translation fault -[ 297.487809] Data abort info: -[ 297.490679] ISV = 0, ISS = 0x00000005, ISS2 = 0x00000000 -[ 297.496156] CM = 0, WnR = 0, TnD = 0, TagAccess = 0 -[ 297.501196] GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0 -[ 297.506500] user pgtable: 4k pages, 39-bit VAs, pgdp=0000000107480000 -[ 297.512927] [000000000000080a] pgd=08000001097fb003, p4d=08000001097fb003, pud=08000001097fb003, pmd=0000000000000000 -[ 297.523532] Internal error: Oops: 0000000096000005 [#1] SMP -[ 297.715393] CPU: 2 UID: 0 PID: 45 Comm: kworker/u16:2 Tainted: G O 6.12.50 #0 -[ 297.723908] Tainted: [O]=OOT_MODULE -[ 297.727384] Hardware name: Banana Pi BPI-R4 (2x SFP+) (DT) -[ 297.732857] Workqueue: nf_ft_offload_del nf_flow_rule_route_ipv6 [nf_flow_table] -[ 297.740254] pstate: 60400005 (nZCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) -[ 297.747205] pc : mt76_wed_offload_disable+0x64/0xa0 [mt76] -[ 297.752688] lr : mtk_wed_flow_remove+0x58/0x80 -[ 297.757126] sp : ffffffc080fe3ae0 -[ 297.760430] x29: ffffffc080fe3ae0 x28: ffffffc080fe3be0 x27: 00000000deadbef7 -[ 297.767557] x26: ffffff80c5ebca00 x25: 0000000000000001 x24: ffffff80c85f4c00 -[ 297.774683] x23: ffffff80c1875b78 x22: ffffffc080d42cd0 x21: ffffffc080660018 -[ 297.781809] x20: ffffff80c6a076d0 x19: ffffff80c6a043c8 x18: 0000000000000000 -[ 297.788935] x17: 0000000000000000 x16: 0000000000000001 x15: 0000000000000000 -[ 297.796060] x14: 0000000000000019 x13: ffffff80c0ad8ec0 x12: 00000000fa83b2da -[ 297.803185] x11: ffffff80c02700c0 x10: ffffff80c0ad8ec0 x9 : ffffff81fef96200 -[ 297.810311] x8 : ffffff80c02700c0 x7 : ffffff80c02700d0 x6 : 0000000000000002 -[ 297.817435] x5 : 0000000000000400 x4 : 0000000000000000 x3 : 0000000000000000 -[ 297.824561] x2 : 0000000000000001 x1 : 0000000000000800 x0 : ffffff80c6a063c8 -[ 297.831686] Call trace: -[ 297.834123] mt76_wed_offload_disable+0x64/0xa0 [mt76] -[ 297.839254] mtk_wed_flow_remove+0x58/0x80 -[ 297.843342] mtk_flow_offload_cmd+0x434/0x574 -[ 297.847689] mtk_wed_setup_tc_block_cb+0x30/0x40 -[ 297.852295] nf_flow_offload_ipv6_hook+0x7f4/0x964 [nf_flow_table] -[ 297.858466] nf_flow_rule_route_ipv6+0x438/0x4a4 [nf_flow_table] -[ 297.864463] process_one_work+0x174/0x300 -[ 297.868465] worker_thread+0x278/0x430 -[ 297.872204] kthread+0xd8/0xdc -[ 297.875251] ret_from_fork+0x10/0x20 -[ 297.878820] Code: 928b5ae0 8b000273 91400a60 f943fa61 (79401421) -[ 297.884901] ---[ end trace 0000000000000000 ]--- - -Fix the issue detecting the proper wed reference to use running wed -callabacks. - --- Partial backport for data structure change only (rest is in the mt76 package) - -Fixes: 83eafc9251d6 ("wifi: mt76: mt7996: add wed tx support") -Tested-by: Daniel Pawlik -Tested-by: Matteo Croce -Signed-off-by: Lorenzo Bianconi -Link: https://patch.msgid.link/20251008-wed-fixes-v1-1-8f7678583385@kernel.org -Signed-off-by: Felix Fietkau ---- - ---- a/include/linux/soc/mediatek/mtk_wed.h -+++ b/include/linux/soc/mediatek/mtk_wed.h -@@ -154,6 +154,7 @@ struct mtk_wed_device { - bool wcid_512; - bool hw_rro; - bool msi; -+ bool hif2; - - u16 token_start; - unsigned int nbuf; diff --git a/target/linux/generic/backport-6.18/733-v6.18-net-mtk-wed-add-dma-mask-limitation-and-GFP_DMA32-fo.patch b/target/linux/generic/backport-6.18/733-v6.18-net-mtk-wed-add-dma-mask-limitation-and-GFP_DMA32-fo.patch deleted file mode 100644 index c1bb1b972b..0000000000 --- a/target/linux/generic/backport-6.18/733-v6.18-net-mtk-wed-add-dma-mask-limitation-and-GFP_DMA32-fo.patch +++ /dev/null @@ -1,50 +0,0 @@ -From: Rex Lu -Date: Thu, 9 Oct 2025 08:29:34 +0200 -Subject: [PATCH] net: mtk: wed: add dma mask limitation and GFP_DMA32 for - device with more than 4GB DRAM - -Limit tx/rx buffer address to 32-bit address space for board with more -than 4GB DRAM. - -Fixes: 804775dfc2885 ("net: ethernet: mtk_eth_soc: add support for Wireless Ethernet Dispatch (WED)") -Fixes: 6757d345dd7db ("net: ethernet: mtk_wed: introduce hw_rro support for MT7988") -Tested-by: Daniel Pawlik -Tested-by: Matteo Croce -Signed-off-by: Rex Lu -Co-developed-by: Lorenzo Bianconi -Signed-off-by: Lorenzo Bianconi -Reviewed-by: Simon Horman -Signed-off-by: David S. Miller ---- - ---- a/drivers/net/ethernet/mediatek/mtk_wed.c -+++ b/drivers/net/ethernet/mediatek/mtk_wed.c -@@ -677,7 +677,7 @@ mtk_wed_tx_buffer_alloc(struct mtk_wed_d - void *buf; - int s; - -- page = __dev_alloc_page(GFP_KERNEL); -+ page = __dev_alloc_page(GFP_KERNEL | GFP_DMA32); - if (!page) - return -ENOMEM; - -@@ -800,7 +800,7 @@ mtk_wed_hwrro_buffer_alloc(struct mtk_we - struct page *page; - int s; - -- page = __dev_alloc_page(GFP_KERNEL); -+ page = __dev_alloc_page(GFP_KERNEL | GFP_DMA32); - if (!page) - return -ENOMEM; - -@@ -2438,6 +2438,10 @@ mtk_wed_attach(struct mtk_wed_device *de - dev->version = hw->version; - dev->hw->pcie_base = mtk_wed_get_pcie_base(dev); - -+ ret = dma_set_mask_and_coherent(hw->dev, DMA_BIT_MASK(32)); -+ if (ret) -+ goto out; -+ - if (hw->eth->dma_dev == hw->eth->dev && - of_dma_is_coherent(hw->eth->dev->of_node)) - mtk_eth_set_dma_device(hw->eth, hw->dev); diff --git a/target/linux/generic/backport-6.18/735-v6.13-net-phy-avoid-undefined-behavior-in-_led_polarity_se.patch b/target/linux/generic/backport-6.18/735-v6.13-net-phy-avoid-undefined-behavior-in-_led_polarity_se.patch deleted file mode 100644 index 622d2c3b54..0000000000 --- a/target/linux/generic/backport-6.18/735-v6.13-net-phy-avoid-undefined-behavior-in-_led_polarity_se.patch +++ /dev/null @@ -1,64 +0,0 @@ -From cff865c700711ecc3824b2dfe181637f3ed23c80 Mon Sep 17 00:00:00 2001 -From: Arnd Bergmann -Date: Tue, 17 Dec 2024 09:10:34 +0100 -Subject: net: phy: avoid undefined behavior in *_led_polarity_set() - -gcc runs into undefined behavior at the end of the three led_polarity_set() -callback functions if it were called with a zero 'modes' argument and it -just ends the function there without returning from it. - -This gets flagged by 'objtool' as a function that continues on -to the next one: - -drivers/net/phy/aquantia/aquantia_leds.o: warning: objtool: aqr_phy_led_polarity_set+0xf: can't find jump dest instruction at .text+0x5d9 -drivers/net/phy/intel-xway.o: warning: objtool: xway_gphy_led_polarity_set() falls through to next function xway_gphy_config_init() -drivers/net/phy/mxl-gpy.o: warning: objtool: gpy_led_polarity_set() falls through to next function gpy_led_hw_control_get() - -There is no point to micro-optimize the behavior here to save a single-digit -number of bytes in the kernel, so just change this to a "return -EINVAL" -as we do when any unexpected bits are set. - -Fixes: 1758af47b98c ("net: phy: intel-xway: add support for PHY LEDs") -Fixes: 9d55e68b19f2 ("net: phy: aquantia: correctly describe LED polarity override") -Fixes: eb89c79c1b8f ("net: phy: mxl-gpy: correctly describe LED polarity") -Signed-off-by: Arnd Bergmann -Reviewed-by: Andrew Lunn -Link: https://patch.msgid.link/20241217081056.238792-1-arnd@kernel.org -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/aquantia/aquantia_leds.c | 2 +- - drivers/net/phy/intel-xway.c | 2 +- - drivers/net/phy/mxl-gpy.c | 2 +- - 3 files changed, 3 insertions(+), 3 deletions(-) - ---- a/drivers/net/phy/aquantia/aquantia_leds.c -+++ b/drivers/net/phy/aquantia/aquantia_leds.c -@@ -156,5 +156,5 @@ int aqr_phy_led_polarity_set(struct phy_ - if (force_active_high || force_active_low) - return aqr_phy_led_active_low_set(phydev, index, force_active_low); - -- unreachable(); -+ return -EINVAL; - } ---- a/drivers/net/phy/intel-xway.c -+++ b/drivers/net/phy/intel-xway.c -@@ -529,7 +529,7 @@ static int xway_gphy_led_polarity_set(st - if (force_active_high) - return phy_clear_bits(phydev, XWAY_MDIO_LED, XWAY_GPHY_LED_INV(index)); - -- unreachable(); -+ return -EINVAL; - } - - static struct phy_driver xway_gphy[] = { ---- a/drivers/net/phy/mxl-gpy.c -+++ b/drivers/net/phy/mxl-gpy.c -@@ -1005,7 +1005,7 @@ static int gpy_led_polarity_set(struct p - if (force_active_high) - return phy_clear_bits(phydev, PHY_LED, PHY_LED_POLARITY(index)); - -- unreachable(); -+ return -EINVAL; - } - - static unsigned int gpy_inband_caps(struct phy_device *phydev, diff --git a/target/linux/generic/backport-6.18/740-v6.13-net-dsa-mv88e6xxx-Support-LED-control.patch b/target/linux/generic/backport-6.18/740-v6.13-net-dsa-mv88e6xxx-Support-LED-control.patch deleted file mode 100644 index 19268cf578..0000000000 --- a/target/linux/generic/backport-6.18/740-v6.13-net-dsa-mv88e6xxx-Support-LED-control.patch +++ /dev/null @@ -1,1250 +0,0 @@ -From 7b590490e3aa6bfa38bf6e2069a529017fd3c1d2 Mon Sep 17 00:00:00 2001 -From: Linus Walleij -Date: Fri, 13 Oct 2023 00:08:35 +0200 -Subject: [PATCH] net: dsa: mv88e6xxx: Support LED control - -This adds control over the hardware LEDs in the Marvell -MV88E6xxx DSA switch and enables it for MV88E6352. - -This fixes an imminent problem on the Inteno XG6846 which -has a WAN LED that simply do not work with hardware -defaults: driver amendment is necessary. - -The patch is modeled after Christian Marangis LED support -code for the QCA8k DSA switch, I got help with the register -definitions from Tim Harvey. - -After this patch it is possible to activate hardware link -indication like this (or with a similar script): - - cd /sys/class/leds/Marvell\ 88E6352:05:00:green:wan/ - echo netdev > trigger - echo 1 > link - -This makes the green link indicator come up on any link -speed. It is also possible to be more elaborate, like this: - - cd /sys/class/leds/Marvell\ 88E6352:05:00:green:wan/ - echo netdev > trigger - echo 1 > link_1000 - cd /sys/class/leds/Marvell\ 88E6352:05:01:amber:wan/ - echo netdev > trigger - echo 1 > link_100 - -Making the green LED come on for a gigabit link and the -amber LED come on for a 100 mbit link. - -Each port has 2 LED slots (the hardware may use just one or -none) and the hardware triggers are specified in four bits per -LED, and some of the hardware triggers are only available on the -SFP (fiber) uplink. The restrictions are described in the -port.h header file where the registers are described. For -example, selector 1 set for LED 1 on port 5 or 6 will indicate -Fiber 1000 (gigabit) and activity with a blinking LED, but -ONLY for an SFP connection. If port 5/6 is used with something -not SFP, this selector is a noop: something else need to be -selected. - -After the previous series rewriting the MV88E6xxx DT -bindings to use YAML a "leds" subnode is already valid -for each port, in my scratch device tree it looks like -this: - - leds { - #address-cells = <1>; - #size-cells = <0>; - - led@0 { - reg = <0>; - color = ; - function = LED_FUNCTION_LAN; - default-state = "off"; - linux,default-trigger = "netdev"; - }; - led@1 { - reg = <1>; - color = ; - function = LED_FUNCTION_LAN; - default-state = "off"; - }; - }; - -This DT config is not yet configuring everything: when the netdev -default trigger is assigned the hw acceleration callbacks are -not called, and there is no way to set the netdev sub-trigger -type (such as link_1000) from the device tree, such as if you want -a gigabit link indicator. This has to be done from userspace at -this point. - -We add LED operations to all switches in the 6352 family: -6172, 6176, 6240 and 6352. - -Signed-off-by: Linus Walleij ---- - drivers/net/dsa/mv88e6xxx/Kconfig | 10 + - drivers/net/dsa/mv88e6xxx/Makefile | 1 + - drivers/net/dsa/mv88e6xxx/chip.c | 38 +- - drivers/net/dsa/mv88e6xxx/chip.h | 11 + - drivers/net/dsa/mv88e6xxx/leds.c | 839 +++++++++++++++++++++++++++++ - drivers/net/dsa/mv88e6xxx/port.c | 1 + - drivers/net/dsa/mv88e6xxx/port.h | 133 +++++ - 7 files changed, 1031 insertions(+), 2 deletions(-) - create mode 100644 drivers/net/dsa/mv88e6xxx/leds.c - ---- a/drivers/net/dsa/mv88e6xxx/Kconfig -+++ b/drivers/net/dsa/mv88e6xxx/Kconfig -@@ -17,3 +17,13 @@ config NET_DSA_MV88E6XXX_PTP - help - Say Y to enable PTP hardware timestamping on Marvell 88E6xxx switch - chips that support it. -+ -+config NET_DSA_MV88E6XXX_LEDS -+ bool "LED support for Marvell 88E6xxx" -+ default y -+ depends on NET_DSA_MV88E6XXX -+ depends on LEDS_CLASS=y || LEDS_CLASS=NET_DSA_MV88E6XXX -+ depends on LEDS_TRIGGERS -+ help -+ This enabled support for controlling the LEDs attached to the -+ Marvell 88E6xxx switch chips. ---- a/drivers/net/dsa/mv88e6xxx/Makefile -+++ b/drivers/net/dsa/mv88e6xxx/Makefile -@@ -9,6 +9,7 @@ mv88e6xxx-objs += global2.o - mv88e6xxx-objs += global2_avb.o - mv88e6xxx-objs += global2_scratch.o - mv88e6xxx-$(CONFIG_NET_DSA_MV88E6XXX_PTP) += hwtstamp.o -+mv88e6xxx-$(CONFIG_NET_DSA_MV88E6XXX_LEDS) += leds.o - mv88e6xxx-objs += pcs-6185.o - mv88e6xxx-objs += pcs-6352.o - mv88e6xxx-objs += pcs-639x.o ---- a/drivers/net/dsa/mv88e6xxx/chip.c -+++ b/drivers/net/dsa/mv88e6xxx/chip.c -@@ -27,6 +27,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -3412,14 +3413,43 @@ static int mv88e6xxx_setup_upstream_port - static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port) - { - struct device_node *phy_handle = NULL; -+ struct fwnode_handle *ports_fwnode; -+ struct fwnode_handle *port_fwnode; - struct dsa_switch *ds = chip->ds; -+ struct mv88e6xxx_port *p; - struct dsa_port *dp; - int tx_amp; - int err; - u16 reg; -+ u32 val; - -- chip->ports[port].chip = chip; -- chip->ports[port].port = port; -+ p = &chip->ports[port]; -+ p->chip = chip; -+ p->port = port; -+ -+ /* Look up corresponding fwnode if any */ -+ ports_fwnode = device_get_named_child_node(chip->dev, "ethernet-ports"); -+ if (!ports_fwnode) -+ ports_fwnode = device_get_named_child_node(chip->dev, "ports"); -+ if (ports_fwnode) { -+ fwnode_for_each_child_node(ports_fwnode, port_fwnode) { -+ if (fwnode_property_read_u32(port_fwnode, "reg", &val)) -+ continue; -+ if (val == port) { -+ p->fwnode = port_fwnode; -+ p->fiber = fwnode_property_present(port_fwnode, "sfp"); -+ break; -+ } -+ } -+ } else { -+ dev_dbg(chip->dev, "no ethernet ports node defined for the device\n"); -+ } -+ -+ if (chip->info->ops->port_setup_leds) { -+ err = chip->info->ops->port_setup_leds(chip, port); -+ if (err && err != -EOPNOTSUPP) -+ return err; -+ } - - err = mv88e6xxx_port_setup_mac(chip, port, LINK_UNFORCED, - SPEED_UNFORCED, DUPLEX_UNFORCED, -@@ -4653,6 +4683,7 @@ static const struct mv88e6xxx_ops mv88e6 - .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit, - .port_disable_pri_override = mv88e6xxx_port_disable_pri_override, - .port_get_cmode = mv88e6352_port_get_cmode, -+ .port_setup_leds = mv88e6xxx_port_setup_leds, - .port_setup_message_port = mv88e6xxx_setup_message_port, - .stats_snapshot = mv88e6320_g1_stats_snapshot, - .stats_set_histogram = mv88e6095_g1_stats_set_histogram, -@@ -4755,6 +4786,7 @@ static const struct mv88e6xxx_ops mv88e6 - .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit, - .port_disable_pri_override = mv88e6xxx_port_disable_pri_override, - .port_get_cmode = mv88e6352_port_get_cmode, -+ .port_setup_leds = mv88e6xxx_port_setup_leds, - .port_setup_message_port = mv88e6xxx_setup_message_port, - .stats_snapshot = mv88e6320_g1_stats_snapshot, - .stats_set_histogram = mv88e6095_g1_stats_set_histogram, -@@ -5030,6 +5062,7 @@ static const struct mv88e6xxx_ops mv88e6 - .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit, - .port_disable_pri_override = mv88e6xxx_port_disable_pri_override, - .port_get_cmode = mv88e6352_port_get_cmode, -+ .port_setup_leds = mv88e6xxx_port_setup_leds, - .port_setup_message_port = mv88e6xxx_setup_message_port, - .stats_snapshot = mv88e6320_g1_stats_snapshot, - .stats_set_histogram = mv88e6095_g1_stats_set_histogram, -@@ -5460,6 +5493,7 @@ static const struct mv88e6xxx_ops mv88e6 - .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit, - .port_disable_pri_override = mv88e6xxx_port_disable_pri_override, - .port_get_cmode = mv88e6352_port_get_cmode, -+ .port_setup_leds = mv88e6xxx_port_setup_leds, - .port_setup_message_port = mv88e6xxx_setup_message_port, - .stats_snapshot = mv88e6320_g1_stats_snapshot, - .stats_set_histogram = mv88e6095_g1_stats_set_histogram, ---- a/drivers/net/dsa/mv88e6xxx/chip.h -+++ b/drivers/net/dsa/mv88e6xxx/chip.h -@@ -13,7 +13,9 @@ - #include - #include - #include -+#include - #include -+#include - #include - #include - #include -@@ -276,6 +278,7 @@ struct mv88e6xxx_vlan { - struct mv88e6xxx_port { - struct mv88e6xxx_chip *chip; - int port; -+ struct fwnode_handle *fwnode; - struct mv88e6xxx_vlan bridge_pvid; - u64 serdes_stats[2]; - u64 atu_member_violation; -@@ -290,6 +293,11 @@ struct mv88e6xxx_port { - struct devlink_region *region; - void *pcs_private; - -+ /* LED related information */ -+ bool fiber; -+ struct led_classdev led0; -+ struct led_classdev led1; -+ - /* MacAuth Bypass control flag */ - bool mab; - }; -@@ -574,6 +582,9 @@ struct mv88e6xxx_ops { - phy_interface_t mode); - int (*port_get_cmode)(struct mv88e6xxx_chip *chip, int port, u8 *cmode); - -+ /* LED control */ -+ int (*port_setup_leds)(struct mv88e6xxx_chip *chip, int port); -+ - /* Some devices have a per port register indicating what is - * the upstream port this port should forward to. - */ ---- /dev/null -+++ b/drivers/net/dsa/mv88e6xxx/leds.c -@@ -0,0 +1,839 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later -+#include -+#include -+#include -+ -+#include "chip.h" -+#include "global2.h" -+#include "port.h" -+ -+/* Offset 0x16: LED control */ -+ -+static int mv88e6xxx_port_led_write(struct mv88e6xxx_chip *chip, int port, u16 reg) -+{ -+ reg |= MV88E6XXX_PORT_LED_CONTROL_UPDATE; -+ -+ return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_LED_CONTROL, reg); -+} -+ -+static int mv88e6xxx_port_led_read(struct mv88e6xxx_chip *chip, int port, -+ u16 ptr, u16 *val) -+{ -+ int err; -+ -+ err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_LED_CONTROL, ptr); -+ if (err) -+ return err; -+ -+ err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_LED_CONTROL, val); -+ *val &= 0x3ff; -+ -+ return err; -+} -+ -+static int mv88e6xxx_led_brightness_set(struct mv88e6xxx_port *p, int led, -+ int brightness) -+{ -+ u16 reg; -+ int err; -+ -+ err = mv88e6xxx_port_led_read(p->chip, p->port, -+ MV88E6XXX_PORT_LED_CONTROL_POINTER_LED01_CTRL, -+ ®); -+ if (err) -+ return err; -+ -+ if (led == 1) -+ reg &= ~MV88E6XXX_PORT_LED_CONTROL_LED1_SEL_MASK; -+ else -+ reg &= ~MV88E6XXX_PORT_LED_CONTROL_LED0_SEL_MASK; -+ -+ if (brightness) { -+ /* Selector 0x0f == Force LED ON */ -+ if (led == 1) -+ reg |= MV88E6XXX_PORT_LED_CONTROL_LED1_SELF; -+ else -+ reg |= MV88E6XXX_PORT_LED_CONTROL_LED0_SELF; -+ } else { -+ /* Selector 0x0e == Force LED OFF */ -+ if (led == 1) -+ reg |= MV88E6XXX_PORT_LED_CONTROL_LED1_SELE; -+ else -+ reg |= MV88E6XXX_PORT_LED_CONTROL_LED0_SELE; -+ } -+ -+ reg |= MV88E6XXX_PORT_LED_CONTROL_POINTER_LED01_CTRL; -+ -+ return mv88e6xxx_port_led_write(p->chip, p->port, reg); -+} -+ -+static int mv88e6xxx_led0_brightness_set_blocking(struct led_classdev *ldev, -+ enum led_brightness brightness) -+{ -+ struct mv88e6xxx_port *p = container_of(ldev, struct mv88e6xxx_port, led0); -+ int err; -+ -+ mv88e6xxx_reg_lock(p->chip); -+ err = mv88e6xxx_led_brightness_set(p, 0, brightness); -+ mv88e6xxx_reg_unlock(p->chip); -+ -+ return err; -+} -+ -+static int mv88e6xxx_led1_brightness_set_blocking(struct led_classdev *ldev, -+ enum led_brightness brightness) -+{ -+ struct mv88e6xxx_port *p = container_of(ldev, struct mv88e6xxx_port, led1); -+ int err; -+ -+ mv88e6xxx_reg_lock(p->chip); -+ err = mv88e6xxx_led_brightness_set(p, 1, brightness); -+ mv88e6xxx_reg_unlock(p->chip); -+ -+ return err; -+} -+ -+struct mv88e6xxx_led_hwconfig { -+ int led; -+ u8 portmask; -+ unsigned long rules; -+ bool fiber; -+ bool blink_activity; -+ u16 selector; -+}; -+ -+/* The following is a lookup table to check what rules we can support on a -+ * certain LED given restrictions such as that some rules only work with fiber -+ * (SFP) connections and some blink on activity by default. -+ */ -+#define MV88E6XXX_PORTS_0_3 (BIT(0) | BIT(1) | BIT(2) | BIT(3)) -+#define MV88E6XXX_PORTS_4_5 (BIT(4) | BIT(5)) -+#define MV88E6XXX_PORT_4 BIT(4) -+#define MV88E6XXX_PORT_5 BIT(5) -+ -+/* Entries are listed in selector order. -+ * -+ * These configurations vary across different switch families, list -+ * different tables per-family here. -+ */ -+static const struct mv88e6xxx_led_hwconfig mv88e6352_led_hwconfigs[] = { -+ { -+ .led = 0, -+ .portmask = MV88E6XXX_PORT_4, -+ .rules = BIT(TRIGGER_NETDEV_LINK), -+ .blink_activity = true, -+ .selector = MV88E6XXX_PORT_LED_CONTROL_LED0_SEL0, -+ }, -+ { -+ .led = 1, -+ .portmask = MV88E6XXX_PORT_5, -+ .rules = BIT(TRIGGER_NETDEV_LINK_1000), -+ .blink_activity = true, -+ .selector = MV88E6XXX_PORT_LED_CONTROL_LED1_SEL0, -+ }, -+ { -+ .led = 0, -+ .portmask = MV88E6XXX_PORTS_0_3, -+ .rules = BIT(TRIGGER_NETDEV_LINK_100) | BIT(TRIGGER_NETDEV_LINK_1000), -+ .blink_activity = true, -+ .selector = MV88E6XXX_PORT_LED_CONTROL_LED0_SEL1, -+ }, -+ { -+ .led = 1, -+ .portmask = MV88E6XXX_PORTS_0_3, -+ .rules = BIT(TRIGGER_NETDEV_LINK_10) | BIT(TRIGGER_NETDEV_LINK_100), -+ .blink_activity = true, -+ .selector = MV88E6XXX_PORT_LED_CONTROL_LED1_SEL1, -+ }, -+ { -+ .led = 0, -+ .portmask = MV88E6XXX_PORTS_4_5, -+ .rules = BIT(TRIGGER_NETDEV_LINK_100), -+ .blink_activity = true, -+ .fiber = true, -+ .selector = MV88E6XXX_PORT_LED_CONTROL_LED0_SEL1, -+ }, -+ { -+ .led = 1, -+ .portmask = MV88E6XXX_PORTS_4_5, -+ .rules = BIT(TRIGGER_NETDEV_LINK_1000), -+ .blink_activity = true, -+ .fiber = true, -+ .selector = MV88E6XXX_PORT_LED_CONTROL_LED1_SEL1, -+ }, -+ { -+ .led = 0, -+ .portmask = MV88E6XXX_PORTS_0_3, -+ .rules = BIT(TRIGGER_NETDEV_LINK_1000), -+ .blink_activity = true, -+ .selector = MV88E6XXX_PORT_LED_CONTROL_LED0_SEL2, -+ }, -+ { -+ .led = 1, -+ .portmask = MV88E6XXX_PORTS_0_3, -+ .rules = BIT(TRIGGER_NETDEV_LINK_10) | BIT(TRIGGER_NETDEV_LINK_100), -+ .blink_activity = true, -+ .selector = MV88E6XXX_PORT_LED_CONTROL_LED1_SEL2, -+ }, -+ { -+ .led = 0, -+ .portmask = MV88E6XXX_PORTS_4_5, -+ .rules = BIT(TRIGGER_NETDEV_LINK_1000), -+ .blink_activity = true, -+ .fiber = true, -+ .selector = MV88E6XXX_PORT_LED_CONTROL_LED0_SEL2, -+ }, -+ { -+ .led = 1, -+ .portmask = MV88E6XXX_PORTS_4_5, -+ .rules = BIT(TRIGGER_NETDEV_LINK_100), -+ .blink_activity = true, -+ .fiber = true, -+ .selector = MV88E6XXX_PORT_LED_CONTROL_LED1_SEL2, -+ }, -+ { -+ .led = 0, -+ .portmask = MV88E6XXX_PORTS_0_3, -+ .rules = BIT(TRIGGER_NETDEV_LINK), -+ .blink_activity = true, -+ .selector = MV88E6XXX_PORT_LED_CONTROL_LED0_SEL3, -+ }, -+ { -+ .led = 1, -+ .portmask = MV88E6XXX_PORTS_0_3, -+ .rules = BIT(TRIGGER_NETDEV_LINK_1000), -+ .selector = MV88E6XXX_PORT_LED_CONTROL_LED1_SEL3, -+ }, -+ { -+ .led = 1, -+ .portmask = MV88E6XXX_PORTS_4_5, -+ .rules = BIT(TRIGGER_NETDEV_LINK), -+ .fiber = true, -+ .selector = MV88E6XXX_PORT_LED_CONTROL_LED1_SEL3, -+ }, -+ { -+ .led = 1, -+ .portmask = MV88E6XXX_PORT_4, -+ .rules = BIT(TRIGGER_NETDEV_LINK), -+ .blink_activity = true, -+ .selector = MV88E6XXX_PORT_LED_CONTROL_LED1_SEL4, -+ }, -+ { -+ .led = 1, -+ .portmask = MV88E6XXX_PORT_5, -+ .rules = BIT(TRIGGER_NETDEV_LINK), -+ .selector = MV88E6XXX_PORT_LED_CONTROL_LED1_SEL5, -+ }, -+ { -+ .led = 0, -+ .portmask = MV88E6XXX_PORTS_0_3, -+ .rules = BIT(TRIGGER_NETDEV_FULL_DUPLEX), -+ .blink_activity = true, -+ .selector = MV88E6XXX_PORT_LED_CONTROL_LED0_SEL6, -+ }, -+ { -+ .led = 1, -+ .portmask = MV88E6XXX_PORTS_0_3, -+ .rules = BIT(TRIGGER_NETDEV_LINK_10) | BIT(TRIGGER_NETDEV_LINK_1000), -+ .blink_activity = true, -+ .selector = MV88E6XXX_PORT_LED_CONTROL_LED1_SEL6, -+ }, -+ { -+ .led = 0, -+ .portmask = MV88E6XXX_PORT_4, -+ .rules = BIT(TRIGGER_NETDEV_FULL_DUPLEX), -+ .blink_activity = true, -+ .selector = MV88E6XXX_PORT_LED_CONTROL_LED0_SEL6, -+ }, -+ { -+ .led = 1, -+ .portmask = MV88E6XXX_PORT_5, -+ .rules = BIT(TRIGGER_NETDEV_FULL_DUPLEX), -+ .blink_activity = true, -+ .selector = MV88E6XXX_PORT_LED_CONTROL_LED1_SEL6, -+ }, -+ { -+ .led = 0, -+ .portmask = MV88E6XXX_PORTS_0_3, -+ .rules = BIT(TRIGGER_NETDEV_LINK_10) | BIT(TRIGGER_NETDEV_LINK_1000), -+ .blink_activity = true, -+ .selector = MV88E6XXX_PORT_LED_CONTROL_LED0_SEL7, -+ }, -+ { -+ .led = 1, -+ .portmask = MV88E6XXX_PORTS_0_3, -+ .rules = BIT(TRIGGER_NETDEV_LINK_10) | BIT(TRIGGER_NETDEV_LINK_1000), -+ .selector = MV88E6XXX_PORT_LED_CONTROL_LED1_SEL7, -+ }, -+ { -+ .led = 0, -+ .portmask = MV88E6XXX_PORTS_0_3, -+ .rules = BIT(TRIGGER_NETDEV_LINK), -+ .selector = MV88E6XXX_PORT_LED_CONTROL_LED0_SEL8, -+ }, -+ { -+ .led = 1, -+ .portmask = MV88E6XXX_PORTS_0_3, -+ .rules = BIT(TRIGGER_NETDEV_LINK), -+ .blink_activity = true, -+ .selector = MV88E6XXX_PORT_LED_CONTROL_LED1_SEL8, -+ }, -+ { -+ .led = 0, -+ .portmask = MV88E6XXX_PORT_5, -+ .rules = BIT(TRIGGER_NETDEV_LINK), -+ .blink_activity = true, -+ .selector = MV88E6XXX_PORT_LED_CONTROL_LED0_SEL8, -+ }, -+ { -+ .led = 0, -+ .portmask = MV88E6XXX_PORTS_0_3, -+ .rules = BIT(TRIGGER_NETDEV_LINK_10), -+ .selector = MV88E6XXX_PORT_LED_CONTROL_LED0_SEL9, -+ }, -+ { -+ .led = 1, -+ .portmask = MV88E6XXX_PORTS_0_3, -+ .rules = BIT(TRIGGER_NETDEV_LINK_100), -+ .selector = MV88E6XXX_PORT_LED_CONTROL_LED1_SEL9, -+ }, -+ { -+ .led = 0, -+ .portmask = MV88E6XXX_PORTS_0_3, -+ .rules = BIT(TRIGGER_NETDEV_LINK_10), -+ .blink_activity = true, -+ .selector = MV88E6XXX_PORT_LED_CONTROL_LED0_SELA, -+ }, -+ { -+ .led = 1, -+ .portmask = MV88E6XXX_PORTS_0_3, -+ .rules = BIT(TRIGGER_NETDEV_LINK_100), -+ .blink_activity = true, -+ .selector = MV88E6XXX_PORT_LED_CONTROL_LED1_SELA, -+ }, -+ { -+ .led = 0, -+ .portmask = MV88E6XXX_PORTS_0_3, -+ .rules = BIT(TRIGGER_NETDEV_LINK_100) | BIT(TRIGGER_NETDEV_LINK_1000), -+ .selector = MV88E6XXX_PORT_LED_CONTROL_LED0_SELB, -+ }, -+ { -+ .led = 1, -+ .portmask = MV88E6XXX_PORTS_0_3, -+ .rules = BIT(TRIGGER_NETDEV_LINK_100) | BIT(TRIGGER_NETDEV_LINK_1000), -+ .blink_activity = true, -+ .selector = MV88E6XXX_PORT_LED_CONTROL_LED1_SELB, -+ }, -+}; -+ -+/* mv88e6xxx_led_match_selector() - look up the appropriate LED mode selector -+ * @p: port state container -+ * @led: LED number, 0 or 1 -+ * @blink_activity: blink the LED (usually blink on indicated activity) -+ * @fiber: the link is connected to fiber such as SFP -+ * @rules: LED status flags from the LED classdev core -+ * @selector: fill in the selector in this parameter with an OR operation -+ */ -+static int mv88e6xxx_led_match_selector(struct mv88e6xxx_port *p, int led, bool blink_activity, -+ bool fiber, unsigned long rules, u16 *selector) -+{ -+ const struct mv88e6xxx_led_hwconfig *conf; -+ int i; -+ -+ /* No rules means we turn the LED off */ -+ if (!rules) { -+ if (led == 1) -+ *selector |= MV88E6XXX_PORT_LED_CONTROL_LED1_SELE; -+ else -+ *selector |= MV88E6XXX_PORT_LED_CONTROL_LED0_SELE; -+ return 0; -+ } -+ -+ /* TODO: these rules are for MV88E6352, when adding other families, -+ * think about making sure you select the table that match the -+ * specific switch family. -+ */ -+ for (i = 0; i < ARRAY_SIZE(mv88e6352_led_hwconfigs); i++) { -+ conf = &mv88e6352_led_hwconfigs[i]; -+ -+ if (conf->led != led) -+ continue; -+ -+ if (!(conf->portmask & BIT(p->port))) -+ continue; -+ -+ if (conf->blink_activity != blink_activity) -+ continue; -+ -+ if (conf->fiber != fiber) -+ continue; -+ -+ if (conf->rules == rules) { -+ dev_dbg(p->chip->dev, "port%d LED %d set selector %04x for rules %08lx\n", -+ p->port, led, conf->selector, rules); -+ *selector |= conf->selector; -+ return 0; -+ } -+ } -+ -+ return -EOPNOTSUPP; -+} -+ -+/* mv88e6xxx_led_match_selector() - find Linux netdev rules from a selector value -+ * @p: port state container -+ * @selector: the selector value from the LED actity register -+ * @led: LED number, 0 or 1 -+ * @rules: Linux netdev activity rules found from selector -+ */ -+static int -+mv88e6xxx_led_match_rule(struct mv88e6xxx_port *p, u16 selector, int led, unsigned long *rules) -+{ -+ const struct mv88e6xxx_led_hwconfig *conf; -+ int i; -+ -+ /* Find the selector in the table, we just look for the right selector -+ * and ignore if the activity has special properties such as blinking -+ * or is fiber-only. -+ */ -+ for (i = 0; i < ARRAY_SIZE(mv88e6352_led_hwconfigs); i++) { -+ conf = &mv88e6352_led_hwconfigs[i]; -+ -+ if (conf->led != led) -+ continue; -+ -+ if (!(conf->portmask & BIT(p->port))) -+ continue; -+ -+ if (conf->selector == selector) { -+ dev_dbg(p->chip->dev, "port%d LED %d has selector %04x, rules %08lx\n", -+ p->port, led, selector, conf->rules); -+ *rules = conf->rules; -+ return 0; -+ } -+ } -+ -+ return -EINVAL; -+} -+ -+/* mv88e6xxx_led_get_selector() - get the appropriate LED mode selector -+ * @p: port state container -+ * @led: LED number, 0 or 1 -+ * @fiber: the link is connected to fiber such as SFP -+ * @rules: LED status flags from the LED classdev core -+ * @selector: fill in the selector in this parameter with an OR operation -+ */ -+static int mv88e6xxx_led_get_selector(struct mv88e6xxx_port *p, int led, -+ bool fiber, unsigned long rules, u16 *selector) -+{ -+ int err; -+ -+ /* What happens here is that we first try to locate a trigger with solid -+ * indicator (such as LED is on for a 1000 link) else we try a second -+ * sweep to find something suitable with a trigger that will blink on -+ * activity. -+ */ -+ err = mv88e6xxx_led_match_selector(p, led, false, fiber, rules, selector); -+ if (err) -+ return mv88e6xxx_led_match_selector(p, led, true, fiber, rules, selector); -+ -+ return 0; -+} -+ -+/* Sets up the hardware blinking period */ -+static int mv88e6xxx_led_set_blinking_period(struct mv88e6xxx_port *p, int led, -+ unsigned long delay_on, unsigned long delay_off) -+{ -+ unsigned long period; -+ u16 reg; -+ -+ period = delay_on + delay_off; -+ -+ reg = 0; -+ -+ switch (period) { -+ case 21: -+ reg |= MV88E6XXX_PORT_LED_CONTROL_0x06_BLINK_RATE_21MS; -+ break; -+ case 42: -+ reg |= MV88E6XXX_PORT_LED_CONTROL_0x06_BLINK_RATE_42MS; -+ break; -+ case 84: -+ reg |= MV88E6XXX_PORT_LED_CONTROL_0x06_BLINK_RATE_84MS; -+ break; -+ case 168: -+ reg |= MV88E6XXX_PORT_LED_CONTROL_0x06_BLINK_RATE_168MS; -+ break; -+ case 336: -+ reg |= MV88E6XXX_PORT_LED_CONTROL_0x06_BLINK_RATE_336MS; -+ break; -+ case 672: -+ reg |= MV88E6XXX_PORT_LED_CONTROL_0x06_BLINK_RATE_672MS; -+ break; -+ default: -+ /* Fall back to software blinking */ -+ return -EINVAL; -+ } -+ -+ /* This is essentially PWM duty cycle: how long time of the period -+ * will the LED be on. Zero isn't great in most cases. -+ */ -+ switch (delay_on) { -+ case 0: -+ /* This is usually pretty useless and will make the LED look OFF */ -+ reg |= MV88E6XXX_PORT_LED_CONTROL_0x06_PULSE_STRETCH_NONE; -+ break; -+ case 21: -+ reg |= MV88E6XXX_PORT_LED_CONTROL_0x06_PULSE_STRETCH_21MS; -+ break; -+ case 42: -+ reg |= MV88E6XXX_PORT_LED_CONTROL_0x06_PULSE_STRETCH_42MS; -+ break; -+ case 84: -+ reg |= MV88E6XXX_PORT_LED_CONTROL_0x06_PULSE_STRETCH_84MS; -+ break; -+ case 168: -+ reg |= MV88E6XXX_PORT_LED_CONTROL_0x06_PULSE_STRETCH_168MS; -+ break; -+ default: -+ /* Just use something non-zero */ -+ reg |= MV88E6XXX_PORT_LED_CONTROL_0x06_PULSE_STRETCH_21MS; -+ break; -+ } -+ -+ /* Set up blink rate */ -+ reg |= MV88E6XXX_PORT_LED_CONTROL_POINTER_STRETCH_BLINK; -+ -+ return mv88e6xxx_port_led_write(p->chip, p->port, reg); -+} -+ -+static int mv88e6xxx_led_blink_set(struct mv88e6xxx_port *p, int led, -+ unsigned long *delay_on, unsigned long *delay_off) -+{ -+ u16 reg; -+ int err; -+ -+ /* Choose a sensible default 336 ms (~3 Hz) */ -+ if ((*delay_on == 0) && (*delay_off == 0)) { -+ *delay_on = 168; -+ *delay_off = 168; -+ } -+ -+ /* No off delay is just on */ -+ if (*delay_off == 0) -+ return mv88e6xxx_led_brightness_set(p, led, 1); -+ -+ err = mv88e6xxx_led_set_blinking_period(p, led, *delay_on, *delay_off); -+ if (err) -+ return err; -+ -+ err = mv88e6xxx_port_led_read(p->chip, p->port, -+ MV88E6XXX_PORT_LED_CONTROL_POINTER_LED01_CTRL, -+ ®); -+ if (err) -+ return err; -+ -+ if (led == 1) -+ reg &= ~MV88E6XXX_PORT_LED_CONTROL_LED1_SEL_MASK; -+ else -+ reg &= ~MV88E6XXX_PORT_LED_CONTROL_LED0_SEL_MASK; -+ -+ /* This will select the forced blinking status */ -+ if (led == 1) -+ reg |= MV88E6XXX_PORT_LED_CONTROL_LED1_SELD; -+ else -+ reg |= MV88E6XXX_PORT_LED_CONTROL_LED0_SELD; -+ -+ reg |= MV88E6XXX_PORT_LED_CONTROL_POINTER_LED01_CTRL; -+ -+ return mv88e6xxx_port_led_write(p->chip, p->port, reg); -+} -+ -+static int mv88e6xxx_led0_blink_set(struct led_classdev *ldev, -+ unsigned long *delay_on, -+ unsigned long *delay_off) -+{ -+ struct mv88e6xxx_port *p = container_of(ldev, struct mv88e6xxx_port, led0); -+ int err; -+ -+ mv88e6xxx_reg_lock(p->chip); -+ err = mv88e6xxx_led_blink_set(p, 0, delay_on, delay_off); -+ mv88e6xxx_reg_unlock(p->chip); -+ -+ return err; -+} -+ -+static int mv88e6xxx_led1_blink_set(struct led_classdev *ldev, -+ unsigned long *delay_on, -+ unsigned long *delay_off) -+{ -+ struct mv88e6xxx_port *p = container_of(ldev, struct mv88e6xxx_port, led1); -+ int err; -+ -+ mv88e6xxx_reg_lock(p->chip); -+ err = mv88e6xxx_led_blink_set(p, 1, delay_on, delay_off); -+ mv88e6xxx_reg_unlock(p->chip); -+ -+ return err; -+} -+ -+static int -+mv88e6xxx_led0_hw_control_is_supported(struct led_classdev *ldev, unsigned long rules) -+{ -+ struct mv88e6xxx_port *p = container_of(ldev, struct mv88e6xxx_port, led0); -+ u16 selector = 0; -+ -+ return mv88e6xxx_led_get_selector(p, 0, p->fiber, rules, &selector); -+} -+ -+static int -+mv88e6xxx_led1_hw_control_is_supported(struct led_classdev *ldev, unsigned long rules) -+{ -+ struct mv88e6xxx_port *p = container_of(ldev, struct mv88e6xxx_port, led1); -+ u16 selector = 0; -+ -+ return mv88e6xxx_led_get_selector(p, 1, p->fiber, rules, &selector); -+} -+ -+static int mv88e6xxx_led_hw_control_set(struct mv88e6xxx_port *p, -+ int led, unsigned long rules) -+{ -+ u16 reg; -+ int err; -+ -+ err = mv88e6xxx_port_led_read(p->chip, p->port, -+ MV88E6XXX_PORT_LED_CONTROL_POINTER_LED01_CTRL, -+ ®); -+ if (err) -+ return err; -+ -+ if (led == 1) -+ reg &= ~MV88E6XXX_PORT_LED_CONTROL_LED1_SEL_MASK; -+ else -+ reg &= ~MV88E6XXX_PORT_LED_CONTROL_LED0_SEL_MASK; -+ -+ err = mv88e6xxx_led_get_selector(p, led, p->fiber, rules, ®); -+ if (err) -+ return err; -+ -+ reg |= MV88E6XXX_PORT_LED_CONTROL_POINTER_LED01_CTRL; -+ -+ if (led == 0) -+ dev_dbg(p->chip->dev, "LED 0 hw control on port %d trigger selector 0x%02x\n", -+ p->port, -+ (unsigned int)(reg & MV88E6XXX_PORT_LED_CONTROL_LED0_SEL_MASK)); -+ else -+ dev_dbg(p->chip->dev, "LED 1 hw control on port %d trigger selector 0x%02x\n", -+ p->port, -+ (unsigned int)(reg & MV88E6XXX_PORT_LED_CONTROL_LED1_SEL_MASK) >> 4); -+ -+ return mv88e6xxx_port_led_write(p->chip, p->port, reg); -+} -+ -+static int -+mv88e6xxx_led_hw_control_get(struct mv88e6xxx_port *p, int led, unsigned long *rules) -+{ -+ u16 val; -+ int err; -+ -+ mv88e6xxx_reg_lock(p->chip); -+ err = mv88e6xxx_port_led_read(p->chip, p->port, -+ MV88E6XXX_PORT_LED_CONTROL_POINTER_LED01_CTRL, &val); -+ mv88e6xxx_reg_unlock(p->chip); -+ if (err) -+ return err; -+ -+ /* Mask out the selector bits for this port */ -+ if (led == 1) { -+ val &= MV88E6XXX_PORT_LED_CONTROL_LED1_SEL_MASK; -+ /* It's forced blinking/OFF/ON */ -+ if (val == MV88E6XXX_PORT_LED_CONTROL_LED1_SELD || -+ val == MV88E6XXX_PORT_LED_CONTROL_LED1_SELE || -+ val == MV88E6XXX_PORT_LED_CONTROL_LED1_SELF) { -+ *rules = 0; -+ return 0; -+ } -+ } else { -+ val &= MV88E6XXX_PORT_LED_CONTROL_LED0_SEL_MASK; -+ /* It's forced blinking/OFF/ON */ -+ if (val == MV88E6XXX_PORT_LED_CONTROL_LED0_SELD || -+ val == MV88E6XXX_PORT_LED_CONTROL_LED0_SELE || -+ val == MV88E6XXX_PORT_LED_CONTROL_LED0_SELF) { -+ *rules = 0; -+ return 0; -+ } -+ } -+ -+ err = mv88e6xxx_led_match_rule(p, val, led, rules); -+ if (!err) -+ return 0; -+ -+ dev_dbg(p->chip->dev, "couldn't find matching selector for %04x\n", val); -+ *rules = 0; -+ return 0; -+} -+ -+static int -+mv88e6xxx_led0_hw_control_set(struct led_classdev *ldev, unsigned long rules) -+{ -+ struct mv88e6xxx_port *p = container_of(ldev, struct mv88e6xxx_port, led0); -+ int err; -+ -+ mv88e6xxx_reg_lock(p->chip); -+ err = mv88e6xxx_led_hw_control_set(p, 0, rules); -+ mv88e6xxx_reg_unlock(p->chip); -+ -+ return err; -+} -+ -+static int -+mv88e6xxx_led1_hw_control_set(struct led_classdev *ldev, unsigned long rules) -+{ -+ struct mv88e6xxx_port *p = container_of(ldev, struct mv88e6xxx_port, led1); -+ int err; -+ -+ mv88e6xxx_reg_lock(p->chip); -+ err = mv88e6xxx_led_hw_control_set(p, 1, rules); -+ mv88e6xxx_reg_unlock(p->chip); -+ -+ return err; -+} -+ -+static int -+mv88e6xxx_led0_hw_control_get(struct led_classdev *ldev, unsigned long *rules) -+{ -+ struct mv88e6xxx_port *p = container_of(ldev, struct mv88e6xxx_port, led0); -+ -+ return mv88e6xxx_led_hw_control_get(p, 0, rules); -+} -+ -+static int -+mv88e6xxx_led1_hw_control_get(struct led_classdev *ldev, unsigned long *rules) -+{ -+ struct mv88e6xxx_port *p = container_of(ldev, struct mv88e6xxx_port, led1); -+ -+ return mv88e6xxx_led_hw_control_get(p, 1, rules); -+} -+ -+static struct device *mv88e6xxx_led_hw_control_get_device(struct mv88e6xxx_port *p) -+{ -+ struct dsa_port *dp; -+ -+ dp = dsa_to_port(p->chip->ds, p->port); -+ if (!dp) -+ return NULL; -+ if (dp->user) -+ return &dp->user->dev; -+ return NULL; -+} -+ -+static struct device * -+mv88e6xxx_led0_hw_control_get_device(struct led_classdev *ldev) -+{ -+ struct mv88e6xxx_port *p = container_of(ldev, struct mv88e6xxx_port, led0); -+ -+ return mv88e6xxx_led_hw_control_get_device(p); -+} -+ -+static struct device * -+mv88e6xxx_led1_hw_control_get_device(struct led_classdev *ldev) -+{ -+ struct mv88e6xxx_port *p = container_of(ldev, struct mv88e6xxx_port, led1); -+ -+ return mv88e6xxx_led_hw_control_get_device(p); -+} -+ -+int mv88e6xxx_port_setup_leds(struct mv88e6xxx_chip *chip, int port) -+{ -+ struct fwnode_handle *led = NULL, *leds = NULL; -+ struct led_init_data init_data = { }; -+ enum led_default_state state; -+ struct mv88e6xxx_port *p; -+ struct led_classdev *l; -+ struct device *dev; -+ u32 led_num; -+ int ret; -+ -+ /* LEDs are on ports 1,2,3,4, 5 and 6 (index 0..5), no more */ -+ if (port > 5) -+ return -EOPNOTSUPP; -+ -+ p = &chip->ports[port]; -+ if (!p->fwnode) -+ return 0; -+ -+ dev = chip->dev; -+ -+ leds = fwnode_get_named_child_node(p->fwnode, "leds"); -+ if (!leds) { -+ dev_dbg(dev, "No Leds node specified in device tree for port %d!\n", -+ port); -+ return 0; -+ } -+ -+ fwnode_for_each_child_node(leds, led) { -+ /* Reg represent the led number of the port, max 2 -+ * LEDs can be connected to each port, in some designs -+ * only one LED is connected. -+ */ -+ if (fwnode_property_read_u32(led, "reg", &led_num)) -+ continue; -+ if (led_num > 1) { -+ dev_err(dev, "invalid LED specified port %d\n", port); -+ return -EINVAL; -+ } -+ -+ if (led_num == 0) -+ l = &p->led0; -+ else -+ l = &p->led1; -+ -+ state = led_init_default_state_get(led); -+ switch (state) { -+ case LEDS_DEFSTATE_ON: -+ l->brightness = 1; -+ mv88e6xxx_led_brightness_set(p, led_num, 1); -+ break; -+ case LEDS_DEFSTATE_KEEP: -+ break; -+ default: -+ l->brightness = 0; -+ mv88e6xxx_led_brightness_set(p, led_num, 0); -+ } -+ -+ l->max_brightness = 1; -+ if (led_num == 0) { -+ l->brightness_set_blocking = mv88e6xxx_led0_brightness_set_blocking; -+ l->blink_set = mv88e6xxx_led0_blink_set; -+ l->hw_control_is_supported = mv88e6xxx_led0_hw_control_is_supported; -+ l->hw_control_set = mv88e6xxx_led0_hw_control_set; -+ l->hw_control_get = mv88e6xxx_led0_hw_control_get; -+ l->hw_control_get_device = mv88e6xxx_led0_hw_control_get_device; -+ } else { -+ l->brightness_set_blocking = mv88e6xxx_led1_brightness_set_blocking; -+ l->blink_set = mv88e6xxx_led1_blink_set; -+ l->hw_control_is_supported = mv88e6xxx_led1_hw_control_is_supported; -+ l->hw_control_set = mv88e6xxx_led1_hw_control_set; -+ l->hw_control_get = mv88e6xxx_led1_hw_control_get; -+ l->hw_control_get_device = mv88e6xxx_led1_hw_control_get_device; -+ } -+ l->hw_control_trigger = "netdev"; -+ -+ init_data.default_label = ":port"; -+ init_data.fwnode = led; -+ init_data.devname_mandatory = true; -+ init_data.devicename = kasprintf(GFP_KERNEL, "%s:0%d:0%d", chip->info->name, -+ port, led_num); -+ if (!init_data.devicename) -+ return -ENOMEM; -+ -+ ret = devm_led_classdev_register_ext(dev, l, &init_data); -+ kfree(init_data.devicename); -+ -+ if (ret) { -+ dev_err(dev, "Failed to init LED %d for port %d", led_num, port); -+ return ret; -+ } -+ } -+ -+ return 0; -+} ---- a/drivers/net/dsa/mv88e6xxx/port.c -+++ b/drivers/net/dsa/mv88e6xxx/port.c -@@ -12,6 +12,7 @@ - #include - #include - #include -+#include - - #include "chip.h" - #include "global2.h" ---- a/drivers/net/dsa/mv88e6xxx/port.h -+++ b/drivers/net/dsa/mv88e6xxx/port.h -@@ -309,6 +309,130 @@ - /* Offset 0x13: OutFiltered Counter */ - #define MV88E6XXX_PORT_OUT_FILTERED 0x13 - -+/* Offset 0x16: LED Control */ -+#define MV88E6XXX_PORT_LED_CONTROL 0x16 -+#define MV88E6XXX_PORT_LED_CONTROL_UPDATE BIT(15) -+#define MV88E6XXX_PORT_LED_CONTROL_POINTER_MASK GENMASK(14, 12) -+#define MV88E6XXX_PORT_LED_CONTROL_POINTER_LED01_CTRL (0x00 << 12) /* Control for LED 0 and 1 */ -+#define MV88E6XXX_PORT_LED_CONTROL_POINTER_STRETCH_BLINK (0x06 << 12) /* Stetch and Blink Rate */ -+#define MV88E6XXX_PORT_LED_CONTROL_POINTER_CNTL_SPECIAL (0x07 << 12) /* Control for the Port's Special LED */ -+#define MV88E6XXX_PORT_LED_CONTROL_DATA_MASK GENMASK(10, 0) -+/* Selection masks valid for either port 1,2,3,4 or 5 */ -+#define MV88E6XXX_PORT_LED_CONTROL_LED0_SEL_MASK GENMASK(3, 0) -+#define MV88E6XXX_PORT_LED_CONTROL_LED1_SEL_MASK GENMASK(7, 4) -+/* Selection control for LED 0 and 1, ports 5 and 6 only has LED 0 -+ * Bits Function -+ * 0..3 LED 0 control selector on ports 1-5 -+ * 4..7 LED 1 control selector on ports 1-4 on port 5 this controls LED 0 of port 6 -+ * -+ * Sel Port LED Function for the 6352 family: -+ * 0 1-4 0 Link/Act/Speed by Blink Rate (off=no link, on=link, blink=activity, blink speed=link speed) -+ * 1-4 1 Port 2's Special LED -+ * 5-6 0 Port 5 Link/Act (off=no link, on=link, blink=activity) -+ * 5-6 1 Port 6 Link/Act (off=no link, on=link 1000, blink=activity) -+ * 1 1-4 0 100/1000 Link/Act (off=no link, on=100 or 1000 link, blink=activity) -+ * 1-4 1 10/100 Link Act (off=no link, on=10 or 100 link, blink=activity) -+ * 5-6 0 Fiber 100 Link/Act (off=no link, on=link 100, blink=activity) -+ * 5-6 1 Fiber 1000 Link/Act (off=no link, on=link 1000, blink=activity) -+ * 2 1-4 0 1000 Link/Act (off=no link, on=link 1000, blink=activity) -+ * 1-4 1 10/100 Link/Act (off=no link, on=10 or 100 link, blink=activity) -+ * 5-6 0 Fiber 1000 Link/Act (off=no link, on=link 1000, blink=activity) -+ * 5-6 1 Fiber 100 Link/Act (off=no link, on=link 100, blink=activity) -+ * 3 1-4 0 Link/Act (off=no link, on=link, blink=activity) -+ * 1-4 1 1000 Link (off=no link, on=1000 link) -+ * 5-6 0 Port 0's Special LED -+ * 5-6 1 Fiber Link (off=no link, on=link) -+ * 4 1-4 0 Port 0's Special LED -+ * 1-4 1 Port 1's Special LED -+ * 5-6 0 Port 1's Special LED -+ * 5-6 1 Port 5 Link/Act (off=no link, on=link, blink=activity) -+ * 5 1-4 0 Reserved -+ * 1-4 1 Reserved -+ * 5-6 0 Port 2's Special LED -+ * 5-6 1 Port 6 Link (off=no link, on=link) -+ * 6 1-4 0 Duplex/Collision (off=half-duplex,on=full-duplex,blink=collision) -+ * 1-4 1 10/1000 Link/Act (off=no link, on=10 or 1000 link, blink=activity) -+ * 5-6 0 Port 5 Duplex/Collision (off=half-duplex, on=full-duplex, blink=col) -+ * 5-6 1 Port 6 Duplex/Collision (off=half-duplex, on=full-duplex, blink=col) -+ * 7 1-4 0 10/1000 Link/Act (off=no link, on=10 or 1000 link, blink=activity) -+ * 1-4 1 10/1000 Link (off=no link, on=10 or 1000 link) -+ * 5-6 0 Port 5 Link/Act/Speed by Blink rate (off=no link, on=link, blink=activity, blink speed=link speed) -+ * 5-6 1 Port 6 Link/Act/Speed by Blink rate (off=no link, on=link, blink=activity, blink speed=link speed) -+ * 8 1-4 0 Link (off=no link, on=link) -+ * 1-4 1 Activity (off=no link, blink on=activity) -+ * 5-6 0 Port 6 Link/Act (off=no link, on=link, blink=activity) -+ * 5-6 1 Port 0's Special LED -+ * 9 1-4 0 10 Link (off=no link, on=10 link) -+ * 1-4 1 100 Link (off=no link, on=100 link) -+ * 5-6 0 Reserved -+ * 5-6 1 Port 1's Special LED -+ * a 1-4 0 10 Link/Act (off=no link, on=10 link, blink=activity) -+ * 1-4 1 100 Link/Act (off=no link, on=100 link, blink=activity) -+ * 5-6 0 Reserved -+ * 5-6 1 Port 2's Special LED -+ * b 1-4 0 100/1000 Link (off=no link, on=100 or 1000 link) -+ * 1-4 1 10/100 Link (off=no link, on=100 link, blink=activity) -+ * 5-6 0 Reserved -+ * 5-6 1 Reserved -+ * c * * PTP Act (blink on=PTP activity) -+ * d * * Force Blink -+ * e * * Force Off -+ * f * * Force On -+ */ -+/* Select LED0 output */ -+#define MV88E6XXX_PORT_LED_CONTROL_LED0_SEL0 0x0 -+#define MV88E6XXX_PORT_LED_CONTROL_LED0_SEL1 0x1 -+#define MV88E6XXX_PORT_LED_CONTROL_LED0_SEL2 0x2 -+#define MV88E6XXX_PORT_LED_CONTROL_LED0_SEL3 0x3 -+#define MV88E6XXX_PORT_LED_CONTROL_LED0_SEL4 0x4 -+#define MV88E6XXX_PORT_LED_CONTROL_LED0_SEL5 0x5 -+#define MV88E6XXX_PORT_LED_CONTROL_LED0_SEL6 0x6 -+#define MV88E6XXX_PORT_LED_CONTROL_LED0_SEL7 0x7 -+#define MV88E6XXX_PORT_LED_CONTROL_LED0_SEL8 0x8 -+#define MV88E6XXX_PORT_LED_CONTROL_LED0_SEL9 0x9 -+#define MV88E6XXX_PORT_LED_CONTROL_LED0_SELA 0xa -+#define MV88E6XXX_PORT_LED_CONTROL_LED0_SELB 0xb -+#define MV88E6XXX_PORT_LED_CONTROL_LED0_SELC 0xc -+#define MV88E6XXX_PORT_LED_CONTROL_LED0_SELD 0xd -+#define MV88E6XXX_PORT_LED_CONTROL_LED0_SELE 0xe -+#define MV88E6XXX_PORT_LED_CONTROL_LED0_SELF 0xf -+#define MV88E6XXX_PORT_LED_CONTROL_LED1_SEL0 (0x0 << 4) -+#define MV88E6XXX_PORT_LED_CONTROL_LED1_SEL1 (0x1 << 4) -+#define MV88E6XXX_PORT_LED_CONTROL_LED1_SEL2 (0x2 << 4) -+#define MV88E6XXX_PORT_LED_CONTROL_LED1_SEL3 (0x3 << 4) -+#define MV88E6XXX_PORT_LED_CONTROL_LED1_SEL4 (0x4 << 4) -+#define MV88E6XXX_PORT_LED_CONTROL_LED1_SEL5 (0x5 << 4) -+#define MV88E6XXX_PORT_LED_CONTROL_LED1_SEL6 (0x6 << 4) -+#define MV88E6XXX_PORT_LED_CONTROL_LED1_SEL7 (0x7 << 4) -+#define MV88E6XXX_PORT_LED_CONTROL_LED1_SEL8 (0x8 << 4) -+#define MV88E6XXX_PORT_LED_CONTROL_LED1_SEL9 (0x9 << 4) -+#define MV88E6XXX_PORT_LED_CONTROL_LED1_SELA (0xa << 4) -+#define MV88E6XXX_PORT_LED_CONTROL_LED1_SELB (0xb << 4) -+#define MV88E6XXX_PORT_LED_CONTROL_LED1_SELC (0xc << 4) -+#define MV88E6XXX_PORT_LED_CONTROL_LED1_SELD (0xd << 4) -+#define MV88E6XXX_PORT_LED_CONTROL_LED1_SELE (0xe << 4) -+#define MV88E6XXX_PORT_LED_CONTROL_LED1_SELF (0xf << 4) -+/* Stretch and Blink Rate Control (Index 0x06 of LED Control) */ -+/* Pulse Stretch Selection for all LED's on this port */ -+#define MV88E6XXX_PORT_LED_CONTROL_0x06_PULSE_STRETCH_NONE (0 << 4) -+#define MV88E6XXX_PORT_LED_CONTROL_0x06_PULSE_STRETCH_21MS (1 << 4) -+#define MV88E6XXX_PORT_LED_CONTROL_0x06_PULSE_STRETCH_42MS (2 << 4) -+#define MV88E6XXX_PORT_LED_CONTROL_0x06_PULSE_STRETCH_84MS (3 << 4) -+#define MV88E6XXX_PORT_LED_CONTROL_0x06_PULSE_STRETCH_168MS (4 << 4) -+/* Blink Rate Selection for all LEDs on this port */ -+#define MV88E6XXX_PORT_LED_CONTROL_0x06_BLINK_RATE_21MS 0 -+#define MV88E6XXX_PORT_LED_CONTROL_0x06_BLINK_RATE_42MS 1 -+#define MV88E6XXX_PORT_LED_CONTROL_0x06_BLINK_RATE_84MS 2 -+#define MV88E6XXX_PORT_LED_CONTROL_0x06_BLINK_RATE_168MS 3 -+#define MV88E6XXX_PORT_LED_CONTROL_0x06_BLINK_RATE_336MS 4 -+#define MV88E6XXX_PORT_LED_CONTROL_0x06_BLINK_RATE_672MS 5 -+ /* Control for Special LED (Index 0x7 of LED Control on Port0) */ -+#define MV88E6XXX_PORT_LED_CONTROL_0x07_P0_LAN_LINKACT_SHIFT 0 /* bits 6:0 LAN Link Activity LED */ -+/* Control for Special LED (Index 0x7 of LED Control on Port 1) */ -+#define MV88E6XXX_PORT_LED_CONTROL_0x07_P1_WAN_LINKACT_SHIFT 0 /* bits 6:0 WAN Link Activity LED */ -+/* Control for Special LED (Index 0x7 of LED Control on Port 2) */ -+#define MV88E6XXX_PORT_LED_CONTROL_0x07_P2_PTP_ACT 0 /* bits 6:0 PTP Activity */ -+ - /* Offset 0x18: IEEE Priority Mapping Table */ - #define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE 0x18 - #define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_UPDATE 0x8000 -@@ -457,6 +581,15 @@ int mv88e6393x_port_set_cmode(struct mv8 - phy_interface_t mode); - int mv88e6185_port_get_cmode(struct mv88e6xxx_chip *chip, int port, u8 *cmode); - int mv88e6352_port_get_cmode(struct mv88e6xxx_chip *chip, int port, u8 *cmode); -+#ifdef CONFIG_NET_DSA_MV88E6XXX_LEDS -+int mv88e6xxx_port_setup_leds(struct mv88e6xxx_chip *chip, int port); -+#else -+static inline int mv88e6xxx_port_setup_leds(struct mv88e6xxx_chip *chip, -+ int port) -+{ -+ return 0; -+} -+#endif - int mv88e6xxx_port_drop_untagged(struct mv88e6xxx_chip *chip, int port, - bool drop_untagged); - int mv88e6xxx_port_set_map_da(struct mv88e6xxx_chip *chip, int port, bool map); diff --git a/target/linux/generic/backport-6.18/741-v6.13-net-dsa-mv88e6xxx-fix-unreleased-fwnode_handle-in-se.patch b/target/linux/generic/backport-6.18/741-v6.13-net-dsa-mv88e6xxx-fix-unreleased-fwnode_handle-in-se.patch deleted file mode 100644 index 2c81983a20..0000000000 --- a/target/linux/generic/backport-6.18/741-v6.13-net-dsa-mv88e6xxx-fix-unreleased-fwnode_handle-in-se.patch +++ /dev/null @@ -1,31 +0,0 @@ -From b8ee7a11c75436b85fa1641aa5f970de0f8a575c Mon Sep 17 00:00:00 2001 -From: Javier Carrasco -Date: Sat, 19 Oct 2024 22:16:49 +0200 -Subject: net: dsa: mv88e6xxx: fix unreleased fwnode_handle in setup_port() - -'ports_fwnode' is initialized via device_get_named_child_node(), which -requires a call to fwnode_handle_put() when the variable is no longer -required to avoid leaking memory. - -Add the missing fwnode_handle_put() after 'ports_fwnode' has been used -and is no longer required. - -Fixes: 94a2a84f5e9e ("net: dsa: mv88e6xxx: Support LED control") -Signed-off-by: Javier Carrasco -Reviewed-by: Andrew Lunn -Reviewed-by: Linus Walleij -Signed-off-by: David S. Miller ---- - drivers/net/dsa/mv88e6xxx/chip.c | 1 + - 1 file changed, 1 insertion(+) - ---- a/drivers/net/dsa/mv88e6xxx/chip.c -+++ b/drivers/net/dsa/mv88e6xxx/chip.c -@@ -3441,6 +3441,7 @@ static int mv88e6xxx_setup_port(struct m - break; - } - } -+ fwnode_handle_put(ports_fwnode); - } else { - dev_dbg(chip->dev, "no ethernet ports node defined for the device\n"); - } diff --git a/target/linux/generic/backport-6.18/742-v6.17-net-dsa-mv88e6xxx-Fix-fwnode-reference-leaks-in-mv88.patch b/target/linux/generic/backport-6.18/742-v6.17-net-dsa-mv88e6xxx-Fix-fwnode-reference-leaks-in-mv88.patch deleted file mode 100644 index 6e0fbb82af..0000000000 --- a/target/linux/generic/backport-6.18/742-v6.17-net-dsa-mv88e6xxx-Fix-fwnode-reference-leaks-in-mv88.patch +++ /dev/null @@ -1,68 +0,0 @@ -From f63e7c8a83892781f6ceb55566f9497639c44555 Mon Sep 17 00:00:00 2001 -From: Miaoqian Lin -Date: Mon, 1 Sep 2025 15:32:23 +0800 -Subject: net: dsa: mv88e6xxx: Fix fwnode reference leaks in - mv88e6xxx_port_setup_leds - -Fix multiple fwnode reference leaks: - -1. The function calls fwnode_get_named_child_node() to get the "leds" node, - but never calls fwnode_handle_put(leds) to release this reference. - -2. Within the fwnode_for_each_child_node() loop, the early return - paths that don't properly release the "led" fwnode reference. - -This fix follows the same pattern as commit d029edefed39 -("net dsa: qca8k: fix usages of device_get_named_child_node()") - -Fixes: 94a2a84f5e9e ("net: dsa: mv88e6xxx: Support LED control") -Cc: stable@vger.kernel.org -Signed-off-by: Miaoqian Lin -Reviewed-by: Linus Walleij -Link: https://patch.msgid.link/20250901073224.2273103-1-linmq006@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/dsa/mv88e6xxx/leds.c | 17 +++++++++++++---- - 1 file changed, 13 insertions(+), 4 deletions(-) - ---- a/drivers/net/dsa/mv88e6xxx/leds.c -+++ b/drivers/net/dsa/mv88e6xxx/leds.c -@@ -779,7 +779,8 @@ int mv88e6xxx_port_setup_leds(struct mv8 - continue; - if (led_num > 1) { - dev_err(dev, "invalid LED specified port %d\n", port); -- return -EINVAL; -+ ret = -EINVAL; -+ goto err_put_led; - } - - if (led_num == 0) -@@ -823,17 +824,25 @@ int mv88e6xxx_port_setup_leds(struct mv8 - init_data.devname_mandatory = true; - init_data.devicename = kasprintf(GFP_KERNEL, "%s:0%d:0%d", chip->info->name, - port, led_num); -- if (!init_data.devicename) -- return -ENOMEM; -+ if (!init_data.devicename) { -+ ret = -ENOMEM; -+ goto err_put_led; -+ } - - ret = devm_led_classdev_register_ext(dev, l, &init_data); - kfree(init_data.devicename); - - if (ret) { - dev_err(dev, "Failed to init LED %d for port %d", led_num, port); -- return ret; -+ goto err_put_led; - } - } - -+ fwnode_handle_put(leds); - return 0; -+ -+err_put_led: -+ fwnode_handle_put(led); -+ fwnode_handle_put(leds); -+ return ret; - } diff --git a/target/linux/generic/backport-6.18/760-v6.18-net-phy-introduce-phy_id_compare_model-PHY-ID-helper.patch b/target/linux/generic/backport-6.18/760-v6.18-net-phy-introduce-phy_id_compare_model-PHY-ID-helper.patch deleted file mode 100644 index a367f66504..0000000000 --- a/target/linux/generic/backport-6.18/760-v6.18-net-phy-introduce-phy_id_compare_model-PHY-ID-helper.patch +++ /dev/null @@ -1,39 +0,0 @@ -From ae1c658b33d4bec20c037aebba583a68375d4773 Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Thu, 11 Sep 2025 15:08:31 +0200 -Subject: [PATCH] net: phy: introduce phy_id_compare_model() PHY ID helper - -Similar to phy_id_compare_vendor(), introduce the equivalent -phy_id_compare_model() helper for the generic PHY ID Model mask. - -Reviewed-by: Andrew Lunn -Reviewed-by: Florian Fainelli -Signed-off-by: Christian Marangi -Link: https://patch.msgid.link/20250911130840.23569-1-ansuelsmth@gmail.com -Signed-off-by: Jakub Kicinski ---- - include/linux/phy.h | 13 +++++++++++++ - 1 file changed, 13 insertions(+) - ---- a/include/linux/phy.h -+++ b/include/linux/phy.h -@@ -1284,6 +1284,19 @@ static inline bool phy_id_compare(u32 id - } - - /** -+ * phy_id_compare_model - compare @id with @model mask -+ * @id: PHY ID -+ * @model_mask: PHY Model mask -+ * -+ * Return: true if the bits from @id match @model using the -+ * generic PHY Model mask. -+ */ -+static inline bool phy_id_compare_model(u32 id, u32 model_mask) -+{ -+ return phy_id_compare(id, model_mask, PHY_ID_MATCH_MODEL_MASK); -+} -+ -+/** - * phydev_id_compare - compare @id with the PHY's Clause 22 ID - * @phydev: the PHY device - * @id: the PHY ID to be matched diff --git a/target/linux/generic/backport-6.18/780-01-v6.13-r8169-remove-original-workaround-for-RTL8125-broken-.patch b/target/linux/generic/backport-6.18/780-01-v6.13-r8169-remove-original-workaround-for-RTL8125-broken-.patch deleted file mode 100644 index bd10a96772..0000000000 --- a/target/linux/generic/backport-6.18/780-01-v6.13-r8169-remove-original-workaround-for-RTL8125-broken-.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 854d71c555dfc3383c1fde7d9989b6046e21093d Mon Sep 17 00:00:00 2001 -From: Heiner Kallweit -Date: Wed, 9 Oct 2024 07:48:05 +0200 -Subject: [PATCH] r8169: remove original workaround for RTL8125 broken rx issue - -Now that we have b9c7ac4fe22c ("r8169: disable ALDPS per default for -RTL8125"), the first attempt to fix the issue shouldn't be needed -any longer. So let's effectively revert 621735f59064 ("r8169: fix -rare issue with broken rx after link-down on RTL8125") and see -whether anybody complains. - -Signed-off-by: Heiner Kallweit -Reviewed-by: Simon Horman -Link: https://patch.msgid.link/382d8c88-cbce-400f-ad62-fda0181c7e38@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/realtek/r8169_main.c | 4 ---- - 1 file changed, 4 deletions(-) - ---- a/drivers/net/ethernet/realtek/r8169_main.c -+++ b/drivers/net/ethernet/realtek/r8169_main.c -@@ -4810,11 +4810,7 @@ static void r8169_phylink_handler(struct - if (netif_carrier_ok(ndev)) { - rtl_link_chg_patch(tp); - pm_request_resume(d); -- netif_wake_queue(tp->dev); - } else { -- /* In few cases rx is broken after link-down otherwise */ -- if (rtl_is_8125(tp)) -- rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_NO_QUEUE_WAKE); - pm_runtime_idle(d); - } - diff --git a/target/linux/generic/backport-6.18/780-02-v6.13-r8169-enable-SG-TSO-on-selected-chip-versions-per-de.patch b/target/linux/generic/backport-6.18/780-02-v6.13-r8169-enable-SG-TSO-on-selected-chip-versions-per-de.patch deleted file mode 100644 index 7ea1a11ee3..0000000000 --- a/target/linux/generic/backport-6.18/780-02-v6.13-r8169-enable-SG-TSO-on-selected-chip-versions-per-de.patch +++ /dev/null @@ -1,52 +0,0 @@ -From b8bf38440ba94e8ed8e2ae55c5dfb0276d30e843 Mon Sep 17 00:00:00 2001 -From: Heiner Kallweit -Date: Thu, 10 Oct 2024 12:58:02 +0200 -Subject: [PATCH] r8169: enable SG/TSO on selected chip versions per default - -Due to problem reports in the past SG and TSO/TSO6 are disabled per -default. It's not fully clear which chip versions are affected, so we -may impact also users of unaffected chip versions, unless they know -how to use ethtool for enabling SG/TSO/TSO6. -Vendor drivers r8168/r8125 enable SG/TSO/TSO6 for selected chip -versions per default, I'd interpret this as confirmation that these -chip versions are unaffected. So let's do the same here. - -Signed-off-by: Heiner Kallweit -Reviewed-by: Simon Horman -Signed-off-by: David S. Miller ---- - drivers/net/ethernet/realtek/r8169_main.c | 16 +++++++++++----- - 1 file changed, 11 insertions(+), 5 deletions(-) - ---- a/drivers/net/ethernet/realtek/r8169_main.c -+++ b/drivers/net/ethernet/realtek/r8169_main.c -@@ -5524,11 +5524,6 @@ static int rtl_init_one(struct pci_dev * - - dev->features |= dev->hw_features; - -- /* There has been a number of reports that using SG/TSO results in -- * tx timeouts. However for a lot of people SG/TSO works fine. -- * Therefore disable both features by default, but allow users to -- * enable them. Use at own risk! -- */ - if (rtl_chip_supports_csum_v2(tp)) { - dev->hw_features |= NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO6; - netif_set_tso_max_size(dev, RTL_GSO_MAX_SIZE_V2); -@@ -5539,6 +5534,17 @@ static int rtl_init_one(struct pci_dev * - netif_set_tso_max_segs(dev, RTL_GSO_MAX_SEGS_V1); - } - -+ /* There has been a number of reports that using SG/TSO results in -+ * tx timeouts. However for a lot of people SG/TSO works fine. -+ * It's not fully clear which chip versions are affected. Vendor -+ * drivers enable SG/TSO for certain chip versions per default, -+ * let's mimic this here. On other chip versions users can -+ * use ethtool to enable SG/TSO, use at own risk! -+ */ -+ if (tp->mac_version >= RTL_GIGA_MAC_VER_46 && -+ tp->mac_version != RTL_GIGA_MAC_VER_61) -+ dev->features |= dev->hw_features; -+ - dev->hw_features |= NETIF_F_RXALL; - dev->hw_features |= NETIF_F_RXFCS; - diff --git a/target/linux/generic/backport-6.18/780-03-v6.13-r8169-implement-additional-ethtool-stats-ops.patch b/target/linux/generic/backport-6.18/780-03-v6.13-r8169-implement-additional-ethtool-stats-ops.patch deleted file mode 100644 index 594a8fae1a..0000000000 --- a/target/linux/generic/backport-6.18/780-03-v6.13-r8169-implement-additional-ethtool-stats-ops.patch +++ /dev/null @@ -1,130 +0,0 @@ -From e3fc5139bd8ffaa1498adc21be4e8ecbc6aed508 Mon Sep 17 00:00:00 2001 -From: Heiner Kallweit -Date: Sun, 13 Oct 2024 11:17:39 +0200 -Subject: [PATCH] r8169: implement additional ethtool stats ops - -This adds support for ethtool standard statistics, and makes use of the -extended hardware statistics being available from RTl8125. - -Signed-off-by: Heiner Kallweit -Reviewed-by: Simon Horman -Link: https://patch.msgid.link/58e0da73-a7dd-4be3-82ae-d5b3f9069bde@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/realtek/r8169_main.c | 82 +++++++++++++++++++++++ - 1 file changed, 82 insertions(+) - ---- a/drivers/net/ethernet/realtek/r8169_main.c -+++ b/drivers/net/ethernet/realtek/r8169_main.c -@@ -2160,6 +2160,19 @@ static void rtl8169_get_ringparam(struct - data->tx_pending = NUM_TX_DESC; - } - -+static void rtl8169_get_pause_stats(struct net_device *dev, -+ struct ethtool_pause_stats *pause_stats) -+{ -+ struct rtl8169_private *tp = netdev_priv(dev); -+ -+ if (!rtl_is_8125(tp)) -+ return; -+ -+ rtl8169_update_counters(tp); -+ pause_stats->tx_pause_frames = le32_to_cpu(tp->counters->tx_pause_on); -+ pause_stats->rx_pause_frames = le32_to_cpu(tp->counters->rx_pause_on); -+} -+ - static void rtl8169_get_pauseparam(struct net_device *dev, - struct ethtool_pauseparam *data) - { -@@ -2186,6 +2199,69 @@ static int rtl8169_set_pauseparam(struct - return 0; - } - -+static void rtl8169_get_eth_mac_stats(struct net_device *dev, -+ struct ethtool_eth_mac_stats *mac_stats) -+{ -+ struct rtl8169_private *tp = netdev_priv(dev); -+ -+ rtl8169_update_counters(tp); -+ -+ mac_stats->FramesTransmittedOK = -+ le64_to_cpu(tp->counters->tx_packets); -+ mac_stats->SingleCollisionFrames = -+ le32_to_cpu(tp->counters->tx_one_collision); -+ mac_stats->MultipleCollisionFrames = -+ le32_to_cpu(tp->counters->tx_multi_collision); -+ mac_stats->FramesReceivedOK = -+ le64_to_cpu(tp->counters->rx_packets); -+ mac_stats->AlignmentErrors = -+ le16_to_cpu(tp->counters->align_errors); -+ mac_stats->FramesLostDueToIntMACXmitError = -+ le64_to_cpu(tp->counters->tx_errors); -+ mac_stats->BroadcastFramesReceivedOK = -+ le64_to_cpu(tp->counters->rx_broadcast); -+ mac_stats->MulticastFramesReceivedOK = -+ le32_to_cpu(tp->counters->rx_multicast); -+ -+ if (!rtl_is_8125(tp)) -+ return; -+ -+ mac_stats->AlignmentErrors = -+ le32_to_cpu(tp->counters->align_errors32); -+ mac_stats->OctetsTransmittedOK = -+ le64_to_cpu(tp->counters->tx_octets); -+ mac_stats->LateCollisions = -+ le32_to_cpu(tp->counters->tx_late_collision); -+ mac_stats->FramesAbortedDueToXSColls = -+ le32_to_cpu(tp->counters->tx_aborted32); -+ mac_stats->OctetsReceivedOK = -+ le64_to_cpu(tp->counters->rx_octets); -+ mac_stats->FramesLostDueToIntMACRcvError = -+ le32_to_cpu(tp->counters->rx_mac_error); -+ mac_stats->MulticastFramesXmittedOK = -+ le64_to_cpu(tp->counters->tx_multicast64); -+ mac_stats->BroadcastFramesXmittedOK = -+ le64_to_cpu(tp->counters->tx_broadcast64); -+ mac_stats->MulticastFramesReceivedOK = -+ le64_to_cpu(tp->counters->rx_multicast64); -+ mac_stats->FrameTooLongErrors = -+ le32_to_cpu(tp->counters->rx_frame_too_long); -+} -+ -+static void rtl8169_get_eth_ctrl_stats(struct net_device *dev, -+ struct ethtool_eth_ctrl_stats *ctrl_stats) -+{ -+ struct rtl8169_private *tp = netdev_priv(dev); -+ -+ if (!rtl_is_8125(tp)) -+ return; -+ -+ rtl8169_update_counters(tp); -+ -+ ctrl_stats->UnsupportedOpcodesReceived = -+ le32_to_cpu(tp->counters->rx_unknown_opcode); -+} -+ - static const struct ethtool_ops rtl8169_ethtool_ops = { - .supported_coalesce_params = ETHTOOL_COALESCE_USECS | - ETHTOOL_COALESCE_MAX_FRAMES, -@@ -2207,8 +2283,11 @@ static const struct ethtool_ops rtl8169_ - .get_link_ksettings = phy_ethtool_get_link_ksettings, - .set_link_ksettings = phy_ethtool_set_link_ksettings, - .get_ringparam = rtl8169_get_ringparam, -+ .get_pause_stats = rtl8169_get_pause_stats, - .get_pauseparam = rtl8169_get_pauseparam, - .set_pauseparam = rtl8169_set_pauseparam, -+ .get_eth_mac_stats = rtl8169_get_eth_mac_stats, -+ .get_eth_ctrl_stats = rtl8169_get_eth_ctrl_stats, - }; - - static enum mac_version rtl8169_get_mac_version(u16 xid, bool gmii) -@@ -3926,6 +4005,9 @@ static void rtl_hw_start_8125(struct rtl - break; - } - -+ /* enable extended tally counter */ -+ r8168_mac_ocp_modify(tp, 0xea84, 0, BIT(1) | BIT(0)); -+ - rtl_hw_config(tp); - } - diff --git a/target/linux/generic/backport-6.18/780-04-v6.13-r8169-don-t-take-RTNL-lock-in-rtl_task.patch b/target/linux/generic/backport-6.18/780-04-v6.13-r8169-don-t-take-RTNL-lock-in-rtl_task.patch deleted file mode 100644 index a125ebb6cd..0000000000 --- a/target/linux/generic/backport-6.18/780-04-v6.13-r8169-don-t-take-RTNL-lock-in-rtl_task.patch +++ /dev/null @@ -1,50 +0,0 @@ -From ac48430368c1a4f4e6c2fa92243b4b93fd25bee4 Mon Sep 17 00:00:00 2001 -From: Heiner Kallweit -Date: Wed, 16 Oct 2024 22:05:57 +0200 -Subject: [PATCH] r8169: don't take RTNL lock in rtl_task() - -There's not really a benefit here in taking the RTNL lock. The task -handler does exception handling only, so we're in trouble anyway when -we come here, and there's no need to protect against e.g. a parallel -ethtool call. -A benefit of removing the RTNL lock here is that we now can -synchronously cancel the workqueue from a context holding the RTNL mutex. - -Signed-off-by: Heiner Kallweit -Signed-off-by: Andrew Lunn ---- - drivers/net/ethernet/realtek/r8169_main.c | 8 ++------ - 1 file changed, 2 insertions(+), 6 deletions(-) - ---- a/drivers/net/ethernet/realtek/r8169_main.c -+++ b/drivers/net/ethernet/realtek/r8169_main.c -@@ -4833,10 +4833,8 @@ static void rtl_task(struct work_struct - container_of(work, struct rtl8169_private, wk.work); - int ret; - -- rtnl_lock(); -- - if (!test_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags)) -- goto out_unlock; -+ return; - - if (test_and_clear_bit(RTL_FLAG_TASK_TX_TIMEOUT, tp->wk.flags)) { - /* if chip isn't accessible, reset bus to revive it */ -@@ -4845,7 +4843,7 @@ static void rtl_task(struct work_struct - if (ret < 0) { - netdev_err(tp->dev, "Can't reset secondary PCI bus, detach NIC\n"); - netif_device_detach(tp->dev); -- goto out_unlock; -+ return; - } - } - -@@ -4864,8 +4862,6 @@ reset: - } else if (test_and_clear_bit(RTL_FLAG_TASK_RESET_NO_QUEUE_WAKE, tp->wk.flags)) { - rtl_reset_work(tp); - } --out_unlock: -- rtnl_unlock(); - } - - static int rtl8169_poll(struct napi_struct *napi, int budget) diff --git a/target/linux/generic/backport-6.18/780-05-v6.13-replace-custom-flag-with-disable_work-et-al.patch b/target/linux/generic/backport-6.18/780-05-v6.13-replace-custom-flag-with-disable_work-et-al.patch deleted file mode 100644 index 49e274a5e2..0000000000 --- a/target/linux/generic/backport-6.18/780-05-v6.13-replace-custom-flag-with-disable_work-et-al.patch +++ /dev/null @@ -1,94 +0,0 @@ -From e2015942e90a021151a5751776f35830ba063be7 Mon Sep 17 00:00:00 2001 -From: Heiner Kallweit -Date: Wed, 16 Oct 2024 22:06:53 +0200 -Subject: [PATCH] r8169: replace custom flag with disable_work() et al - -So far we use a custom flag to define when a task can be scheduled and -when not. Let's use the standard mechanism with disable_work() et al -instead. -Note that in rtl8169_close() we can remove the call to cancel_work() -because we now call disable_work_sync() in rtl8169_down() already. - -Signed-off-by: Heiner Kallweit -Signed-off-by: Andrew Lunn ---- - drivers/net/ethernet/realtek/r8169_main.c | 18 ++++++------------ - 1 file changed, 6 insertions(+), 12 deletions(-) - ---- a/drivers/net/ethernet/realtek/r8169_main.c -+++ b/drivers/net/ethernet/realtek/r8169_main.c -@@ -619,7 +619,6 @@ struct rtl8169_tc_offsets { - }; - - enum rtl_flag { -- RTL_FLAG_TASK_ENABLED = 0, - RTL_FLAG_TASK_RESET_PENDING, - RTL_FLAG_TASK_RESET_NO_QUEUE_WAKE, - RTL_FLAG_TASK_TX_TIMEOUT, -@@ -2505,11 +2504,9 @@ u16 rtl8168h_2_get_adc_bias_ioffset(stru - - static void rtl_schedule_task(struct rtl8169_private *tp, enum rtl_flag flag) - { -- if (!test_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags)) -- return; -- - set_bit(flag, tp->wk.flags); -- schedule_work(&tp->wk.work); -+ if (!schedule_work(&tp->wk.work)) -+ clear_bit(flag, tp->wk.flags); - } - - static void rtl8169_init_phy(struct rtl8169_private *tp) -@@ -4833,9 +4830,6 @@ static void rtl_task(struct work_struct - container_of(work, struct rtl8169_private, wk.work); - int ret; - -- if (!test_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags)) -- return; -- - if (test_and_clear_bit(RTL_FLAG_TASK_TX_TIMEOUT, tp->wk.flags)) { - /* if chip isn't accessible, reset bus to revive it */ - if (RTL_R32(tp, TxConfig) == ~0) { -@@ -4919,6 +4913,7 @@ static int r8169_phy_connect(struct rtl8 - - static void rtl8169_down(struct rtl8169_private *tp) - { -+ disable_work_sync(&tp->wk.work); - /* Clear all task flags */ - bitmap_zero(tp->wk.flags, RTL_FLAG_MAX); - -@@ -4947,7 +4942,7 @@ static void rtl8169_up(struct rtl8169_pr - phy_resume(tp->phydev); - rtl8169_init_phy(tp); - napi_enable(&tp->napi); -- set_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags); -+ enable_work(&tp->wk.work); - rtl_reset_work(tp); - - phy_start(tp->phydev); -@@ -4964,8 +4959,6 @@ static int rtl8169_close(struct net_devi - rtl8169_down(tp); - rtl8169_rx_clear(tp); - -- cancel_work(&tp->wk.work); -- - free_irq(tp->irq, tp); - - phy_disconnect(tp->phydev); -@@ -5199,7 +5192,7 @@ static void rtl_remove_one(struct pci_de - if (pci_dev_run_wake(pdev)) - pm_runtime_get_noresume(&pdev->dev); - -- cancel_work_sync(&tp->wk.work); -+ disable_work_sync(&tp->wk.work); - - if (IS_ENABLED(CONFIG_R8169_LEDS)) - r8169_remove_leds(tp->leds); -@@ -5577,6 +5570,7 @@ static int rtl_init_one(struct pci_dev * - tp->irq = pci_irq_vector(pdev, 0); - - INIT_WORK(&tp->wk.work, rtl_task); -+ disable_work(&tp->wk.work); - - rtl_init_mac_address(tp); - diff --git a/target/linux/generic/backport-6.18/780-06-v6.13-r8169-avoid-duplicated-messages-if-loading-firmware-.patch b/target/linux/generic/backport-6.18/780-06-v6.13-r8169-avoid-duplicated-messages-if-loading-firmware-.patch deleted file mode 100644 index 6430d32252..0000000000 --- a/target/linux/generic/backport-6.18/780-06-v6.13-r8169-avoid-duplicated-messages-if-loading-firmware-.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 1c105bacb160b5918e917ab811552b7be69fc69c Mon Sep 17 00:00:00 2001 -From: Heiner Kallweit -Date: Wed, 16 Oct 2024 22:29:39 +0200 -Subject: [PATCH] r8169: avoid duplicated messages if loading firmware fails - and switch to warn level - -In case of a problem with firmware loading we inform at the driver level, -in addition the firmware load code itself issues warnings. Therefore -switch to firmware_request_nowarn() to avoid duplicated error messages. -In addition switch to warn level because the firmware is optional and -typically just fixes compatibility issues. - -Signed-off-by: Heiner Kallweit -Reviewed-by: Simon Horman -Message-ID: -Signed-off-by: Andrew Lunn ---- - drivers/net/ethernet/realtek/r8169_firmware.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - ---- a/drivers/net/ethernet/realtek/r8169_firmware.c -+++ b/drivers/net/ethernet/realtek/r8169_firmware.c -@@ -215,7 +215,7 @@ int rtl_fw_request_firmware(struct rtl_f - { - int rc; - -- rc = request_firmware(&rtl_fw->fw, rtl_fw->fw_name, rtl_fw->dev); -+ rc = firmware_request_nowarn(&rtl_fw->fw, rtl_fw->fw_name, rtl_fw->dev); - if (rc < 0) - goto out; - -@@ -227,7 +227,7 @@ int rtl_fw_request_firmware(struct rtl_f - - return 0; - out: -- dev_err(rtl_fw->dev, "Unable to load firmware %s (%d)\n", -- rtl_fw->fw_name, rc); -+ dev_warn(rtl_fw->dev, "Unable to load firmware %s (%d)\n", -+ rtl_fw->fw_name, rc); - return rc; - } diff --git a/target/linux/generic/backport-6.18/780-07-v6.13-r8169-remove-rtl_dash_loop_wait_high-low.patch b/target/linux/generic/backport-6.18/780-07-v6.13-r8169-remove-rtl_dash_loop_wait_high-low.patch deleted file mode 100644 index bc8f979c20..0000000000 --- a/target/linux/generic/backport-6.18/780-07-v6.13-r8169-remove-rtl_dash_loop_wait_high-low.patch +++ /dev/null @@ -1,82 +0,0 @@ -From d64113c6bb5ea5a70b7c9c3a6bcadef307638187 Mon Sep 17 00:00:00 2001 -From: Heiner Kallweit -Date: Wed, 16 Oct 2024 22:31:10 +0200 -Subject: [PATCH] r8169: remove rtl_dash_loop_wait_high/low - -Remove rtl_dash_loop_wait_high/low to simplify the code. - -Signed-off-by: Heiner Kallweit -Reviewed-by: Simon Horman -Message-ID: -Signed-off-by: Andrew Lunn ---- - drivers/net/ethernet/realtek/r8169_main.c | 35 ++++++----------------- - 1 file changed, 8 insertions(+), 27 deletions(-) - ---- a/drivers/net/ethernet/realtek/r8169_main.c -+++ b/drivers/net/ethernet/realtek/r8169_main.c -@@ -1348,40 +1348,19 @@ static void rtl8168ep_stop_cmac(struct r - RTL_W8(tp, IBCR0, RTL_R8(tp, IBCR0) & ~0x01); - } - --static void rtl_dash_loop_wait(struct rtl8169_private *tp, -- const struct rtl_cond *c, -- unsigned long usecs, int n, bool high) --{ -- if (!tp->dash_enabled) -- return; -- rtl_loop_wait(tp, c, usecs, n, high); --} -- --static void rtl_dash_loop_wait_high(struct rtl8169_private *tp, -- const struct rtl_cond *c, -- unsigned long d, int n) --{ -- rtl_dash_loop_wait(tp, c, d, n, true); --} -- --static void rtl_dash_loop_wait_low(struct rtl8169_private *tp, -- const struct rtl_cond *c, -- unsigned long d, int n) --{ -- rtl_dash_loop_wait(tp, c, d, n, false); --} -- - static void rtl8168dp_driver_start(struct rtl8169_private *tp) - { - r8168dp_oob_notify(tp, OOB_CMD_DRIVER_START); -- rtl_dash_loop_wait_high(tp, &rtl_dp_ocp_read_cond, 10000, 10); -+ if (tp->dash_enabled) -+ rtl_loop_wait_high(tp, &rtl_dp_ocp_read_cond, 10000, 10); - } - - static void rtl8168ep_driver_start(struct rtl8169_private *tp) - { - r8168ep_ocp_write(tp, 0x01, 0x180, OOB_CMD_DRIVER_START); - r8168ep_ocp_write(tp, 0x01, 0x30, r8168ep_ocp_read(tp, 0x30) | 0x01); -- rtl_dash_loop_wait_high(tp, &rtl_ep_ocp_read_cond, 10000, 30); -+ if (tp->dash_enabled) -+ rtl_loop_wait_high(tp, &rtl_ep_ocp_read_cond, 10000, 30); - } - - static void rtl8168_driver_start(struct rtl8169_private *tp) -@@ -1395,7 +1374,8 @@ static void rtl8168_driver_start(struct - static void rtl8168dp_driver_stop(struct rtl8169_private *tp) - { - r8168dp_oob_notify(tp, OOB_CMD_DRIVER_STOP); -- rtl_dash_loop_wait_low(tp, &rtl_dp_ocp_read_cond, 10000, 10); -+ if (tp->dash_enabled) -+ rtl_loop_wait_low(tp, &rtl_dp_ocp_read_cond, 10000, 10); - } - - static void rtl8168ep_driver_stop(struct rtl8169_private *tp) -@@ -1403,7 +1383,8 @@ static void rtl8168ep_driver_stop(struct - rtl8168ep_stop_cmac(tp); - r8168ep_ocp_write(tp, 0x01, 0x180, OOB_CMD_DRIVER_STOP); - r8168ep_ocp_write(tp, 0x01, 0x30, r8168ep_ocp_read(tp, 0x30) | 0x01); -- rtl_dash_loop_wait_low(tp, &rtl_ep_ocp_read_cond, 10000, 10); -+ if (tp->dash_enabled) -+ rtl_loop_wait_low(tp, &rtl_ep_ocp_read_cond, 10000, 10); - } - - static void rtl8168_driver_stop(struct rtl8169_private *tp) diff --git a/target/linux/generic/backport-6.18/780-08-v6.13-r8169-enable-EEE-at-2.5G-per-default-on-RTL8125B.patch b/target/linux/generic/backport-6.18/780-08-v6.13-r8169-enable-EEE-at-2.5G-per-default-on-RTL8125B.patch deleted file mode 100644 index 4ec06cc601..0000000000 --- a/target/linux/generic/backport-6.18/780-08-v6.13-r8169-enable-EEE-at-2.5G-per-default-on-RTL8125B.patch +++ /dev/null @@ -1,28 +0,0 @@ -From c4e64095c00cb2de413cd6b90be047c273bcd491 Mon Sep 17 00:00:00 2001 -From: Heiner Kallweit -Date: Thu, 17 Oct 2024 22:27:44 +0200 -Subject: [PATCH] r8169: enable EEE at 2.5G per default on RTL8125B - -Register a6d/12 is shadowing register MDIO_AN_EEE_ADV2. So this line -disables advertisement of EEE at 2.5G. Latest vendor driver r8125 -doesn't do this (any longer?), so this mode seems to be safe. -EEE saves quite some energy, therefore enable this mode per default. - -Signed-off-by: Heiner Kallweit -Reviewed-by: Simon Horman -Message-ID: <95dd5a0c-09ea-4847-94d9-b7aa3063e8ff@gmail.com> -Signed-off-by: Andrew Lunn ---- - drivers/net/ethernet/realtek/r8169_phy_config.c | 1 - - 1 file changed, 1 deletion(-) - ---- a/drivers/net/ethernet/realtek/r8169_phy_config.c -+++ b/drivers/net/ethernet/realtek/r8169_phy_config.c -@@ -99,7 +99,6 @@ static void rtl8125a_config_eee_phy(stru - - static void rtl8125b_config_eee_phy(struct phy_device *phydev) - { -- phy_modify_paged(phydev, 0xa6d, 0x12, 0x0001, 0x0000); - phy_modify_paged(phydev, 0xa6d, 0x14, 0x0010, 0x0000); - phy_modify_paged(phydev, 0xa42, 0x14, 0x0080, 0x0000); - phy_modify_paged(phydev, 0xa4a, 0x11, 0x0200, 0x0000); diff --git a/target/linux/generic/backport-6.18/780-10-v6.13-r8169-fix-inconsistent-indenting-in-rtl8169_get_eth_.patch b/target/linux/generic/backport-6.18/780-10-v6.13-r8169-fix-inconsistent-indenting-in-rtl8169_get_eth_.patch deleted file mode 100644 index 41bab55366..0000000000 --- a/target/linux/generic/backport-6.18/780-10-v6.13-r8169-fix-inconsistent-indenting-in-rtl8169_get_eth_.patch +++ /dev/null @@ -1,30 +0,0 @@ -From b8bd8c44a266c9a7dcb907eab10fbb119e3f6494 Mon Sep 17 00:00:00 2001 -From: Heiner Kallweit -Date: Thu, 24 Oct 2024 22:48:59 +0200 -Subject: [PATCH] r8169: fix inconsistent indenting in - rtl8169_get_eth_mac_stats - -This fixes an inconsistent indenting introduced with e3fc5139bd8f -("r8169: implement additional ethtool stats ops"). - -Reported-by: kernel test robot -Closes: https://lore.kernel.org/oe-kbuild-all/202410220413.1gAxIJ4t-lkp@intel.com/ -Signed-off-by: Heiner Kallweit -Reviewed-by: Simon Horman -Link: https://patch.msgid.link/20fd6f39-3c1b-4af0-9adc-7d1f49728fad@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/realtek/r8169_main.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/net/ethernet/realtek/r8169_main.c -+++ b/drivers/net/ethernet/realtek/r8169_main.c -@@ -2224,7 +2224,7 @@ static void rtl8169_get_eth_mac_stats(st - le64_to_cpu(tp->counters->tx_broadcast64); - mac_stats->MulticastFramesReceivedOK = - le64_to_cpu(tp->counters->rx_multicast64); -- mac_stats->FrameTooLongErrors = -+ mac_stats->FrameTooLongErrors = - le32_to_cpu(tp->counters->rx_frame_too_long); - } - diff --git a/target/linux/generic/backport-6.18/780-11-v6.13-r8169-align-RTL8125-EEE-config-with-vendor-driver.patch b/target/linux/generic/backport-6.18/780-11-v6.13-r8169-align-RTL8125-EEE-config-with-vendor-driver.patch deleted file mode 100644 index de2be0165c..0000000000 --- a/target/linux/generic/backport-6.18/780-11-v6.13-r8169-align-RTL8125-EEE-config-with-vendor-driver.patch +++ /dev/null @@ -1,49 +0,0 @@ -From eb90f876b7961d702d7fc549e14614860f531e60 Mon Sep 17 00:00:00 2001 -From: Heiner Kallweit -Date: Thu, 31 Oct 2024 22:42:52 +0100 -Subject: [PATCH] r8169: align RTL8125 EEE config with vendor driver - -Align the EEE config for RTL8125A/RTL8125B with vendor driver r8125. -This should help to avoid compatibility issues. - -Signed-off-by: Heiner Kallweit -Link: https://patch.msgid.link/044c925e-8669-4b98-87df-95b4056f4f5f@gmail.com -Signed-off-by: Jakub Kicinski ---- - .../net/ethernet/realtek/r8169_phy_config.c | 18 ++++++++++++------ - 1 file changed, 12 insertions(+), 6 deletions(-) - ---- a/drivers/net/ethernet/realtek/r8169_phy_config.c -+++ b/drivers/net/ethernet/realtek/r8169_phy_config.c -@@ -89,19 +89,25 @@ static void rtl8168h_config_eee_phy(stru - phy_modify_paged(phydev, 0xa42, 0x14, 0x0000, 0x0080); - } - --static void rtl8125a_config_eee_phy(struct phy_device *phydev) -+static void rtl8125_common_config_eee_phy(struct phy_device *phydev) - { -- rtl8168h_config_eee_phy(phydev); -+ phy_modify_paged(phydev, 0xa6d, 0x14, 0x0010, 0x0000); -+ phy_modify_paged(phydev, 0xa42, 0x14, 0x0080, 0x0000); -+ phy_modify_paged(phydev, 0xa4a, 0x11, 0x0200, 0x0000); -+} - -+static void rtl8125a_config_eee_phy(struct phy_device *phydev) -+{ -+ rtl8168g_config_eee_phy(phydev); -+ /* disable EEE at 2.5Gbps */ - phy_modify_paged(phydev, 0xa6d, 0x12, 0x0001, 0x0000); -- phy_modify_paged(phydev, 0xa6d, 0x14, 0x0010, 0x0000); -+ rtl8125_common_config_eee_phy(phydev); - } - - static void rtl8125b_config_eee_phy(struct phy_device *phydev) - { -- phy_modify_paged(phydev, 0xa6d, 0x14, 0x0010, 0x0000); -- phy_modify_paged(phydev, 0xa42, 0x14, 0x0080, 0x0000); -- phy_modify_paged(phydev, 0xa4a, 0x11, 0x0200, 0x0000); -+ rtl8168g_config_eee_phy(phydev); -+ rtl8125_common_config_eee_phy(phydev); - } - - static void rtl8169s_hw_phy_config(struct rtl8169_private *tp, diff --git a/target/linux/generic/backport-6.18/780-12-v6.13-r8169-align-RTL8125-RTL8126-PHY-config-with-vendor-d.patch b/target/linux/generic/backport-6.18/780-12-v6.13-r8169-align-RTL8125-RTL8126-PHY-config-with-vendor-d.patch deleted file mode 100644 index a546c426b4..0000000000 --- a/target/linux/generic/backport-6.18/780-12-v6.13-r8169-align-RTL8125-RTL8126-PHY-config-with-vendor-d.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 4af2f60bf7378bd5c92b15a528d8c6c7d02bed6c Mon Sep 17 00:00:00 2001 -From: Heiner Kallweit -Date: Thu, 31 Oct 2024 22:43:45 +0100 -Subject: [PATCH] r8169: align RTL8125/RTL8126 PHY config with vendor driver - -This aligns some parameters with vendor driver r8125/r8126 to avoid -compatibility issues. Note that for RTL8125B there's no functional -change, just the open-coded version of the function is replaced. - -Signed-off-by: Heiner Kallweit -Link: https://patch.msgid.link/a8a9d896-fbe6-41f2-bf87-666567d3cdb3@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/realtek/r8169_phy_config.c | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - ---- a/drivers/net/ethernet/realtek/r8169_phy_config.c -+++ b/drivers/net/ethernet/realtek/r8169_phy_config.c -@@ -1073,8 +1073,8 @@ static void rtl8125b_hw_phy_config(struc - struct phy_device *phydev) - { - r8169_apply_firmware(tp); -+ rtl8168g_enable_gphy_10m(phydev); - -- phy_modify_paged(phydev, 0xa44, 0x11, 0x0000, 0x0800); - phy_modify_paged(phydev, 0xac4, 0x13, 0x00f0, 0x0090); - phy_modify_paged(phydev, 0xad3, 0x10, 0x0003, 0x0001); - -@@ -1113,6 +1113,7 @@ static void rtl8125d_hw_phy_config(struc - struct phy_device *phydev) - { - r8169_apply_firmware(tp); -+ rtl8168g_enable_gphy_10m(phydev); - rtl8125_legacy_force_mode(phydev); - rtl8168g_disable_aldps(phydev); - rtl8125b_config_eee_phy(phydev); -@@ -1122,6 +1123,9 @@ static void rtl8126a_hw_phy_config(struc - struct phy_device *phydev) - { - r8169_apply_firmware(tp); -+ rtl8168g_enable_gphy_10m(phydev); -+ rtl8125_legacy_force_mode(phydev); -+ rtl8168g_disable_aldps(phydev); - } - - void r8169_hw_phy_config(struct rtl8169_private *tp, struct phy_device *phydev, diff --git a/target/linux/generic/backport-6.18/780-13-v6.13-r8169-align-RTL8126-EEE-config-with-vendor-driver.patch b/target/linux/generic/backport-6.18/780-13-v6.13-r8169-align-RTL8126-EEE-config-with-vendor-driver.patch deleted file mode 100644 index 36c8041c94..0000000000 --- a/target/linux/generic/backport-6.18/780-13-v6.13-r8169-align-RTL8126-EEE-config-with-vendor-driver.patch +++ /dev/null @@ -1,25 +0,0 @@ -From a3d8520e6a19ab018da6c7fc22512c913697a829 Mon Sep 17 00:00:00 2001 -From: Heiner Kallweit -Date: Thu, 31 Oct 2024 22:44:36 +0100 -Subject: [PATCH] r8169: align RTL8126 EEE config with vendor driver - -Align the EEE config for RTL8126A with vendor driver r8126 to avoid -compatibility issues. - -Signed-off-by: Heiner Kallweit -Link: https://patch.msgid.link/71e4859e-4cd0-4b6b-b7fa-621d7721992f@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/realtek/r8169_phy_config.c | 1 + - 1 file changed, 1 insertion(+) - ---- a/drivers/net/ethernet/realtek/r8169_phy_config.c -+++ b/drivers/net/ethernet/realtek/r8169_phy_config.c -@@ -1126,6 +1126,7 @@ static void rtl8126a_hw_phy_config(struc - rtl8168g_enable_gphy_10m(phydev); - rtl8125_legacy_force_mode(phydev); - rtl8168g_disable_aldps(phydev); -+ rtl8125_common_config_eee_phy(phydev); - } - - void r8169_hw_phy_config(struct rtl8169_private *tp, struct phy_device *phydev, diff --git a/target/linux/generic/backport-6.18/780-14-v6.13-r8169-improve-initialization-of-RSS-registers-on-RTL.patch b/target/linux/generic/backport-6.18/780-14-v6.13-r8169-improve-initialization-of-RSS-registers-on-RTL.patch deleted file mode 100644 index d00b08e0fa..0000000000 --- a/target/linux/generic/backport-6.18/780-14-v6.13-r8169-improve-initialization-of-RSS-registers-on-RTL.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 2cd02f2fdd8a92e5b6b85ff64eab0fc549b30c07 Mon Sep 17 00:00:00 2001 -From: Heiner Kallweit -Date: Sat, 2 Nov 2024 14:49:01 +0100 -Subject: [PATCH] r8169: improve initialization of RSS registers on - RTL8125/RTL8126 - -Replace the register addresses with the names used in r8125/r8126 -vendor driver, and consider that RSS_CTRL_8125 is a 32 bit register. - -Signed-off-by: Heiner Kallweit -Link: https://patch.msgid.link/3bf2f340-b369-4174-97bf-fd38d4217492@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/realtek/r8169_main.c | 6 ++++-- - 1 file changed, 4 insertions(+), 2 deletions(-) - ---- a/drivers/net/ethernet/realtek/r8169_main.c -+++ b/drivers/net/ethernet/realtek/r8169_main.c -@@ -346,6 +346,8 @@ enum rtl8125_registers { - TxPoll_8125 = 0x90, - LEDSEL3 = 0x96, - MAC0_BKP = 0x19e0, -+ RSS_CTRL_8125 = 0x4500, -+ Q_NUM_CTRL_8125 = 0x4800, - EEE_TXIDLE_TIMER_8125 = 0x6048, - }; - -@@ -3788,8 +3790,8 @@ static void rtl_hw_start_8125_common(str - rtl_pcie_state_l2l3_disable(tp); - - RTL_W16(tp, 0x382, 0x221b); -- RTL_W8(tp, 0x4500, 0); -- RTL_W16(tp, 0x4800, 0); -+ RTL_W32(tp, RSS_CTRL_8125, 0); -+ RTL_W16(tp, Q_NUM_CTRL_8125, 0); - - /* disable UPS */ - r8168_mac_ocp_modify(tp, 0xd40a, 0x0010, 0x0000); diff --git a/target/linux/generic/backport-6.18/780-15-v6.13-r8169-remove-leftover-locks-after-reverted-change.patch b/target/linux/generic/backport-6.18/780-15-v6.13-r8169-remove-leftover-locks-after-reverted-change.patch deleted file mode 100644 index 19bcf08d55..0000000000 --- a/target/linux/generic/backport-6.18/780-15-v6.13-r8169-remove-leftover-locks-after-reverted-change.patch +++ /dev/null @@ -1,113 +0,0 @@ -From 83cb4b470c66b37b19a347a35cea01e0cbdd258d Mon Sep 17 00:00:00 2001 -From: Heiner Kallweit -Date: Mon, 4 Nov 2024 23:16:20 +0100 -Subject: [PATCH] r8169: remove leftover locks after reverted change - -After e31a9fedc7d8 ("Revert "r8169: disable ASPM during NAPI poll"") -these locks aren't needed any longer. - -Signed-off-by: Heiner Kallweit -Link: https://patch.msgid.link/680f2606-ac7d-4ced-8694-e5033855da9b@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/realtek/r8169_main.c | 29 ++--------------------- - 1 file changed, 2 insertions(+), 27 deletions(-) - ---- a/drivers/net/ethernet/realtek/r8169_main.c -+++ b/drivers/net/ethernet/realtek/r8169_main.c -@@ -661,13 +661,9 @@ struct rtl8169_private { - struct work_struct work; - } wk; - -- raw_spinlock_t config25_lock; - raw_spinlock_t mac_ocp_lock; - struct mutex led_lock; /* serialize LED ctrl RMW access */ - -- raw_spinlock_t cfg9346_usage_lock; -- int cfg9346_usage_count; -- - unsigned supports_gmii:1; - unsigned aspm_manageable:1; - unsigned dash_enabled:1; -@@ -721,22 +717,12 @@ static inline struct device *tp_to_dev(s - - static void rtl_lock_config_regs(struct rtl8169_private *tp) - { -- unsigned long flags; -- -- raw_spin_lock_irqsave(&tp->cfg9346_usage_lock, flags); -- if (!--tp->cfg9346_usage_count) -- RTL_W8(tp, Cfg9346, Cfg9346_Lock); -- raw_spin_unlock_irqrestore(&tp->cfg9346_usage_lock, flags); -+ RTL_W8(tp, Cfg9346, Cfg9346_Lock); - } - - static void rtl_unlock_config_regs(struct rtl8169_private *tp) - { -- unsigned long flags; -- -- raw_spin_lock_irqsave(&tp->cfg9346_usage_lock, flags); -- if (!tp->cfg9346_usage_count++) -- RTL_W8(tp, Cfg9346, Cfg9346_Unlock); -- raw_spin_unlock_irqrestore(&tp->cfg9346_usage_lock, flags); -+ RTL_W8(tp, Cfg9346, Cfg9346_Unlock); - } - - static void rtl_pci_commit(struct rtl8169_private *tp) -@@ -747,24 +733,18 @@ static void rtl_pci_commit(struct rtl816 - - static void rtl_mod_config2(struct rtl8169_private *tp, u8 clear, u8 set) - { -- unsigned long flags; - u8 val; - -- raw_spin_lock_irqsave(&tp->config25_lock, flags); - val = RTL_R8(tp, Config2); - RTL_W8(tp, Config2, (val & ~clear) | set); -- raw_spin_unlock_irqrestore(&tp->config25_lock, flags); - } - - static void rtl_mod_config5(struct rtl8169_private *tp, u8 clear, u8 set) - { -- unsigned long flags; - u8 val; - -- raw_spin_lock_irqsave(&tp->config25_lock, flags); - val = RTL_R8(tp, Config5); - RTL_W8(tp, Config5, (val & ~clear) | set); -- raw_spin_unlock_irqrestore(&tp->config25_lock, flags); - } - - static bool rtl_is_8125(struct rtl8169_private *tp) -@@ -1570,7 +1550,6 @@ static void __rtl8169_set_wol(struct rtl - { WAKE_MAGIC, Config3, MagicPacket } - }; - unsigned int i, tmp = ARRAY_SIZE(cfg); -- unsigned long flags; - u8 options; - - rtl_unlock_config_regs(tp); -@@ -1589,14 +1568,12 @@ static void __rtl8169_set_wol(struct rtl - r8168_mac_ocp_modify(tp, 0xc0b6, BIT(0), 0); - } - -- raw_spin_lock_irqsave(&tp->config25_lock, flags); - for (i = 0; i < tmp; i++) { - options = RTL_R8(tp, cfg[i].reg) & ~cfg[i].mask; - if (wolopts & cfg[i].opt) - options |= cfg[i].mask; - RTL_W8(tp, cfg[i].reg, options); - } -- raw_spin_unlock_irqrestore(&tp->config25_lock, flags); - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_02 ... RTL_GIGA_MAC_VER_06: -@@ -5477,8 +5454,6 @@ static int rtl_init_one(struct pci_dev * - tp->supports_gmii = ent->driver_data == RTL_CFG_NO_GBIT ? 0 : 1; - tp->ocp_base = OCP_STD_PHY_BASE; - -- raw_spin_lock_init(&tp->cfg9346_usage_lock); -- raw_spin_lock_init(&tp->config25_lock); - raw_spin_lock_init(&tp->mac_ocp_lock); - mutex_init(&tp->led_lock); - diff --git a/target/linux/generic/backport-6.18/780-16-v6.13-r8169-improve-__rtl8169_set_wol.patch b/target/linux/generic/backport-6.18/780-16-v6.13-r8169-improve-__rtl8169_set_wol.patch deleted file mode 100644 index 3158ac5171..0000000000 --- a/target/linux/generic/backport-6.18/780-16-v6.13-r8169-improve-__rtl8169_set_wol.patch +++ /dev/null @@ -1,108 +0,0 @@ -From c507e96b5763b36b63ad50ad804341f72ea000e4 Mon Sep 17 00:00:00 2001 -From: Heiner Kallweit -Date: Wed, 6 Nov 2024 17:55:45 +0100 -Subject: [PATCH] r8169: improve __rtl8169_set_wol - -Add helper r8169_mod_reg8_cond() what allows to significantly simplify -__rtl8169_set_wol(). - -Signed-off-by: Heiner Kallweit -Reviewed-by: Simon Horman -Link: https://patch.msgid.link/697b197a-8eac-40c6-8847-27093cacec36@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/realtek/r8169_main.c | 55 ++++++++++------------- - 1 file changed, 24 insertions(+), 31 deletions(-) - ---- a/drivers/net/ethernet/realtek/r8169_main.c -+++ b/drivers/net/ethernet/realtek/r8169_main.c -@@ -747,6 +747,20 @@ static void rtl_mod_config5(struct rtl81 - RTL_W8(tp, Config5, (val & ~clear) | set); - } - -+static void r8169_mod_reg8_cond(struct rtl8169_private *tp, int reg, -+ u8 bits, bool cond) -+{ -+ u8 val, old_val; -+ -+ old_val = RTL_R8(tp, reg); -+ if (cond) -+ val = old_val | bits; -+ else -+ val = old_val & ~bits; -+ if (val != old_val) -+ RTL_W8(tp, reg, val); -+} -+ - static bool rtl_is_8125(struct rtl8169_private *tp) - { - return tp->mac_version >= RTL_GIGA_MAC_VER_61; -@@ -1537,58 +1551,37 @@ static void rtl8169_get_wol(struct net_d - - static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts) - { -- static const struct { -- u32 opt; -- u16 reg; -- u8 mask; -- } cfg[] = { -- { WAKE_PHY, Config3, LinkUp }, -- { WAKE_UCAST, Config5, UWF }, -- { WAKE_BCAST, Config5, BWF }, -- { WAKE_MCAST, Config5, MWF }, -- { WAKE_ANY, Config5, LanWake }, -- { WAKE_MAGIC, Config3, MagicPacket } -- }; -- unsigned int i, tmp = ARRAY_SIZE(cfg); -- u8 options; -- - rtl_unlock_config_regs(tp); - - if (rtl_is_8168evl_up(tp)) { -- tmp--; - if (wolopts & WAKE_MAGIC) - rtl_eri_set_bits(tp, 0x0dc, MagicPacket_v2); - else - rtl_eri_clear_bits(tp, 0x0dc, MagicPacket_v2); - } else if (rtl_is_8125(tp)) { -- tmp--; - if (wolopts & WAKE_MAGIC) - r8168_mac_ocp_modify(tp, 0xc0b6, 0, BIT(0)); - else - r8168_mac_ocp_modify(tp, 0xc0b6, BIT(0), 0); -+ } else { -+ r8169_mod_reg8_cond(tp, Config3, MagicPacket, -+ wolopts & WAKE_MAGIC); - } - -- for (i = 0; i < tmp; i++) { -- options = RTL_R8(tp, cfg[i].reg) & ~cfg[i].mask; -- if (wolopts & cfg[i].opt) -- options |= cfg[i].mask; -- RTL_W8(tp, cfg[i].reg, options); -- } -+ r8169_mod_reg8_cond(tp, Config3, LinkUp, wolopts & WAKE_PHY); -+ r8169_mod_reg8_cond(tp, Config5, UWF, wolopts & WAKE_UCAST); -+ r8169_mod_reg8_cond(tp, Config5, BWF, wolopts & WAKE_BCAST); -+ r8169_mod_reg8_cond(tp, Config5, MWF, wolopts & WAKE_MCAST); -+ r8169_mod_reg8_cond(tp, Config5, LanWake, wolopts); - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_02 ... RTL_GIGA_MAC_VER_06: -- options = RTL_R8(tp, Config1) & ~PMEnable; -- if (wolopts) -- options |= PMEnable; -- RTL_W8(tp, Config1, options); -+ r8169_mod_reg8_cond(tp, Config1, PMEnable, wolopts); - break; - case RTL_GIGA_MAC_VER_34: - case RTL_GIGA_MAC_VER_37: - case RTL_GIGA_MAC_VER_39 ... RTL_GIGA_MAC_VER_66: -- if (wolopts) -- rtl_mod_config2(tp, 0, PME_SIGNAL); -- else -- rtl_mod_config2(tp, PME_SIGNAL, 0); -+ r8169_mod_reg8_cond(tp, Config2, PME_SIGNAL, wolopts); - break; - default: - break; diff --git a/target/linux/generic/backport-6.18/780-17-v6.13-r8169-improve-rtl_set_d3_pll_down.patch b/target/linux/generic/backport-6.18/780-17-v6.13-r8169-improve-rtl_set_d3_pll_down.patch deleted file mode 100644 index ede589ee73..0000000000 --- a/target/linux/generic/backport-6.18/780-17-v6.13-r8169-improve-rtl_set_d3_pll_down.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 330dc2297c82953dff402e0b4176a5383a618538 Mon Sep 17 00:00:00 2001 -From: Heiner Kallweit -Date: Wed, 6 Nov 2024 17:56:28 +0100 -Subject: [PATCH] r8169: improve rtl_set_d3_pll_down - -Make use of new helper r8169_mod_reg8_cond() and move from a switch() -to an if() clause. Benefit is that we don't have to touch this piece of -code each time support for a new chip version is added. - -Signed-off-by: Heiner Kallweit -Reviewed-by: Simon Horman -Link: https://patch.msgid.link/e1ccdb85-a4ed-4800-89c2-89770ff06452@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/realtek/r8169_main.c | 18 +++++------------- - 1 file changed, 5 insertions(+), 13 deletions(-) - ---- a/drivers/net/ethernet/realtek/r8169_main.c -+++ b/drivers/net/ethernet/realtek/r8169_main.c -@@ -1430,19 +1430,11 @@ static enum rtl_dash_type rtl_get_dash_t - - static void rtl_set_d3_pll_down(struct rtl8169_private *tp, bool enable) - { -- switch (tp->mac_version) { -- case RTL_GIGA_MAC_VER_25 ... RTL_GIGA_MAC_VER_26: -- case RTL_GIGA_MAC_VER_29 ... RTL_GIGA_MAC_VER_30: -- case RTL_GIGA_MAC_VER_32 ... RTL_GIGA_MAC_VER_37: -- case RTL_GIGA_MAC_VER_39 ... RTL_GIGA_MAC_VER_66: -- if (enable) -- RTL_W8(tp, PMCH, RTL_R8(tp, PMCH) & ~D3_NO_PLL_DOWN); -- else -- RTL_W8(tp, PMCH, RTL_R8(tp, PMCH) | D3_NO_PLL_DOWN); -- break; -- default: -- break; -- } -+ if (tp->mac_version >= RTL_GIGA_MAC_VER_25 && -+ tp->mac_version != RTL_GIGA_MAC_VER_28 && -+ tp->mac_version != RTL_GIGA_MAC_VER_31 && -+ tp->mac_version != RTL_GIGA_MAC_VER_38) -+ r8169_mod_reg8_cond(tp, PMCH, D3_NO_PLL_DOWN, !enable); - } - - static void rtl_reset_packet_filter(struct rtl8169_private *tp) diff --git a/target/linux/generic/backport-6.18/780-18-v6.13-r8169-align-WAKE_PHY-handling-with-r8125-r8126-vendo.patch b/target/linux/generic/backport-6.18/780-18-v6.13-r8169-align-WAKE_PHY-handling-with-r8125-r8126-vendo.patch deleted file mode 100644 index ceb8c1239f..0000000000 --- a/target/linux/generic/backport-6.18/780-18-v6.13-r8169-align-WAKE_PHY-handling-with-r8125-r8126-vendo.patch +++ /dev/null @@ -1,29 +0,0 @@ -From e3e9e9039fa6ae885c7d5c954d7b9f105fa23e8f Mon Sep 17 00:00:00 2001 -From: Heiner Kallweit -Date: Wed, 6 Nov 2024 17:57:08 +0100 -Subject: [PATCH] r8169: align WAKE_PHY handling with r8125/r8126 vendor - drivers - -Vendor drivers r8125/r8126 apply this additional magic setting when -enabling WAKE_PHY, so do the same here. - -Signed-off-by: Heiner Kallweit -Reviewed-by: Simon Horman -Link: https://patch.msgid.link/51130715-45be-4db5-abb7-05d87e1f5df9@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/realtek/r8169_main.c | 3 +++ - 1 file changed, 3 insertions(+) - ---- a/drivers/net/ethernet/realtek/r8169_main.c -+++ b/drivers/net/ethernet/realtek/r8169_main.c -@@ -1561,6 +1561,9 @@ static void __rtl8169_set_wol(struct rtl - } - - r8169_mod_reg8_cond(tp, Config3, LinkUp, wolopts & WAKE_PHY); -+ if (rtl_is_8125(tp)) -+ r8168_mac_ocp_modify(tp, 0xe0c6, 0x3f, -+ wolopts & WAKE_PHY ? 0x13 : 0); - r8169_mod_reg8_cond(tp, Config5, UWF, wolopts & WAKE_UCAST); - r8169_mod_reg8_cond(tp, Config5, BWF, wolopts & WAKE_BCAST); - r8169_mod_reg8_cond(tp, Config5, MWF, wolopts & WAKE_MCAST); diff --git a/target/linux/generic/backport-6.18/780-19-v6.13-r8169-use-helper-r8169_mod_reg8_cond-to-simplify-rtl.patch b/target/linux/generic/backport-6.18/780-19-v6.13-r8169-use-helper-r8169_mod_reg8_cond-to-simplify-rtl.patch deleted file mode 100644 index d6332dfa14..0000000000 --- a/target/linux/generic/backport-6.18/780-19-v6.13-r8169-use-helper-r8169_mod_reg8_cond-to-simplify-rtl.patch +++ /dev/null @@ -1,117 +0,0 @@ -From 7a3bcd39ae1f0e3ab896d9df62339ab4297a0bfd Mon Sep 17 00:00:00 2001 -From: Heiner Kallweit -Date: Sat, 9 Nov 2024 23:12:12 +0100 -Subject: [PATCH] r8169: use helper r8169_mod_reg8_cond to simplify - rtl_jumbo_config - -Use recently added helper r8169_mod_reg8_cond() to simplify jumbo -mode configuration. - -Signed-off-by: Heiner Kallweit -Reviewed-by: Simon Horman -Link: https://patch.msgid.link/3df1d484-a02e-46e7-8f75-db5b428e422e@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/realtek/r8169_main.c | 77 ++++------------------- - 1 file changed, 11 insertions(+), 66 deletions(-) - ---- a/drivers/net/ethernet/realtek/r8169_main.c -+++ b/drivers/net/ethernet/realtek/r8169_main.c -@@ -2542,86 +2542,31 @@ static void rtl8169_init_ring_indexes(st - tp->dirty_tx = tp->cur_tx = tp->cur_rx = 0; - } - --static void r8168c_hw_jumbo_enable(struct rtl8169_private *tp) --{ -- RTL_W8(tp, Config3, RTL_R8(tp, Config3) | Jumbo_En0); -- RTL_W8(tp, Config4, RTL_R8(tp, Config4) | Jumbo_En1); --} -- --static void r8168c_hw_jumbo_disable(struct rtl8169_private *tp) --{ -- RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Jumbo_En0); -- RTL_W8(tp, Config4, RTL_R8(tp, Config4) & ~Jumbo_En1); --} -- --static void r8168dp_hw_jumbo_enable(struct rtl8169_private *tp) --{ -- RTL_W8(tp, Config3, RTL_R8(tp, Config3) | Jumbo_En0); --} -- --static void r8168dp_hw_jumbo_disable(struct rtl8169_private *tp) --{ -- RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Jumbo_En0); --} -- --static void r8168e_hw_jumbo_enable(struct rtl8169_private *tp) --{ -- RTL_W8(tp, MaxTxPacketSize, 0x24); -- RTL_W8(tp, Config3, RTL_R8(tp, Config3) | Jumbo_En0); -- RTL_W8(tp, Config4, RTL_R8(tp, Config4) | 0x01); --} -- --static void r8168e_hw_jumbo_disable(struct rtl8169_private *tp) --{ -- RTL_W8(tp, MaxTxPacketSize, 0x3f); -- RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Jumbo_En0); -- RTL_W8(tp, Config4, RTL_R8(tp, Config4) & ~0x01); --} -- --static void r8168b_1_hw_jumbo_enable(struct rtl8169_private *tp) --{ -- RTL_W8(tp, Config4, RTL_R8(tp, Config4) | (1 << 0)); --} -- --static void r8168b_1_hw_jumbo_disable(struct rtl8169_private *tp) --{ -- RTL_W8(tp, Config4, RTL_R8(tp, Config4) & ~(1 << 0)); --} -- - static void rtl_jumbo_config(struct rtl8169_private *tp) - { - bool jumbo = tp->dev->mtu > ETH_DATA_LEN; - int readrq = 4096; - -+ if (jumbo && tp->mac_version >= RTL_GIGA_MAC_VER_17 && -+ tp->mac_version <= RTL_GIGA_MAC_VER_26) -+ readrq = 512; -+ - rtl_unlock_config_regs(tp); - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_17: -- if (jumbo) { -- readrq = 512; -- r8168b_1_hw_jumbo_enable(tp); -- } else { -- r8168b_1_hw_jumbo_disable(tp); -- } -+ r8169_mod_reg8_cond(tp, Config4, BIT(0), jumbo); - break; - case RTL_GIGA_MAC_VER_18 ... RTL_GIGA_MAC_VER_26: -- if (jumbo) { -- readrq = 512; -- r8168c_hw_jumbo_enable(tp); -- } else { -- r8168c_hw_jumbo_disable(tp); -- } -+ r8169_mod_reg8_cond(tp, Config3, Jumbo_En0, jumbo); -+ r8169_mod_reg8_cond(tp, Config4, Jumbo_En1, jumbo); - break; - case RTL_GIGA_MAC_VER_28: -- if (jumbo) -- r8168dp_hw_jumbo_enable(tp); -- else -- r8168dp_hw_jumbo_disable(tp); -+ r8169_mod_reg8_cond(tp, Config3, Jumbo_En0, jumbo); - break; - case RTL_GIGA_MAC_VER_31 ... RTL_GIGA_MAC_VER_33: -- if (jumbo) -- r8168e_hw_jumbo_enable(tp); -- else -- r8168e_hw_jumbo_disable(tp); -+ RTL_W8(tp, MaxTxPacketSize, jumbo ? 0x24 : 0x3f); -+ r8169_mod_reg8_cond(tp, Config3, Jumbo_En0, jumbo); -+ r8169_mod_reg8_cond(tp, Config4, BIT(0), jumbo); - break; - default: - break; diff --git a/target/linux/generic/backport-6.18/780-20-v6.13-r8169-copy-vendor-driver-2.5G-5G-EEE-advertisement-c.patch b/target/linux/generic/backport-6.18/780-20-v6.13-r8169-copy-vendor-driver-2.5G-5G-EEE-advertisement-c.patch deleted file mode 100644 index fee9d95368..0000000000 --- a/target/linux/generic/backport-6.18/780-20-v6.13-r8169-copy-vendor-driver-2.5G-5G-EEE-advertisement-c.patch +++ /dev/null @@ -1,82 +0,0 @@ -From e340bff27e63ed61a1e9895bed546107859e48a7 Mon Sep 17 00:00:00 2001 -From: Heiner Kallweit -Date: Fri, 8 Nov 2024 08:08:24 +0100 -Subject: [PATCH] r8169: copy vendor driver 2.5G/5G EEE advertisement - constraints - -Vendor driver r8125 doesn't advertise 2.5G EEE on RTL8125A, and r8126 -doesn't advertise 5G EEE. Likely there are compatibility issues, -therefore do the same in r8169. -With this change we don't have to disable 2.5G EEE advertisement in -rtl8125a_config_eee_phy() any longer. -We use new phylib accessor phy_set_eee_broken() to mark the respective -EEE modes as broken. - -Signed-off-by: Heiner Kallweit -Link: https://patch.msgid.link/ce185e10-8a2f-4cf8-a49b-fd8fb3c3c8a1@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/realtek/r8169_main.c | 6 ++++++ - drivers/net/ethernet/realtek/r8169_phy_config.c | 16 ++++------------ - 2 files changed, 10 insertions(+), 12 deletions(-) - ---- a/drivers/net/ethernet/realtek/r8169_main.c -+++ b/drivers/net/ethernet/realtek/r8169_main.c -@@ -5253,6 +5253,11 @@ static int r8169_mdio_register(struct rt - phy_support_eee(tp->phydev); - phy_support_asym_pause(tp->phydev); - -+ /* mimic behavior of r8125/r8126 vendor drivers */ -+ if (tp->mac_version == RTL_GIGA_MAC_VER_61) -+ tp->phydev->eee_broken_modes |= MDIO_EEE_2_5GT; -+ tp->phydev->eee_broken_modes |= MDIO_EEE_5GT; -+ - /* PHY will be woken up in rtl_open() */ - phy_suspend(tp->phydev); - ---- a/drivers/net/ethernet/realtek/r8169_phy_config.c -+++ b/drivers/net/ethernet/realtek/r8169_phy_config.c -@@ -96,15 +96,7 @@ static void rtl8125_common_config_eee_ph - phy_modify_paged(phydev, 0xa4a, 0x11, 0x0200, 0x0000); - } - --static void rtl8125a_config_eee_phy(struct phy_device *phydev) --{ -- rtl8168g_config_eee_phy(phydev); -- /* disable EEE at 2.5Gbps */ -- phy_modify_paged(phydev, 0xa6d, 0x12, 0x0001, 0x0000); -- rtl8125_common_config_eee_phy(phydev); --} -- --static void rtl8125b_config_eee_phy(struct phy_device *phydev) -+static void rtl8125_config_eee_phy(struct phy_device *phydev) - { - rtl8168g_config_eee_phy(phydev); - rtl8125_common_config_eee_phy(phydev); -@@ -1066,7 +1058,7 @@ static void rtl8125a_2_hw_phy_config(str - rtl8168g_enable_gphy_10m(phydev); - - rtl8168g_disable_aldps(phydev); -- rtl8125a_config_eee_phy(phydev); -+ rtl8125_config_eee_phy(phydev); - } - - static void rtl8125b_hw_phy_config(struct rtl8169_private *tp, -@@ -1106,7 +1098,7 @@ static void rtl8125b_hw_phy_config(struc - - rtl8125_legacy_force_mode(phydev); - rtl8168g_disable_aldps(phydev); -- rtl8125b_config_eee_phy(phydev); -+ rtl8125_config_eee_phy(phydev); - } - - static void rtl8125d_hw_phy_config(struct rtl8169_private *tp, -@@ -1116,7 +1108,7 @@ static void rtl8125d_hw_phy_config(struc - rtl8168g_enable_gphy_10m(phydev); - rtl8125_legacy_force_mode(phydev); - rtl8168g_disable_aldps(phydev); -- rtl8125b_config_eee_phy(phydev); -+ rtl8125_config_eee_phy(phydev); - } - - static void rtl8126a_hw_phy_config(struct rtl8169_private *tp, diff --git a/target/linux/generic/backport-6.18/780-21-v6.14-r8169-remove-unused-flag-RTL_FLAG_TASK_RESET_NO_QUEU.patch b/target/linux/generic/backport-6.18/780-21-v6.14-r8169-remove-unused-flag-RTL_FLAG_TASK_RESET_NO_QUEU.patch deleted file mode 100644 index 182858ac02..0000000000 --- a/target/linux/generic/backport-6.18/780-21-v6.14-r8169-remove-unused-flag-RTL_FLAG_TASK_RESET_NO_QUEU.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 2e20bf8cc05766dcd0357cdfcada49e1bc45512b Mon Sep 17 00:00:00 2001 -From: Heiner Kallweit -Date: Mon, 2 Dec 2024 21:14:35 +0100 -Subject: [PATCH] r8169: remove unused flag RTL_FLAG_TASK_RESET_NO_QUEUE_WAKE - -After 854d71c555dfc3 ("r8169: remove original workaround for RTL8125 -broken rx issue") this flag isn't used any longer. So remove it. - -Signed-off-by: Heiner Kallweit -Reviewed-by: Michal Swiatkowski -Link: https://patch.msgid.link/d9dd214b-3027-4f60-b0e8-6f34a0c76582@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/realtek/r8169_main.c | 3 --- - 1 file changed, 3 deletions(-) - ---- a/drivers/net/ethernet/realtek/r8169_main.c -+++ b/drivers/net/ethernet/realtek/r8169_main.c -@@ -622,7 +622,6 @@ struct rtl8169_tc_offsets { - - enum rtl_flag { - RTL_FLAG_TASK_RESET_PENDING, -- RTL_FLAG_TASK_RESET_NO_QUEUE_WAKE, - RTL_FLAG_TASK_TX_TIMEOUT, - RTL_FLAG_MAX - }; -@@ -4746,8 +4745,6 @@ static void rtl_task(struct work_struct - reset: - rtl_reset_work(tp); - netif_wake_queue(tp->dev); -- } else if (test_and_clear_bit(RTL_FLAG_TASK_RESET_NO_QUEUE_WAKE, tp->wk.flags)) { -- rtl_reset_work(tp); - } - } - diff --git a/target/linux/generic/backport-6.18/780-22-v6.14-r8169-remove-support-for-chip-version-11.patch b/target/linux/generic/backport-6.18/780-22-v6.14-r8169-remove-support-for-chip-version-11.patch deleted file mode 100644 index 055e0f0155..0000000000 --- a/target/linux/generic/backport-6.18/780-22-v6.14-r8169-remove-support-for-chip-version-11.patch +++ /dev/null @@ -1,114 +0,0 @@ -From bb18265c3aba92b91a1355609769f3e967b65dee Mon Sep 17 00:00:00 2001 -From: Heiner Kallweit -Date: Mon, 2 Dec 2024 21:20:02 +0100 -Subject: [PATCH] r8169: remove support for chip version 11 - -This is a follow-up to 982300c115d2 ("r8169: remove detection of chip -version 11 (early RTL8168b)"). Nobody complained yet, so remove -support for this chip version. - -Signed-off-by: Heiner Kallweit -Reviewed-by: Simon Horman -Link: https://patch.msgid.link/b689ab6d-20b5-4b64-bd7e-531a0a972ba3@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/realtek/r8169.h | 2 +- - drivers/net/ethernet/realtek/r8169_main.c | 14 +------------- - drivers/net/ethernet/realtek/r8169_phy_config.c | 10 ---------- - 3 files changed, 2 insertions(+), 24 deletions(-) - ---- a/drivers/net/ethernet/realtek/r8169.h -+++ b/drivers/net/ethernet/realtek/r8169.h -@@ -23,7 +23,7 @@ enum mac_version { - RTL_GIGA_MAC_VER_08, - RTL_GIGA_MAC_VER_09, - RTL_GIGA_MAC_VER_10, -- RTL_GIGA_MAC_VER_11, -+ /* support for RTL_GIGA_MAC_VER_11 has been removed */ - /* RTL_GIGA_MAC_VER_12 was handled the same as VER_17 */ - /* RTL_GIGA_MAC_VER_13 was merged with VER_10 */ - RTL_GIGA_MAC_VER_14, ---- a/drivers/net/ethernet/realtek/r8169_main.c -+++ b/drivers/net/ethernet/realtek/r8169_main.c -@@ -103,7 +103,6 @@ static const struct { - [RTL_GIGA_MAC_VER_08] = {"RTL8102e" }, - [RTL_GIGA_MAC_VER_09] = {"RTL8102e/RTL8103e" }, - [RTL_GIGA_MAC_VER_10] = {"RTL8101e/RTL8100e" }, -- [RTL_GIGA_MAC_VER_11] = {"RTL8168b/8111b" }, - [RTL_GIGA_MAC_VER_14] = {"RTL8401" }, - [RTL_GIGA_MAC_VER_17] = {"RTL8168b/8111b" }, - [RTL_GIGA_MAC_VER_18] = {"RTL8168cp/8111cp" }, -@@ -2334,7 +2333,7 @@ static enum mac_version rtl8169_get_mac_ - - /* 8168B family. */ - { 0x7c8, 0x380, RTL_GIGA_MAC_VER_17 }, -- /* This one is very old and rare, let's see if anybody complains. -+ /* This one is very old and rare, support has been removed. - * { 0x7c8, 0x300, RTL_GIGA_MAC_VER_11 }, - */ - -@@ -3826,7 +3825,6 @@ static void rtl_hw_config(struct rtl8169 - [RTL_GIGA_MAC_VER_08] = rtl_hw_start_8102e_3, - [RTL_GIGA_MAC_VER_09] = rtl_hw_start_8102e_2, - [RTL_GIGA_MAC_VER_10] = NULL, -- [RTL_GIGA_MAC_VER_11] = rtl_hw_start_8168b, - [RTL_GIGA_MAC_VER_14] = rtl_hw_start_8401, - [RTL_GIGA_MAC_VER_17] = rtl_hw_start_8168b, - [RTL_GIGA_MAC_VER_18] = rtl_hw_start_8168cp_1, -@@ -4702,12 +4700,6 @@ static irqreturn_t rtl8169_interrupt(int - if (status & LinkChg) - phy_mac_interrupt(tp->phydev); - -- if (unlikely(status & RxFIFOOver && -- tp->mac_version == RTL_GIGA_MAC_VER_11)) { -- netif_stop_queue(tp->dev); -- rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING); -- } -- - rtl_irq_disable(tp); - napi_schedule(&tp->napi); - out: -@@ -5124,9 +5116,6 @@ static void rtl_set_irq_mask(struct rtl8 - - if (tp->mac_version <= RTL_GIGA_MAC_VER_06) - tp->irq_mask |= SYSErr | RxFIFOOver; -- else if (tp->mac_version == RTL_GIGA_MAC_VER_11) -- /* special workaround needed */ -- tp->irq_mask |= RxFIFOOver; - } - - static int rtl_alloc_irq(struct rtl8169_private *tp) -@@ -5321,7 +5310,6 @@ static int rtl_jumbo_max(struct rtl8169_ - case RTL_GIGA_MAC_VER_02 ... RTL_GIGA_MAC_VER_06: - return JUMBO_7K; - /* RTL8168b */ -- case RTL_GIGA_MAC_VER_11: - case RTL_GIGA_MAC_VER_17: - return JUMBO_4K; - /* RTL8168c */ ---- a/drivers/net/ethernet/realtek/r8169_phy_config.c -+++ b/drivers/net/ethernet/realtek/r8169_phy_config.c -@@ -276,15 +276,6 @@ static void rtl8169sce_hw_phy_config(str - rtl_writephy_batch(phydev, phy_reg_init); - } - --static void rtl8168bb_hw_phy_config(struct rtl8169_private *tp, -- struct phy_device *phydev) --{ -- phy_write(phydev, 0x1f, 0x0001); -- phy_set_bits(phydev, 0x16, BIT(0)); -- phy_write(phydev, 0x10, 0xf41b); -- phy_write(phydev, 0x1f, 0x0000); --} -- - static void rtl8168bef_hw_phy_config(struct rtl8169_private *tp, - struct phy_device *phydev) - { -@@ -1136,7 +1127,6 @@ void r8169_hw_phy_config(struct rtl8169_ - [RTL_GIGA_MAC_VER_08] = rtl8102e_hw_phy_config, - [RTL_GIGA_MAC_VER_09] = rtl8102e_hw_phy_config, - [RTL_GIGA_MAC_VER_10] = NULL, -- [RTL_GIGA_MAC_VER_11] = rtl8168bb_hw_phy_config, - [RTL_GIGA_MAC_VER_14] = rtl8401_hw_phy_config, - [RTL_GIGA_MAC_VER_17] = rtl8168bef_hw_phy_config, - [RTL_GIGA_MAC_VER_18] = rtl8168cp_1_hw_phy_config, diff --git a/target/linux/generic/backport-6.18/780-23-v6.14-r8169-adjust-version-numbering-for-RTL8126.patch b/target/linux/generic/backport-6.18/780-23-v6.14-r8169-adjust-version-numbering-for-RTL8126.patch deleted file mode 100644 index 7ea47bd2ed..0000000000 --- a/target/linux/generic/backport-6.18/780-23-v6.14-r8169-adjust-version-numbering-for-RTL8126.patch +++ /dev/null @@ -1,257 +0,0 @@ -From b299ea0069284186b0d3d54aebe87f0d195d457a Mon Sep 17 00:00:00 2001 -From: Heiner Kallweit -Date: Fri, 13 Dec 2024 20:01:41 +0100 -Subject: [PATCH] r8169: adjust version numbering for RTL8126 - -Adjust version numbering for RTL8126, so that it doesn't overlap with -new RTL8125 versions. - -Signed-off-by: Heiner Kallweit -Reviewed-by: Simon Horman -Link: https://patch.msgid.link/6a354364-20e9-48ad-a198-468264288757@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/realtek/r8169.h | 4 +- - drivers/net/ethernet/realtek/r8169_main.c | 62 +++++++++---------- - .../net/ethernet/realtek/r8169_phy_config.c | 4 +- - 3 files changed, 35 insertions(+), 35 deletions(-) - ---- a/drivers/net/ethernet/realtek/r8169.h -+++ b/drivers/net/ethernet/realtek/r8169.h -@@ -69,8 +69,8 @@ enum mac_version { - RTL_GIGA_MAC_VER_61, - RTL_GIGA_MAC_VER_63, - RTL_GIGA_MAC_VER_64, -- RTL_GIGA_MAC_VER_65, -- RTL_GIGA_MAC_VER_66, -+ RTL_GIGA_MAC_VER_70, -+ RTL_GIGA_MAC_VER_71, - RTL_GIGA_MAC_NONE - }; - ---- a/drivers/net/ethernet/realtek/r8169_main.c -+++ b/drivers/net/ethernet/realtek/r8169_main.c -@@ -139,8 +139,8 @@ static const struct { - /* reserve 62 for CFG_METHOD_4 in the vendor driver */ - [RTL_GIGA_MAC_VER_63] = {"RTL8125B", FIRMWARE_8125B_2}, - [RTL_GIGA_MAC_VER_64] = {"RTL8125D", FIRMWARE_8125D_1}, -- [RTL_GIGA_MAC_VER_65] = {"RTL8126A", FIRMWARE_8126A_2}, -- [RTL_GIGA_MAC_VER_66] = {"RTL8126A", FIRMWARE_8126A_3}, -+ [RTL_GIGA_MAC_VER_70] = {"RTL8126A", FIRMWARE_8126A_2}, -+ [RTL_GIGA_MAC_VER_71] = {"RTL8126A", FIRMWARE_8126A_3}, - }; - - static const struct pci_device_id rtl8169_pci_tbl[] = { -@@ -1227,7 +1227,7 @@ static void rtl_writephy(struct rtl8169_ - case RTL_GIGA_MAC_VER_31: - r8168dp_2_mdio_write(tp, location, val); - break; -- case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_66: -+ case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_71: - r8168g_mdio_write(tp, location, val); - break; - default: -@@ -1242,7 +1242,7 @@ static int rtl_readphy(struct rtl8169_pr - case RTL_GIGA_MAC_VER_28: - case RTL_GIGA_MAC_VER_31: - return r8168dp_2_mdio_read(tp, location); -- case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_66: -+ case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_71: - return r8168g_mdio_read(tp, location); - default: - return r8169_mdio_read(tp, location); -@@ -1573,7 +1573,7 @@ static void __rtl8169_set_wol(struct rtl - break; - case RTL_GIGA_MAC_VER_34: - case RTL_GIGA_MAC_VER_37: -- case RTL_GIGA_MAC_VER_39 ... RTL_GIGA_MAC_VER_66: -+ case RTL_GIGA_MAC_VER_39 ... RTL_GIGA_MAC_VER_71: - r8169_mod_reg8_cond(tp, Config2, PME_SIGNAL, wolopts); - break; - default: -@@ -2046,7 +2046,7 @@ static void rtl_set_eee_txidle_timer(str - tp->tx_lpi_timer = timer_val; - r8168_mac_ocp_write(tp, 0xe048, timer_val); - break; -- case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_66: -+ case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_71: - tp->tx_lpi_timer = timer_val; - RTL_W16(tp, EEE_TXIDLE_TIMER_8125, timer_val); - break; -@@ -2254,8 +2254,8 @@ static enum mac_version rtl8169_get_mac_ - enum mac_version ver; - } mac_info[] = { - /* 8126A family. */ -- { 0x7cf, 0x64a, RTL_GIGA_MAC_VER_66 }, -- { 0x7cf, 0x649, RTL_GIGA_MAC_VER_65 }, -+ { 0x7cf, 0x64a, RTL_GIGA_MAC_VER_71 }, -+ { 0x7cf, 0x649, RTL_GIGA_MAC_VER_70 }, - - /* 8125D family. */ - { 0x7cf, 0x688, RTL_GIGA_MAC_VER_64 }, -@@ -2525,7 +2525,7 @@ static void rtl_init_rxcfg(struct rtl816 - case RTL_GIGA_MAC_VER_61: - RTL_W32(tp, RxConfig, RX_FETCH_DFLT_8125 | RX_DMA_BURST); - break; -- case RTL_GIGA_MAC_VER_63 ... RTL_GIGA_MAC_VER_66: -+ case RTL_GIGA_MAC_VER_63 ... RTL_GIGA_MAC_VER_71: - RTL_W32(tp, RxConfig, RX_FETCH_DFLT_8125 | RX_DMA_BURST | - RX_PAUSE_SLOT_ON); - break; -@@ -2657,7 +2657,7 @@ static void rtl_wait_txrx_fifo_empty(str - case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_61: - rtl_loop_wait_high(tp, &rtl_rxtx_empty_cond, 100, 42); - break; -- case RTL_GIGA_MAC_VER_63 ... RTL_GIGA_MAC_VER_66: -+ case RTL_GIGA_MAC_VER_63 ... RTL_GIGA_MAC_VER_71: - RTL_W8(tp, ChipCmd, RTL_R8(tp, ChipCmd) | StopReq); - rtl_loop_wait_high(tp, &rtl_rxtx_empty_cond, 100, 42); - rtl_loop_wait_high(tp, &rtl_rxtx_empty_cond_2, 100, 42); -@@ -2923,7 +2923,7 @@ static void rtl_enable_exit_l1(struct rt - case RTL_GIGA_MAC_VER_37 ... RTL_GIGA_MAC_VER_38: - rtl_eri_set_bits(tp, 0xd4, 0x0c00); - break; -- case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_66: -+ case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_71: - r8168_mac_ocp_modify(tp, 0xc0ac, 0, 0x1f80); - break; - default: -@@ -2937,7 +2937,7 @@ static void rtl_disable_exit_l1(struct r - case RTL_GIGA_MAC_VER_34 ... RTL_GIGA_MAC_VER_38: - rtl_eri_clear_bits(tp, 0xd4, 0x1f00); - break; -- case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_66: -+ case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_71: - r8168_mac_ocp_modify(tp, 0xc0ac, 0x1f80, 0); - break; - default: -@@ -2963,8 +2963,8 @@ static void rtl_hw_aspm_clkreq_enable(st - - rtl_mod_config5(tp, 0, ASPM_en); - switch (tp->mac_version) { -- case RTL_GIGA_MAC_VER_65: -- case RTL_GIGA_MAC_VER_66: -+ case RTL_GIGA_MAC_VER_70: -+ case RTL_GIGA_MAC_VER_71: - val8 = RTL_R8(tp, INT_CFG0_8125) | INT_CFG0_CLKREQEN; - RTL_W8(tp, INT_CFG0_8125, val8); - break; -@@ -2975,7 +2975,7 @@ static void rtl_hw_aspm_clkreq_enable(st - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_46 ... RTL_GIGA_MAC_VER_48: -- case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_66: -+ case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_71: - /* reset ephy tx/rx disable timer */ - r8168_mac_ocp_modify(tp, 0xe094, 0xff00, 0); - /* chip can trigger L1.2 */ -@@ -2987,7 +2987,7 @@ static void rtl_hw_aspm_clkreq_enable(st - } else { - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_46 ... RTL_GIGA_MAC_VER_48: -- case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_66: -+ case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_71: - r8168_mac_ocp_modify(tp, 0xe092, 0x00ff, 0); - break; - default: -@@ -2995,8 +2995,8 @@ static void rtl_hw_aspm_clkreq_enable(st - } - - switch (tp->mac_version) { -- case RTL_GIGA_MAC_VER_65: -- case RTL_GIGA_MAC_VER_66: -+ case RTL_GIGA_MAC_VER_70: -+ case RTL_GIGA_MAC_VER_71: - val8 = RTL_R8(tp, INT_CFG0_8125) & ~INT_CFG0_CLKREQEN; - RTL_W8(tp, INT_CFG0_8125, val8); - break; -@@ -3716,12 +3716,12 @@ static void rtl_hw_start_8125_common(str - /* disable new tx descriptor format */ - r8168_mac_ocp_modify(tp, 0xeb58, 0x0001, 0x0000); - -- if (tp->mac_version == RTL_GIGA_MAC_VER_65 || -- tp->mac_version == RTL_GIGA_MAC_VER_66) -+ if (tp->mac_version == RTL_GIGA_MAC_VER_70 || -+ tp->mac_version == RTL_GIGA_MAC_VER_71) - RTL_W8(tp, 0xD8, RTL_R8(tp, 0xD8) & ~0x02); - -- if (tp->mac_version == RTL_GIGA_MAC_VER_65 || -- tp->mac_version == RTL_GIGA_MAC_VER_66) -+ if (tp->mac_version == RTL_GIGA_MAC_VER_70 || -+ tp->mac_version == RTL_GIGA_MAC_VER_71) - r8168_mac_ocp_modify(tp, 0xe614, 0x0700, 0x0400); - else if (tp->mac_version == RTL_GIGA_MAC_VER_63) - r8168_mac_ocp_modify(tp, 0xe614, 0x0700, 0x0200); -@@ -3739,8 +3739,8 @@ static void rtl_hw_start_8125_common(str - r8168_mac_ocp_modify(tp, 0xe056, 0x00f0, 0x0000); - r8168_mac_ocp_modify(tp, 0xe040, 0x1000, 0x0000); - r8168_mac_ocp_modify(tp, 0xea1c, 0x0003, 0x0001); -- if (tp->mac_version == RTL_GIGA_MAC_VER_65 || -- tp->mac_version == RTL_GIGA_MAC_VER_66) -+ if (tp->mac_version == RTL_GIGA_MAC_VER_70 || -+ tp->mac_version == RTL_GIGA_MAC_VER_71) - r8168_mac_ocp_modify(tp, 0xea1c, 0x0300, 0x0000); - else - r8168_mac_ocp_modify(tp, 0xea1c, 0x0004, 0x0000); -@@ -3860,8 +3860,8 @@ static void rtl_hw_config(struct rtl8169 - [RTL_GIGA_MAC_VER_61] = rtl_hw_start_8125a_2, - [RTL_GIGA_MAC_VER_63] = rtl_hw_start_8125b, - [RTL_GIGA_MAC_VER_64] = rtl_hw_start_8125d, -- [RTL_GIGA_MAC_VER_65] = rtl_hw_start_8126a, -- [RTL_GIGA_MAC_VER_66] = rtl_hw_start_8126a, -+ [RTL_GIGA_MAC_VER_70] = rtl_hw_start_8126a, -+ [RTL_GIGA_MAC_VER_71] = rtl_hw_start_8126a, - }; - - if (hw_configs[tp->mac_version]) -@@ -3882,8 +3882,8 @@ static void rtl_hw_start_8125(struct rtl - RTL_W32(tp, i, 0); - break; - case RTL_GIGA_MAC_VER_63: -- case RTL_GIGA_MAC_VER_65: -- case RTL_GIGA_MAC_VER_66: -+ case RTL_GIGA_MAC_VER_70: -+ case RTL_GIGA_MAC_VER_71: - for (i = 0xa00; i < 0xa80; i += 4) - RTL_W32(tp, i, 0); - RTL_W16(tp, INT_CFG1_8125, 0x0000); -@@ -4115,7 +4115,7 @@ static void rtl8169_cleanup(struct rtl81 - RTL_W8(tp, ChipCmd, RTL_R8(tp, ChipCmd) | StopReq); - rtl_loop_wait_high(tp, &rtl_txcfg_empty_cond, 100, 666); - break; -- case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_66: -+ case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_71: - rtl_enable_rxdvgate(tp); - fsleep(2000); - break; -@@ -4272,7 +4272,7 @@ static unsigned int rtl_quirk_packet_pad - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_34: -- case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_66: -+ case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_71: - padto = max_t(unsigned int, padto, ETH_ZLEN); - break; - default: -@@ -5291,7 +5291,7 @@ static void rtl_hw_initialize(struct rtl - case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_48: - rtl_hw_init_8168g(tp); - break; -- case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_66: -+ case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_71: - rtl_hw_init_8125(tp); - break; - default: ---- a/drivers/net/ethernet/realtek/r8169_phy_config.c -+++ b/drivers/net/ethernet/realtek/r8169_phy_config.c -@@ -1162,8 +1162,8 @@ void r8169_hw_phy_config(struct rtl8169_ - [RTL_GIGA_MAC_VER_61] = rtl8125a_2_hw_phy_config, - [RTL_GIGA_MAC_VER_63] = rtl8125b_hw_phy_config, - [RTL_GIGA_MAC_VER_64] = rtl8125d_hw_phy_config, -- [RTL_GIGA_MAC_VER_65] = rtl8126a_hw_phy_config, -- [RTL_GIGA_MAC_VER_66] = rtl8126a_hw_phy_config, -+ [RTL_GIGA_MAC_VER_70] = rtl8126a_hw_phy_config, -+ [RTL_GIGA_MAC_VER_71] = rtl8126a_hw_phy_config, - }; - - if (phy_configs[ver]) diff --git a/target/linux/generic/backport-6.18/780-24-v6.14-r8169-add-support-for-RTL8125D-rev.b.patch b/target/linux/generic/backport-6.18/780-24-v6.14-r8169-add-support-for-RTL8125D-rev.b.patch deleted file mode 100644 index bbc447f4de..0000000000 --- a/target/linux/generic/backport-6.18/780-24-v6.14-r8169-add-support-for-RTL8125D-rev.b.patch +++ /dev/null @@ -1,90 +0,0 @@ -From b3593df26ab19f114d613693fa8a92ab202803d0 Mon Sep 17 00:00:00 2001 -From: ChunHao Lin -Date: Fri, 13 Dec 2024 20:02:58 +0100 -Subject: [PATCH] r8169: add support for RTL8125D rev.b - -Add support for RTL8125D rev.b. Its XID is 0x689. It is basically -based on the one with XID 0x688, but with different firmware file. - -Signed-off-by: ChunHao Lin -[hkallweit1@gmail.com: rebased after adjusted version numbering] -Signed-off-by: Heiner Kallweit -Reviewed-by: Simon Horman -Link: https://patch.msgid.link/75e5e9ec-d01f-43ac-b0f4-e7456baf18d1@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/realtek/r8169.h | 1 + - drivers/net/ethernet/realtek/r8169_main.c | 6 ++++++ - drivers/net/ethernet/realtek/r8169_phy_config.c | 1 + - 3 files changed, 8 insertions(+) - ---- a/drivers/net/ethernet/realtek/r8169.h -+++ b/drivers/net/ethernet/realtek/r8169.h -@@ -69,6 +69,7 @@ enum mac_version { - RTL_GIGA_MAC_VER_61, - RTL_GIGA_MAC_VER_63, - RTL_GIGA_MAC_VER_64, -+ RTL_GIGA_MAC_VER_65, - RTL_GIGA_MAC_VER_70, - RTL_GIGA_MAC_VER_71, - RTL_GIGA_MAC_NONE ---- a/drivers/net/ethernet/realtek/r8169_main.c -+++ b/drivers/net/ethernet/realtek/r8169_main.c -@@ -56,6 +56,7 @@ - #define FIRMWARE_8125A_3 "rtl_nic/rtl8125a-3.fw" - #define FIRMWARE_8125B_2 "rtl_nic/rtl8125b-2.fw" - #define FIRMWARE_8125D_1 "rtl_nic/rtl8125d-1.fw" -+#define FIRMWARE_8125D_2 "rtl_nic/rtl8125d-2.fw" - #define FIRMWARE_8126A_2 "rtl_nic/rtl8126a-2.fw" - #define FIRMWARE_8126A_3 "rtl_nic/rtl8126a-3.fw" - -@@ -139,6 +140,7 @@ static const struct { - /* reserve 62 for CFG_METHOD_4 in the vendor driver */ - [RTL_GIGA_MAC_VER_63] = {"RTL8125B", FIRMWARE_8125B_2}, - [RTL_GIGA_MAC_VER_64] = {"RTL8125D", FIRMWARE_8125D_1}, -+ [RTL_GIGA_MAC_VER_65] = {"RTL8125D", FIRMWARE_8125D_2}, - [RTL_GIGA_MAC_VER_70] = {"RTL8126A", FIRMWARE_8126A_2}, - [RTL_GIGA_MAC_VER_71] = {"RTL8126A", FIRMWARE_8126A_3}, - }; -@@ -705,6 +707,7 @@ MODULE_FIRMWARE(FIRMWARE_8107E_2); - MODULE_FIRMWARE(FIRMWARE_8125A_3); - MODULE_FIRMWARE(FIRMWARE_8125B_2); - MODULE_FIRMWARE(FIRMWARE_8125D_1); -+MODULE_FIRMWARE(FIRMWARE_8125D_2); - MODULE_FIRMWARE(FIRMWARE_8126A_2); - MODULE_FIRMWARE(FIRMWARE_8126A_3); - -@@ -2258,6 +2261,7 @@ static enum mac_version rtl8169_get_mac_ - { 0x7cf, 0x649, RTL_GIGA_MAC_VER_70 }, - - /* 8125D family. */ -+ { 0x7cf, 0x689, RTL_GIGA_MAC_VER_65 }, - { 0x7cf, 0x688, RTL_GIGA_MAC_VER_64 }, - - /* 8125B family. */ -@@ -3860,6 +3864,7 @@ static void rtl_hw_config(struct rtl8169 - [RTL_GIGA_MAC_VER_61] = rtl_hw_start_8125a_2, - [RTL_GIGA_MAC_VER_63] = rtl_hw_start_8125b, - [RTL_GIGA_MAC_VER_64] = rtl_hw_start_8125d, -+ [RTL_GIGA_MAC_VER_65] = rtl_hw_start_8125d, - [RTL_GIGA_MAC_VER_70] = rtl_hw_start_8126a, - [RTL_GIGA_MAC_VER_71] = rtl_hw_start_8126a, - }; -@@ -3878,6 +3883,7 @@ static void rtl_hw_start_8125(struct rtl - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_61: - case RTL_GIGA_MAC_VER_64: -+ case RTL_GIGA_MAC_VER_65: - for (i = 0xa00; i < 0xb00; i += 4) - RTL_W32(tp, i, 0); - break; ---- a/drivers/net/ethernet/realtek/r8169_phy_config.c -+++ b/drivers/net/ethernet/realtek/r8169_phy_config.c -@@ -1162,6 +1162,7 @@ void r8169_hw_phy_config(struct rtl8169_ - [RTL_GIGA_MAC_VER_61] = rtl8125a_2_hw_phy_config, - [RTL_GIGA_MAC_VER_63] = rtl8125b_hw_phy_config, - [RTL_GIGA_MAC_VER_64] = rtl8125d_hw_phy_config, -+ [RTL_GIGA_MAC_VER_65] = rtl8125d_hw_phy_config, - [RTL_GIGA_MAC_VER_70] = rtl8126a_hw_phy_config, - [RTL_GIGA_MAC_VER_71] = rtl8126a_hw_phy_config, - }; diff --git a/target/linux/generic/backport-6.18/780-25-v6.14-r8169-add-support-for-RTL8125BP-rev.b.patch b/target/linux/generic/backport-6.18/780-25-v6.14-r8169-add-support-for-RTL8125BP-rev.b.patch deleted file mode 100644 index 7b4f474bee..0000000000 --- a/target/linux/generic/backport-6.18/780-25-v6.14-r8169-add-support-for-RTL8125BP-rev.b.patch +++ /dev/null @@ -1,184 +0,0 @@ -From b11bff90f2ad52c5c55c822ecd20326619a73898 Mon Sep 17 00:00:00 2001 -From: ChunHao Lin -Date: Tue, 7 Jan 2025 14:43:55 +0800 -Subject: [PATCH] r8169: add support for RTL8125BP rev.b - -Add support for RTL8125BP rev.b. Its XID is 0x689. This chip supports -DASH and its dash type is "RTL_DASH_25_BP". - -Signed-off-by: ChunHao Lin -Reviewed-by: Heiner Kallweit -Link: https://patch.msgid.link/20250107064355.104711-1-hau@realtek.com -Signed-off-by: Paolo Abeni ---- - drivers/net/ethernet/realtek/r8169.h | 1 + - drivers/net/ethernet/realtek/r8169_main.c | 30 +++++++++++++++++++ - .../net/ethernet/realtek/r8169_phy_config.c | 23 ++++++++++++++ - 3 files changed, 54 insertions(+) - ---- a/drivers/net/ethernet/realtek/r8169.h -+++ b/drivers/net/ethernet/realtek/r8169.h -@@ -70,6 +70,7 @@ enum mac_version { - RTL_GIGA_MAC_VER_63, - RTL_GIGA_MAC_VER_64, - RTL_GIGA_MAC_VER_65, -+ RTL_GIGA_MAC_VER_66, - RTL_GIGA_MAC_VER_70, - RTL_GIGA_MAC_VER_71, - RTL_GIGA_MAC_NONE ---- a/drivers/net/ethernet/realtek/r8169_main.c -+++ b/drivers/net/ethernet/realtek/r8169_main.c -@@ -57,6 +57,7 @@ - #define FIRMWARE_8125B_2 "rtl_nic/rtl8125b-2.fw" - #define FIRMWARE_8125D_1 "rtl_nic/rtl8125d-1.fw" - #define FIRMWARE_8125D_2 "rtl_nic/rtl8125d-2.fw" -+#define FIRMWARE_8125BP_2 "rtl_nic/rtl8125bp-2.fw" - #define FIRMWARE_8126A_2 "rtl_nic/rtl8126a-2.fw" - #define FIRMWARE_8126A_3 "rtl_nic/rtl8126a-3.fw" - -@@ -141,6 +142,7 @@ static const struct { - [RTL_GIGA_MAC_VER_63] = {"RTL8125B", FIRMWARE_8125B_2}, - [RTL_GIGA_MAC_VER_64] = {"RTL8125D", FIRMWARE_8125D_1}, - [RTL_GIGA_MAC_VER_65] = {"RTL8125D", FIRMWARE_8125D_2}, -+ [RTL_GIGA_MAC_VER_66] = {"RTL8125BP", FIRMWARE_8125BP_2}, - [RTL_GIGA_MAC_VER_70] = {"RTL8126A", FIRMWARE_8126A_2}, - [RTL_GIGA_MAC_VER_71] = {"RTL8126A", FIRMWARE_8126A_3}, - }; -@@ -631,6 +633,7 @@ enum rtl_dash_type { - RTL_DASH_NONE, - RTL_DASH_DP, - RTL_DASH_EP, -+ RTL_DASH_25_BP, - }; - - struct rtl8169_private { -@@ -708,6 +711,7 @@ MODULE_FIRMWARE(FIRMWARE_8125A_3); - MODULE_FIRMWARE(FIRMWARE_8125B_2); - MODULE_FIRMWARE(FIRMWARE_8125D_1); - MODULE_FIRMWARE(FIRMWARE_8125D_2); -+MODULE_FIRMWARE(FIRMWARE_8125BP_2); - MODULE_FIRMWARE(FIRMWARE_8126A_2); - MODULE_FIRMWARE(FIRMWARE_8126A_3); - -@@ -1360,10 +1364,19 @@ static void rtl8168ep_driver_start(struc - rtl_loop_wait_high(tp, &rtl_ep_ocp_read_cond, 10000, 30); - } - -+static void rtl8125bp_driver_start(struct rtl8169_private *tp) -+{ -+ r8168ep_ocp_write(tp, 0x01, 0x14, OOB_CMD_DRIVER_START); -+ r8168ep_ocp_write(tp, 0x01, 0x18, 0x00); -+ r8168ep_ocp_write(tp, 0x01, 0x10, 0x01); -+} -+ - static void rtl8168_driver_start(struct rtl8169_private *tp) - { - if (tp->dash_type == RTL_DASH_DP) - rtl8168dp_driver_start(tp); -+ else if (tp->dash_type == RTL_DASH_25_BP) -+ rtl8125bp_driver_start(tp); - else - rtl8168ep_driver_start(tp); - } -@@ -1384,10 +1397,19 @@ static void rtl8168ep_driver_stop(struct - rtl_loop_wait_low(tp, &rtl_ep_ocp_read_cond, 10000, 10); - } - -+static void rtl8125bp_driver_stop(struct rtl8169_private *tp) -+{ -+ r8168ep_ocp_write(tp, 0x01, 0x14, OOB_CMD_DRIVER_STOP); -+ r8168ep_ocp_write(tp, 0x01, 0x18, 0x00); -+ r8168ep_ocp_write(tp, 0x01, 0x10, 0x01); -+} -+ - static void rtl8168_driver_stop(struct rtl8169_private *tp) - { - if (tp->dash_type == RTL_DASH_DP) - rtl8168dp_driver_stop(tp); -+ else if (tp->dash_type == RTL_DASH_25_BP) -+ rtl8125bp_driver_stop(tp); - else - rtl8168ep_driver_stop(tp); - } -@@ -1410,6 +1432,7 @@ static bool rtl_dash_is_enabled(struct r - case RTL_DASH_DP: - return r8168dp_check_dash(tp); - case RTL_DASH_EP: -+ case RTL_DASH_25_BP: - return r8168ep_check_dash(tp); - default: - return false; -@@ -1424,6 +1447,8 @@ static enum rtl_dash_type rtl_get_dash_t - return RTL_DASH_DP; - case RTL_GIGA_MAC_VER_51 ... RTL_GIGA_MAC_VER_53: - return RTL_DASH_EP; -+ case RTL_GIGA_MAC_VER_66: -+ return RTL_DASH_25_BP; - default: - return RTL_DASH_NONE; - } -@@ -2260,6 +2285,9 @@ static enum mac_version rtl8169_get_mac_ - { 0x7cf, 0x64a, RTL_GIGA_MAC_VER_71 }, - { 0x7cf, 0x649, RTL_GIGA_MAC_VER_70 }, - -+ /* 8125BP family. */ -+ { 0x7cf, 0x681, RTL_GIGA_MAC_VER_66 }, -+ - /* 8125D family. */ - { 0x7cf, 0x689, RTL_GIGA_MAC_VER_65 }, - { 0x7cf, 0x688, RTL_GIGA_MAC_VER_64 }, -@@ -3865,6 +3893,7 @@ static void rtl_hw_config(struct rtl8169 - [RTL_GIGA_MAC_VER_63] = rtl_hw_start_8125b, - [RTL_GIGA_MAC_VER_64] = rtl_hw_start_8125d, - [RTL_GIGA_MAC_VER_65] = rtl_hw_start_8125d, -+ [RTL_GIGA_MAC_VER_66] = rtl_hw_start_8125d, - [RTL_GIGA_MAC_VER_70] = rtl_hw_start_8126a, - [RTL_GIGA_MAC_VER_71] = rtl_hw_start_8126a, - }; -@@ -3884,6 +3913,7 @@ static void rtl_hw_start_8125(struct rtl - case RTL_GIGA_MAC_VER_61: - case RTL_GIGA_MAC_VER_64: - case RTL_GIGA_MAC_VER_65: -+ case RTL_GIGA_MAC_VER_66: - for (i = 0xa00; i < 0xb00; i += 4) - RTL_W32(tp, i, 0); - break; ---- a/drivers/net/ethernet/realtek/r8169_phy_config.c -+++ b/drivers/net/ethernet/realtek/r8169_phy_config.c -@@ -1102,6 +1102,28 @@ static void rtl8125d_hw_phy_config(struc - rtl8125_config_eee_phy(phydev); - } - -+static void rtl8125bp_hw_phy_config(struct rtl8169_private *tp, -+ struct phy_device *phydev) -+{ -+ r8169_apply_firmware(tp); -+ rtl8168g_enable_gphy_10m(phydev); -+ -+ r8168g_phy_param(phydev, 0x8010, 0x0800, 0x0000); -+ -+ phy_write(phydev, 0x1f, 0x0b87); -+ phy_write(phydev, 0x16, 0x8088); -+ phy_modify(phydev, 0x17, 0xff00, 0x9000); -+ phy_write(phydev, 0x16, 0x808f); -+ phy_modify(phydev, 0x17, 0xff00, 0x9000); -+ phy_write(phydev, 0x1f, 0x0000); -+ -+ r8168g_phy_param(phydev, 0x8174, 0x2000, 0x1800); -+ -+ rtl8125_legacy_force_mode(phydev); -+ rtl8168g_disable_aldps(phydev); -+ rtl8125_config_eee_phy(phydev); -+} -+ - static void rtl8126a_hw_phy_config(struct rtl8169_private *tp, - struct phy_device *phydev) - { -@@ -1163,6 +1185,7 @@ void r8169_hw_phy_config(struct rtl8169_ - [RTL_GIGA_MAC_VER_63] = rtl8125b_hw_phy_config, - [RTL_GIGA_MAC_VER_64] = rtl8125d_hw_phy_config, - [RTL_GIGA_MAC_VER_65] = rtl8125d_hw_phy_config, -+ [RTL_GIGA_MAC_VER_66] = rtl8125bp_hw_phy_config, - [RTL_GIGA_MAC_VER_70] = rtl8126a_hw_phy_config, - [RTL_GIGA_MAC_VER_71] = rtl8126a_hw_phy_config, - }; diff --git a/target/linux/generic/backport-6.18/780-26-v6.15-r8169-make-Kconfig-option-for-LED-support-user-visib.patch b/target/linux/generic/backport-6.18/780-26-v6.15-r8169-make-Kconfig-option-for-LED-support-user-visib.patch deleted file mode 100644 index 62acd26963..0000000000 --- a/target/linux/generic/backport-6.18/780-26-v6.15-r8169-make-Kconfig-option-for-LED-support-user-visib.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 135c3c86a7cef4ba3d368da15b16c275b74582d3 Mon Sep 17 00:00:00 2001 -From: Heiner Kallweit -Date: Mon, 3 Feb 2025 21:35:24 +0100 -Subject: [PATCH] r8169: make Kconfig option for LED support user-visible - -Make config option R8169_LEDS user-visible, so that users can remove -support if not needed. - -Signed-off-by: Heiner Kallweit -Reviewed-by: Simon Horman -Link: https://patch.msgid.link/d29f0cdb-32bf-435f-b59d-dc96bca1e3ab@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/realtek/Kconfig | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - ---- a/drivers/net/ethernet/realtek/Kconfig -+++ b/drivers/net/ethernet/realtek/Kconfig -@@ -114,7 +114,8 @@ config R8169 - will be called r8169. This is recommended. - - config R8169_LEDS -- def_bool R8169 && LEDS_TRIGGER_NETDEV -+ bool "Support for controlling the NIC LEDs" -+ depends on R8169 && LEDS_TRIGGER_NETDEV - depends on !(R8169=y && LEDS_CLASS=m) - help - Optional support for controlling the NIC LED's with the netdev diff --git a/target/linux/generic/backport-6.18/780-28-v6.15-r8169-add-support-for-Intel-Killer-E5000.patch b/target/linux/generic/backport-6.18/780-28-v6.15-r8169-add-support-for-Intel-Killer-E5000.patch deleted file mode 100644 index d741d193ab..0000000000 --- a/target/linux/generic/backport-6.18/780-28-v6.15-r8169-add-support-for-Intel-Killer-E5000.patch +++ /dev/null @@ -1,25 +0,0 @@ -From d30460f42675fef5cd4b44ffbc49b545524555e3 Mon Sep 17 00:00:00 2001 -From: Heiner Kallweit -Date: Wed, 12 Feb 2025 08:03:56 +0100 -Subject: [PATCH] r8169: add support for Intel Killer E5000 - -This adds support for the Intel Killer E5000 which seems to be a -rebranded RTL8126. Copied from r8126 vendor driver. - -Signed-off-by: Heiner Kallweit -Link: https://patch.msgid.link/9db73e9b-e2e8-45de-97a5-041c5f71d774@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/realtek/r8169_main.c | 1 + - 1 file changed, 1 insertion(+) - ---- a/drivers/net/ethernet/realtek/r8169_main.c -+++ b/drivers/net/ethernet/realtek/r8169_main.c -@@ -169,6 +169,7 @@ static const struct pci_device_id rtl816 - { PCI_VDEVICE(REALTEK, 0x8125) }, - { PCI_VDEVICE(REALTEK, 0x8126) }, - { PCI_VDEVICE(REALTEK, 0x3000) }, -+ { PCI_VDEVICE(REALTEK, 0x5000) }, - {} - }; - diff --git a/target/linux/generic/backport-6.18/780-29-v6.15-r8169-add-PHY-c45-ops-for-MDIO_MMD_VENDOR2-registers.patch b/target/linux/generic/backport-6.18/780-29-v6.15-r8169-add-PHY-c45-ops-for-MDIO_MMD_VENDOR2-registers.patch deleted file mode 100644 index 1336ec6f91..0000000000 --- a/target/linux/generic/backport-6.18/780-29-v6.15-r8169-add-PHY-c45-ops-for-MDIO_MMD_VENDOR2-registers.patch +++ /dev/null @@ -1,67 +0,0 @@ -From 853e80369cfceb2331bf34f251ba11c6602cc67f Mon Sep 17 00:00:00 2001 -From: Heiner Kallweit -Date: Thu, 13 Feb 2025 20:15:42 +0100 -Subject: [PATCH] r8169: add PHY c45 ops for MDIO_MMD_VENDOR2 registers - -The integrated PHYs on chip versions from RTL8168g allow to address -MDIO_MMD_VEND2 registers. All c22 standard registers are mapped to -MDIO_MMD_VEND2 registers. So far the paging mechanism is used to -address PHY registers. Add support for c45 ops to address MDIO_MMD_VEND2 -registers directly, w/o the paging. - -Signed-off-by: Heiner Kallweit -Reviewed-by: Andrew Lunn -Link: https://patch.msgid.link/d6f97eaa-0f13-468f-89cb-75a41087bc4a@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/realtek/r8169_main.c | 32 +++++++++++++++++++++++ - 1 file changed, 32 insertions(+) - ---- a/drivers/net/ethernet/realtek/r8169_main.c -+++ b/drivers/net/ethernet/realtek/r8169_main.c -@@ -5225,6 +5225,33 @@ static int r8169_mdio_write_reg(struct m - return 0; - } - -+static int r8169_mdio_read_reg_c45(struct mii_bus *mii_bus, int addr, -+ int devnum, int regnum) -+{ -+ struct rtl8169_private *tp = mii_bus->priv; -+ -+ if (addr > 0) -+ return -ENODEV; -+ -+ if (devnum == MDIO_MMD_VEND2 && regnum > MDIO_STAT2) -+ return r8168_phy_ocp_read(tp, regnum); -+ -+ return 0; -+} -+ -+static int r8169_mdio_write_reg_c45(struct mii_bus *mii_bus, int addr, -+ int devnum, int regnum, u16 val) -+{ -+ struct rtl8169_private *tp = mii_bus->priv; -+ -+ if (addr > 0 || devnum != MDIO_MMD_VEND2 || regnum <= MDIO_STAT2) -+ return -ENODEV; -+ -+ r8168_phy_ocp_write(tp, regnum, val); -+ -+ return 0; -+} -+ - static int r8169_mdio_register(struct rtl8169_private *tp) - { - struct pci_dev *pdev = tp->pci_dev; -@@ -5255,6 +5282,11 @@ static int r8169_mdio_register(struct rt - new_bus->read = r8169_mdio_read_reg; - new_bus->write = r8169_mdio_write_reg; - -+ if (tp->mac_version >= RTL_GIGA_MAC_VER_40) { -+ new_bus->read_c45 = r8169_mdio_read_reg_c45; -+ new_bus->write_c45 = r8169_mdio_write_reg_c45; -+ } -+ - ret = devm_mdiobus_register(&pdev->dev, new_bus); - if (ret) - return ret; diff --git a/target/linux/generic/backport-6.18/780-30-v6.15-r8169-increase-max-jumbo-packet-size-on-RTL8125-RTL8.patch b/target/linux/generic/backport-6.18/780-30-v6.15-r8169-increase-max-jumbo-packet-size-on-RTL8125-RTL8.patch deleted file mode 100644 index 852c9a3da7..0000000000 --- a/target/linux/generic/backport-6.18/780-30-v6.15-r8169-increase-max-jumbo-packet-size-on-RTL8125-RTL8.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 473367a5ffe1607a61be481e2feda684eb5faea9 Mon Sep 17 00:00:00 2001 -From: Heiner Kallweit -Date: Fri, 7 Mar 2025 08:29:47 +0100 -Subject: [PATCH] r8169: increase max jumbo packet size on RTL8125/RTL8126 - -Realtek confirmed that all RTL8125/RTL8126 chip versions support up to -16K jumbo packets. Reflect this in the driver. - -Tested by Rui on RTL8125B with 12K jumbo packets. - -Suggested-by: Rui Salvaterra -Tested-by: Rui Salvaterra -Signed-off-by: Heiner Kallweit -Reviewed-by: Simon Horman -Link: https://patch.msgid.link/396762ad-cc65-4e60-b01e-8847db89e98b@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/realtek/r8169_main.c | 4 ++++ - 1 file changed, 4 insertions(+) - ---- a/drivers/net/ethernet/realtek/r8169_main.c -+++ b/drivers/net/ethernet/realtek/r8169_main.c -@@ -89,6 +89,7 @@ - #define JUMBO_6K (6 * SZ_1K - VLAN_ETH_HLEN - ETH_FCS_LEN) - #define JUMBO_7K (7 * SZ_1K - VLAN_ETH_HLEN - ETH_FCS_LEN) - #define JUMBO_9K (9 * SZ_1K - VLAN_ETH_HLEN - ETH_FCS_LEN) -+#define JUMBO_16K (SZ_16K - VLAN_ETH_HLEN - ETH_FCS_LEN) - - static const struct { - const char *name; -@@ -5384,6 +5385,9 @@ static int rtl_jumbo_max(struct rtl8169_ - /* RTL8168c */ - case RTL_GIGA_MAC_VER_18 ... RTL_GIGA_MAC_VER_24: - return JUMBO_6K; -+ /* RTL8125/8126 */ -+ case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_71: -+ return JUMBO_16K; - default: - return JUMBO_9K; - } diff --git a/target/linux/generic/backport-6.18/780-31-v6.15-r8169-switch-away-from-deprecated-pcim_iomap_table.patch b/target/linux/generic/backport-6.18/780-31-v6.15-r8169-switch-away-from-deprecated-pcim_iomap_table.patch deleted file mode 100644 index 0721247508..0000000000 --- a/target/linux/generic/backport-6.18/780-31-v6.15-r8169-switch-away-from-deprecated-pcim_iomap_table.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 34e5ededf4b8ad4c9e58f0cab8596e26c8fa59a2 Mon Sep 17 00:00:00 2001 -From: Heiner Kallweit -Date: Wed, 12 Mar 2025 20:21:42 +0100 -Subject: [PATCH] r8169: switch away from deprecated pcim_iomap_table - -Avoid using deprecated pcim_iomap_table by switching to -pcim_iomap_region. - -Signed-off-by: Heiner Kallweit -Reviewed-by: Jacob Keller -Reviewed-by: Simon Horman -Link: https://patch.msgid.link/a36b4cf3-c792-40fa-8164-5dc9d5f14dd0@gmail.com -Signed-off-by: Paolo Abeni ---- - drivers/net/ethernet/realtek/r8169_main.c | 9 ++++----- - 1 file changed, 4 insertions(+), 5 deletions(-) - ---- a/drivers/net/ethernet/realtek/r8169_main.c -+++ b/drivers/net/ethernet/realtek/r8169_main.c -@@ -5471,11 +5471,10 @@ static int rtl_init_one(struct pci_dev * - if (region < 0) - return dev_err_probe(&pdev->dev, -ENODEV, "no MMIO resource found\n"); - -- rc = pcim_iomap_regions(pdev, BIT(region), KBUILD_MODNAME); -- if (rc < 0) -- return dev_err_probe(&pdev->dev, rc, "cannot remap MMIO, aborting\n"); -- -- tp->mmio_addr = pcim_iomap_table(pdev)[region]; -+ tp->mmio_addr = pcim_iomap_region(pdev, region, KBUILD_MODNAME); -+ if (IS_ERR(tp->mmio_addr)) -+ return dev_err_probe(&pdev->dev, PTR_ERR(tp->mmio_addr), -+ "cannot remap MMIO, aborting\n"); - - txconfig = RTL_R32(tp, TxConfig); - if (txconfig == ~0U) diff --git a/target/linux/generic/backport-6.18/780-32-v6.15-r8169-enable-RTL8168H-RTL8168EP-RTL8168FP-ASPM-suppo.patch b/target/linux/generic/backport-6.18/780-32-v6.15-r8169-enable-RTL8168H-RTL8168EP-RTL8168FP-ASPM-suppo.patch deleted file mode 100644 index 331d296355..0000000000 --- a/target/linux/generic/backport-6.18/780-32-v6.15-r8169-enable-RTL8168H-RTL8168EP-RTL8168FP-ASPM-suppo.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 3d9b8ac5341269d31e59fd5d58d47266ac78bc32 Mon Sep 17 00:00:00 2001 -From: ChunHao Lin -Date: Tue, 18 Mar 2025 16:37:20 +0800 -Subject: [PATCH] r8169: enable RTL8168H/RTL8168EP/RTL8168FP ASPM support - -This patch will enable RTL8168H/RTL8168EP/RTL8168FP ASPM support on -the platforms that have tested with ASPM enabled. - -Signed-off-by: ChunHao Lin -Reviewed-by: Heiner Kallweit -Link: https://patch.msgid.link/20250318083721.4127-2-hau@realtek.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/realtek/r8169_main.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/net/ethernet/realtek/r8169_main.c -+++ b/drivers/net/ethernet/realtek/r8169_main.c -@@ -5422,7 +5422,7 @@ done: - /* register is set if system vendor successfully tested ASPM 1.2 */ - static bool rtl_aspm_is_safe(struct rtl8169_private *tp) - { -- if (tp->mac_version >= RTL_GIGA_MAC_VER_61 && -+ if (tp->mac_version >= RTL_GIGA_MAC_VER_46 && - r8168_mac_ocp_read(tp, 0xc0b2) & 0xf) - return true; - diff --git a/target/linux/generic/backport-6.18/780-34-v6.16-r8169-add-helper-rtl_csi_mod-for-accessing-extended.patch b/target/linux/generic/backport-6.18/780-34-v6.16-r8169-add-helper-rtl_csi_mod-for-accessing-extended.patch deleted file mode 100644 index 383f9eb5f7..0000000000 --- a/target/linux/generic/backport-6.18/780-34-v6.16-r8169-add-helper-rtl_csi_mod-for-accessing-extended.patch +++ /dev/null @@ -1,74 +0,0 @@ -From 8c40d99e5f43e0545a3f4fea9156313847e2eb79 Mon Sep 17 00:00:00 2001 -From: Heiner Kallweit -Date: Wed, 9 Apr 2025 21:05:37 +0200 -Subject: [PATCH] r8169: add helper rtl_csi_mod for accessing extended config - space - -Add a helper for the Realtek-specific mechanism for accessing extended -config space if native access isn't possible. -This avoids code duplication. - -Signed-off-by: Heiner Kallweit -Link: https://patch.msgid.link/b368fd91-57d7-4cb5-9342-98b4d8fe9aea@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/realtek/r8169_main.c | 26 ++++++++++++++--------- - 1 file changed, 16 insertions(+), 10 deletions(-) - ---- a/drivers/net/ethernet/realtek/r8169_main.c -+++ b/drivers/net/ethernet/realtek/r8169_main.c -@@ -2849,10 +2849,23 @@ static u32 rtl_csi_read(struct rtl8169_p - RTL_R32(tp, CSIDR) : ~0; - } - -+static void rtl_csi_mod(struct rtl8169_private *tp, int addr, -+ u32 mask, u32 set) -+{ -+ u32 val; -+ -+ WARN(addr % 4, "Invalid CSI address %#x\n", addr); -+ -+ netdev_notice_once(tp->dev, -+ "No native access to PCI extended config space, falling back to CSI\n"); -+ -+ val = rtl_csi_read(tp, addr); -+ rtl_csi_write(tp, addr, (val & ~mask) | set); -+} -+ - static void rtl_disable_zrxdc_timeout(struct rtl8169_private *tp) - { - struct pci_dev *pdev = tp->pci_dev; -- u32 csi; - int rc; - u8 val; - -@@ -2869,16 +2882,12 @@ static void rtl_disable_zrxdc_timeout(st - } - } - -- netdev_notice_once(tp->dev, -- "No native access to PCI extended config space, falling back to CSI\n"); -- csi = rtl_csi_read(tp, RTL_GEN3_RELATED_OFF); -- rtl_csi_write(tp, RTL_GEN3_RELATED_OFF, csi & ~RTL_GEN3_ZRXDC_NONCOMPL); -+ rtl_csi_mod(tp, RTL_GEN3_RELATED_OFF, RTL_GEN3_ZRXDC_NONCOMPL, 0); - } - - static void rtl_set_aspm_entry_latency(struct rtl8169_private *tp, u8 val) - { - struct pci_dev *pdev = tp->pci_dev; -- u32 csi; - - /* According to Realtek the value at config space address 0x070f - * controls the L0s/L1 entrance latency. We try standard ECAM access -@@ -2890,10 +2899,7 @@ static void rtl_set_aspm_entry_latency(s - pci_write_config_byte(pdev, 0x070f, val) == PCIBIOS_SUCCESSFUL) - return; - -- netdev_notice_once(tp->dev, -- "No native access to PCI extended config space, falling back to CSI\n"); -- csi = rtl_csi_read(tp, 0x070c) & 0x00ffffff; -- rtl_csi_write(tp, 0x070c, csi | val << 24); -+ rtl_csi_mod(tp, 0x070c, 0xff000000, val << 24); - } - - static void rtl_set_def_aspm_entry_latency(struct rtl8169_private *tp) diff --git a/target/linux/generic/backport-6.18/780-35-v6.16-r8169-add-helper-rtl8125_phy_param.patch b/target/linux/generic/backport-6.18/780-35-v6.16-r8169-add-helper-rtl8125_phy_param.patch deleted file mode 100644 index 30ebb4b6f4..0000000000 --- a/target/linux/generic/backport-6.18/780-35-v6.16-r8169-add-helper-rtl8125_phy_param.patch +++ /dev/null @@ -1,82 +0,0 @@ -From 0c49baf099ba2147a6ff3bbdc3197c6ddbee5469 Mon Sep 17 00:00:00 2001 -From: Heiner Kallweit -Date: Wed, 9 Apr 2025 21:14:47 +0200 -Subject: [PATCH] r8169: add helper rtl8125_phy_param - -The integrated PHY's of RTL8125/8126 have an own mechanism to access -PHY parameters, similar to what r8168g_phy_param does on earlier PHY -versions. Add helper rtl8125_phy_param to simplify the code. - -Signed-off-by: Heiner Kallweit -Link: https://patch.msgid.link/847b7356-12d6-441b-ade9-4b6e1539b84a@gmail.com -Signed-off-by: Jakub Kicinski ---- - .../net/ethernet/realtek/r8169_phy_config.c | 36 +++++++++---------- - 1 file changed, 16 insertions(+), 20 deletions(-) - ---- a/drivers/net/ethernet/realtek/r8169_phy_config.c -+++ b/drivers/net/ethernet/realtek/r8169_phy_config.c -@@ -50,6 +50,15 @@ static void r8168g_phy_param(struct phy_ - phy_restore_page(phydev, oldpage, 0); - } - -+static void rtl8125_phy_param(struct phy_device *phydev, u16 parm, -+ u16 mask, u16 val) -+{ -+ phy_lock_mdio_bus(phydev); -+ __phy_write_mmd(phydev, MDIO_MMD_VEND2, 0xb87c, parm); -+ __phy_modify_mmd(phydev, MDIO_MMD_VEND2, 0xb87e, mask, val); -+ phy_unlock_mdio_bus(phydev); -+} -+ - struct phy_reg { - u16 reg; - u16 val; -@@ -1004,12 +1013,8 @@ static void rtl8125a_2_hw_phy_config(str - phy_write_paged(phydev, 0xac5, 0x16, 0x01ff); - phy_modify_paged(phydev, 0xac8, 0x15, 0x00f0, 0x0030); - -- phy_write(phydev, 0x1f, 0x0b87); -- phy_write(phydev, 0x16, 0x80a2); -- phy_write(phydev, 0x17, 0x0153); -- phy_write(phydev, 0x16, 0x809c); -- phy_write(phydev, 0x17, 0x0153); -- phy_write(phydev, 0x1f, 0x0000); -+ rtl8125_phy_param(phydev, 0x80a2, 0xffff, 0x0153); -+ rtl8125_phy_param(phydev, 0x809c, 0xffff, 0x0153); - - phy_write(phydev, 0x1f, 0x0a43); - phy_write(phydev, 0x13, 0x81B3); -@@ -1061,14 +1066,9 @@ static void rtl8125b_hw_phy_config(struc - phy_modify_paged(phydev, 0xac4, 0x13, 0x00f0, 0x0090); - phy_modify_paged(phydev, 0xad3, 0x10, 0x0003, 0x0001); - -- phy_write(phydev, 0x1f, 0x0b87); -- phy_write(phydev, 0x16, 0x80f5); -- phy_write(phydev, 0x17, 0x760e); -- phy_write(phydev, 0x16, 0x8107); -- phy_write(phydev, 0x17, 0x360e); -- phy_write(phydev, 0x16, 0x8551); -- phy_modify(phydev, 0x17, 0xff00, 0x0800); -- phy_write(phydev, 0x1f, 0x0000); -+ rtl8125_phy_param(phydev, 0x80f5, 0xffff, 0x760e); -+ rtl8125_phy_param(phydev, 0x8107, 0xffff, 0x360e); -+ rtl8125_phy_param(phydev, 0x8551, 0xff00, 0x0800); - - phy_modify_paged(phydev, 0xbf0, 0x10, 0xe000, 0xa000); - phy_modify_paged(phydev, 0xbf4, 0x13, 0x0f00, 0x0300); -@@ -1110,12 +1110,8 @@ static void rtl8125bp_hw_phy_config(stru - - r8168g_phy_param(phydev, 0x8010, 0x0800, 0x0000); - -- phy_write(phydev, 0x1f, 0x0b87); -- phy_write(phydev, 0x16, 0x8088); -- phy_modify(phydev, 0x17, 0xff00, 0x9000); -- phy_write(phydev, 0x16, 0x808f); -- phy_modify(phydev, 0x17, 0xff00, 0x9000); -- phy_write(phydev, 0x1f, 0x0000); -+ rtl8125_phy_param(phydev, 0x8088, 0xff00, 0x9000); -+ rtl8125_phy_param(phydev, 0x808f, 0xff00, 0x9000); - - r8168g_phy_param(phydev, 0x8174, 0x2000, 0x1800); - diff --git a/target/linux/generic/backport-6.18/780-36-v6.16-r8169-refactor-chip-version-detection.patch b/target/linux/generic/backport-6.18/780-36-v6.16-r8169-refactor-chip-version-detection.patch deleted file mode 100644 index ae9cfb8a66..0000000000 --- a/target/linux/generic/backport-6.18/780-36-v6.16-r8169-refactor-chip-version-detection.patch +++ /dev/null @@ -1,401 +0,0 @@ -From 2b065c098c37a3ed28df7c3be59dca61b9da8402 Mon Sep 17 00:00:00 2001 -From: Heiner Kallweit -Date: Tue, 15 Apr 2025 21:29:34 +0200 -Subject: [PATCH] r8169: refactor chip version detection - -Refactor chip version detection and merge both configuration tables. -Apart from reducing the code by a third, this paves the way for -merging chip version handling if only difference is the firmware. - -Signed-off-by: Heiner Kallweit -Reviewed-by: Michal Swiatkowski -Link: https://patch.msgid.link/1fea533a-dd5a-4198-a9e2-895e11083947@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/realtek/r8169_main.c | 325 +++++++++------------- - 1 file changed, 128 insertions(+), 197 deletions(-) - ---- a/drivers/net/ethernet/realtek/r8169_main.c -+++ b/drivers/net/ethernet/realtek/r8169_main.c -@@ -91,61 +91,114 @@ - #define JUMBO_9K (9 * SZ_1K - VLAN_ETH_HLEN - ETH_FCS_LEN) - #define JUMBO_16K (SZ_16K - VLAN_ETH_HLEN - ETH_FCS_LEN) - --static const struct { -+static const struct rtl_chip_info { -+ u16 mask; -+ u16 val; -+ enum mac_version mac_version; - const char *name; - const char *fw_name; - } rtl_chip_infos[] = { -- /* PCI devices. */ -- [RTL_GIGA_MAC_VER_02] = {"RTL8169s" }, -- [RTL_GIGA_MAC_VER_03] = {"RTL8110s" }, -- [RTL_GIGA_MAC_VER_04] = {"RTL8169sb/8110sb" }, -- [RTL_GIGA_MAC_VER_05] = {"RTL8169sc/8110sc" }, -- [RTL_GIGA_MAC_VER_06] = {"RTL8169sc/8110sc" }, -- /* PCI-E devices. */ -- [RTL_GIGA_MAC_VER_07] = {"RTL8102e" }, -- [RTL_GIGA_MAC_VER_08] = {"RTL8102e" }, -- [RTL_GIGA_MAC_VER_09] = {"RTL8102e/RTL8103e" }, -- [RTL_GIGA_MAC_VER_10] = {"RTL8101e/RTL8100e" }, -- [RTL_GIGA_MAC_VER_14] = {"RTL8401" }, -- [RTL_GIGA_MAC_VER_17] = {"RTL8168b/8111b" }, -- [RTL_GIGA_MAC_VER_18] = {"RTL8168cp/8111cp" }, -- [RTL_GIGA_MAC_VER_19] = {"RTL8168c/8111c" }, -- [RTL_GIGA_MAC_VER_20] = {"RTL8168c/8111c" }, -- [RTL_GIGA_MAC_VER_21] = {"RTL8168c/8111c" }, -- [RTL_GIGA_MAC_VER_22] = {"RTL8168c/8111c" }, -- [RTL_GIGA_MAC_VER_23] = {"RTL8168cp/8111cp" }, -- [RTL_GIGA_MAC_VER_24] = {"RTL8168cp/8111cp" }, -- [RTL_GIGA_MAC_VER_25] = {"RTL8168d/8111d", FIRMWARE_8168D_1}, -- [RTL_GIGA_MAC_VER_26] = {"RTL8168d/8111d", FIRMWARE_8168D_2}, -- [RTL_GIGA_MAC_VER_28] = {"RTL8168dp/8111dp" }, -- [RTL_GIGA_MAC_VER_29] = {"RTL8105e", FIRMWARE_8105E_1}, -- [RTL_GIGA_MAC_VER_30] = {"RTL8105e", FIRMWARE_8105E_1}, -- [RTL_GIGA_MAC_VER_31] = {"RTL8168dp/8111dp" }, -- [RTL_GIGA_MAC_VER_32] = {"RTL8168e/8111e", FIRMWARE_8168E_1}, -- [RTL_GIGA_MAC_VER_33] = {"RTL8168e/8111e", FIRMWARE_8168E_2}, -- [RTL_GIGA_MAC_VER_34] = {"RTL8168evl/8111evl", FIRMWARE_8168E_3}, -- [RTL_GIGA_MAC_VER_35] = {"RTL8168f/8111f", FIRMWARE_8168F_1}, -- [RTL_GIGA_MAC_VER_36] = {"RTL8168f/8111f", FIRMWARE_8168F_2}, -- [RTL_GIGA_MAC_VER_37] = {"RTL8402", FIRMWARE_8402_1 }, -- [RTL_GIGA_MAC_VER_38] = {"RTL8411", FIRMWARE_8411_1 }, -- [RTL_GIGA_MAC_VER_39] = {"RTL8106e", FIRMWARE_8106E_1}, -- [RTL_GIGA_MAC_VER_40] = {"RTL8168g/8111g", FIRMWARE_8168G_2}, -- [RTL_GIGA_MAC_VER_42] = {"RTL8168gu/8111gu", FIRMWARE_8168G_3}, -- [RTL_GIGA_MAC_VER_43] = {"RTL8106eus", FIRMWARE_8106E_2}, -- [RTL_GIGA_MAC_VER_44] = {"RTL8411b", FIRMWARE_8411_2 }, -- [RTL_GIGA_MAC_VER_46] = {"RTL8168h/8111h", FIRMWARE_8168H_2}, -- [RTL_GIGA_MAC_VER_48] = {"RTL8107e", FIRMWARE_8107E_2}, -- [RTL_GIGA_MAC_VER_51] = {"RTL8168ep/8111ep" }, -- [RTL_GIGA_MAC_VER_52] = {"RTL8168fp/RTL8117", FIRMWARE_8168FP_3}, -- [RTL_GIGA_MAC_VER_53] = {"RTL8168fp/RTL8117", }, -- [RTL_GIGA_MAC_VER_61] = {"RTL8125A", FIRMWARE_8125A_3}, -- /* reserve 62 for CFG_METHOD_4 in the vendor driver */ -- [RTL_GIGA_MAC_VER_63] = {"RTL8125B", FIRMWARE_8125B_2}, -- [RTL_GIGA_MAC_VER_64] = {"RTL8125D", FIRMWARE_8125D_1}, -- [RTL_GIGA_MAC_VER_65] = {"RTL8125D", FIRMWARE_8125D_2}, -- [RTL_GIGA_MAC_VER_66] = {"RTL8125BP", FIRMWARE_8125BP_2}, -- [RTL_GIGA_MAC_VER_70] = {"RTL8126A", FIRMWARE_8126A_2}, -- [RTL_GIGA_MAC_VER_71] = {"RTL8126A", FIRMWARE_8126A_3}, -+ /* 8126A family. */ -+ { 0x7cf, 0x64a, RTL_GIGA_MAC_VER_71, "RTL8126A", FIRMWARE_8126A_3 }, -+ { 0x7cf, 0x649, RTL_GIGA_MAC_VER_70, "RTL8126A", FIRMWARE_8126A_2 }, -+ -+ /* 8125BP family. */ -+ { 0x7cf, 0x681, RTL_GIGA_MAC_VER_66, "RTL8125BP", FIRMWARE_8125BP_2 }, -+ -+ /* 8125D family. */ -+ { 0x7cf, 0x689, RTL_GIGA_MAC_VER_65, "RTL8125D", FIRMWARE_8125D_2 }, -+ { 0x7cf, 0x688, RTL_GIGA_MAC_VER_64, "RTL8125D", FIRMWARE_8125D_1 }, -+ -+ /* 8125B family. */ -+ { 0x7cf, 0x641, RTL_GIGA_MAC_VER_63, "RTL8125B", FIRMWARE_8125B_2 }, -+ -+ /* 8125A family. */ -+ { 0x7cf, 0x609, RTL_GIGA_MAC_VER_61, "RTL8125A", FIRMWARE_8125A_3 }, -+ -+ /* RTL8117 */ -+ { 0x7cf, 0x54b, RTL_GIGA_MAC_VER_53, "RTL8168fp/RTL8117" }, -+ { 0x7cf, 0x54a, RTL_GIGA_MAC_VER_52, "RTL8168fp/RTL8117", -+ FIRMWARE_8168FP_3 }, -+ -+ /* 8168EP family. */ -+ { 0x7cf, 0x502, RTL_GIGA_MAC_VER_51, "RTL8168ep/8111ep" }, -+ -+ /* 8168H family. */ -+ { 0x7cf, 0x541, RTL_GIGA_MAC_VER_46, "RTL8168h/8111h", -+ FIRMWARE_8168H_2 }, -+ /* Realtek calls it RTL8168M, but it's handled like RTL8168H */ -+ { 0x7cf, 0x6c0, RTL_GIGA_MAC_VER_46, "RTL8168M", FIRMWARE_8168H_2 }, -+ -+ /* 8168G family. */ -+ { 0x7cf, 0x5c8, RTL_GIGA_MAC_VER_44, "RTL8411b", FIRMWARE_8411_2 }, -+ { 0x7cf, 0x509, RTL_GIGA_MAC_VER_42, "RTL8168gu/8111gu", -+ FIRMWARE_8168G_3 }, -+ { 0x7cf, 0x4c0, RTL_GIGA_MAC_VER_40, "RTL8168g/8111g", -+ FIRMWARE_8168G_2 }, -+ -+ /* 8168F family. */ -+ { 0x7c8, 0x488, RTL_GIGA_MAC_VER_38, "RTL8411", FIRMWARE_8411_1 }, -+ { 0x7cf, 0x481, RTL_GIGA_MAC_VER_36, "RTL8168f/8111f", -+ FIRMWARE_8168F_2 }, -+ { 0x7cf, 0x480, RTL_GIGA_MAC_VER_35, "RTL8168f/8111f", -+ FIRMWARE_8168F_1 }, -+ -+ /* 8168E family. */ -+ { 0x7c8, 0x2c8, RTL_GIGA_MAC_VER_34, "RTL8168evl/8111evl", -+ FIRMWARE_8168E_3 }, -+ { 0x7cf, 0x2c1, RTL_GIGA_MAC_VER_32, "RTL8168e/8111e", -+ FIRMWARE_8168E_1 }, -+ { 0x7c8, 0x2c0, RTL_GIGA_MAC_VER_33, "RTL8168e/8111e", -+ FIRMWARE_8168E_2 }, -+ -+ /* 8168D family. */ -+ { 0x7cf, 0x281, RTL_GIGA_MAC_VER_25, "RTL8168d/8111d", -+ FIRMWARE_8168D_1 }, -+ { 0x7c8, 0x280, RTL_GIGA_MAC_VER_26, "RTL8168d/8111d", -+ FIRMWARE_8168D_2 }, -+ -+ /* 8168DP family. */ -+ { 0x7cf, 0x28a, RTL_GIGA_MAC_VER_28, "RTL8168dp/8111dp" }, -+ { 0x7cf, 0x28b, RTL_GIGA_MAC_VER_31, "RTL8168dp/8111dp" }, -+ -+ /* 8168C family. */ -+ { 0x7cf, 0x3c9, RTL_GIGA_MAC_VER_23, "RTL8168cp/8111cp" }, -+ { 0x7cf, 0x3c8, RTL_GIGA_MAC_VER_18, "RTL8168cp/8111cp" }, -+ { 0x7c8, 0x3c8, RTL_GIGA_MAC_VER_24, "RTL8168cp/8111cp" }, -+ { 0x7cf, 0x3c0, RTL_GIGA_MAC_VER_19, "RTL8168c/8111c" }, -+ { 0x7cf, 0x3c2, RTL_GIGA_MAC_VER_20, "RTL8168c/8111c" }, -+ { 0x7cf, 0x3c3, RTL_GIGA_MAC_VER_21, "RTL8168c/8111c" }, -+ { 0x7c8, 0x3c0, RTL_GIGA_MAC_VER_22, "RTL8168c/8111c" }, -+ -+ /* 8168B family. */ -+ { 0x7c8, 0x380, RTL_GIGA_MAC_VER_17, "RTL8168b/8111b" }, -+ /* This one is very old and rare, support has been removed. -+ * { 0x7c8, 0x300, RTL_GIGA_MAC_VER_11, "RTL8168b/8111b" }, -+ */ -+ -+ /* 8101 family. */ -+ { 0x7c8, 0x448, RTL_GIGA_MAC_VER_39, "RTL8106e", FIRMWARE_8106E_1 }, -+ { 0x7c8, 0x440, RTL_GIGA_MAC_VER_37, "RTL8402", FIRMWARE_8402_1 }, -+ { 0x7cf, 0x409, RTL_GIGA_MAC_VER_29, "RTL8105e", FIRMWARE_8105E_1 }, -+ { 0x7c8, 0x408, RTL_GIGA_MAC_VER_30, "RTL8105e", FIRMWARE_8105E_1 }, -+ { 0x7cf, 0x349, RTL_GIGA_MAC_VER_08, "RTL8102e" }, -+ { 0x7cf, 0x249, RTL_GIGA_MAC_VER_08, "RTL8102e" }, -+ { 0x7cf, 0x348, RTL_GIGA_MAC_VER_07, "RTL8102e" }, -+ { 0x7cf, 0x248, RTL_GIGA_MAC_VER_07, "RTL8102e" }, -+ { 0x7cf, 0x240, RTL_GIGA_MAC_VER_14, "RTL8401" }, -+ { 0x7c8, 0x348, RTL_GIGA_MAC_VER_09, "RTL8102e/RTL8103e" }, -+ { 0x7c8, 0x248, RTL_GIGA_MAC_VER_09, "RTL8102e/RTL8103e" }, -+ { 0x7c8, 0x340, RTL_GIGA_MAC_VER_10, "RTL8101e/RTL8100e" }, -+ -+ /* 8110 family. */ -+ { 0xfc8, 0x980, RTL_GIGA_MAC_VER_06, "RTL8169sc/8110sc" }, -+ { 0xfc8, 0x180, RTL_GIGA_MAC_VER_05, "RTL8169sc/8110sc" }, -+ { 0xfc8, 0x100, RTL_GIGA_MAC_VER_04, "RTL8169sb/8110sb" }, -+ { 0xfc8, 0x040, RTL_GIGA_MAC_VER_03, "RTL8110s" }, -+ { 0xfc8, 0x008, RTL_GIGA_MAC_VER_02, "RTL8169s" }, -+ -+ /* Catch-all */ -+ { 0x000, 0x000, RTL_GIGA_MAC_NONE } - }; - - static const struct pci_device_id rtl8169_pci_tbl[] = { -@@ -2265,151 +2318,30 @@ static const struct ethtool_ops rtl8169_ - .get_eth_ctrl_stats = rtl8169_get_eth_ctrl_stats, - }; - --static enum mac_version rtl8169_get_mac_version(u16 xid, bool gmii) -+static const struct rtl_chip_info *rtl8169_get_chip_version(u16 xid, bool gmii) - { -- /* -- * The driver currently handles the 8168Bf and the 8168Be identically -- * but they can be identified more specifically through the test below -- * if needed: -- * -- * (RTL_R32(tp, TxConfig) & 0x700000) == 0x500000 ? 8168Bf : 8168Be -- * -- * Same thing for the 8101Eb and the 8101Ec: -- * -- * (RTL_R32(tp, TxConfig) & 0x700000) == 0x200000 ? 8101Eb : 8101Ec -- */ -- static const struct rtl_mac_info { -- u16 mask; -- u16 val; -- enum mac_version ver; -- } mac_info[] = { -- /* 8126A family. */ -- { 0x7cf, 0x64a, RTL_GIGA_MAC_VER_71 }, -- { 0x7cf, 0x649, RTL_GIGA_MAC_VER_70 }, -- -- /* 8125BP family. */ -- { 0x7cf, 0x681, RTL_GIGA_MAC_VER_66 }, -- -- /* 8125D family. */ -- { 0x7cf, 0x689, RTL_GIGA_MAC_VER_65 }, -- { 0x7cf, 0x688, RTL_GIGA_MAC_VER_64 }, -- -- /* 8125B family. */ -- { 0x7cf, 0x641, RTL_GIGA_MAC_VER_63 }, -- -- /* 8125A family. */ -- { 0x7cf, 0x609, RTL_GIGA_MAC_VER_61 }, -- /* It seems only XID 609 made it to the mass market. -- * { 0x7cf, 0x608, RTL_GIGA_MAC_VER_60 }, -- * { 0x7c8, 0x608, RTL_GIGA_MAC_VER_61 }, -- */ -- -- /* RTL8117 */ -- { 0x7cf, 0x54b, RTL_GIGA_MAC_VER_53 }, -- { 0x7cf, 0x54a, RTL_GIGA_MAC_VER_52 }, -- -- /* 8168EP family. */ -- { 0x7cf, 0x502, RTL_GIGA_MAC_VER_51 }, -- /* It seems this chip version never made it to -- * the wild. Let's disable detection. -- * { 0x7cf, 0x501, RTL_GIGA_MAC_VER_50 }, -- * { 0x7cf, 0x500, RTL_GIGA_MAC_VER_49 }, -- */ -- -- /* 8168H family. */ -- { 0x7cf, 0x541, RTL_GIGA_MAC_VER_46 }, -- /* It seems this chip version never made it to -- * the wild. Let's disable detection. -- * { 0x7cf, 0x540, RTL_GIGA_MAC_VER_45 }, -- */ -- /* Realtek calls it RTL8168M, but it's handled like RTL8168H */ -- { 0x7cf, 0x6c0, RTL_GIGA_MAC_VER_46 }, -- -- /* 8168G family. */ -- { 0x7cf, 0x5c8, RTL_GIGA_MAC_VER_44 }, -- { 0x7cf, 0x509, RTL_GIGA_MAC_VER_42 }, -- /* It seems this chip version never made it to -- * the wild. Let's disable detection. -- * { 0x7cf, 0x4c1, RTL_GIGA_MAC_VER_41 }, -- */ -- { 0x7cf, 0x4c0, RTL_GIGA_MAC_VER_40 }, -- -- /* 8168F family. */ -- { 0x7c8, 0x488, RTL_GIGA_MAC_VER_38 }, -- { 0x7cf, 0x481, RTL_GIGA_MAC_VER_36 }, -- { 0x7cf, 0x480, RTL_GIGA_MAC_VER_35 }, -- -- /* 8168E family. */ -- { 0x7c8, 0x2c8, RTL_GIGA_MAC_VER_34 }, -- { 0x7cf, 0x2c1, RTL_GIGA_MAC_VER_32 }, -- { 0x7c8, 0x2c0, RTL_GIGA_MAC_VER_33 }, -- -- /* 8168D family. */ -- { 0x7cf, 0x281, RTL_GIGA_MAC_VER_25 }, -- { 0x7c8, 0x280, RTL_GIGA_MAC_VER_26 }, -- -- /* 8168DP family. */ -- /* It seems this early RTL8168dp version never made it to -- * the wild. Support has been removed. -- * { 0x7cf, 0x288, RTL_GIGA_MAC_VER_27 }, -- */ -- { 0x7cf, 0x28a, RTL_GIGA_MAC_VER_28 }, -- { 0x7cf, 0x28b, RTL_GIGA_MAC_VER_31 }, -- -- /* 8168C family. */ -- { 0x7cf, 0x3c9, RTL_GIGA_MAC_VER_23 }, -- { 0x7cf, 0x3c8, RTL_GIGA_MAC_VER_18 }, -- { 0x7c8, 0x3c8, RTL_GIGA_MAC_VER_24 }, -- { 0x7cf, 0x3c0, RTL_GIGA_MAC_VER_19 }, -- { 0x7cf, 0x3c2, RTL_GIGA_MAC_VER_20 }, -- { 0x7cf, 0x3c3, RTL_GIGA_MAC_VER_21 }, -- { 0x7c8, 0x3c0, RTL_GIGA_MAC_VER_22 }, -- -- /* 8168B family. */ -- { 0x7c8, 0x380, RTL_GIGA_MAC_VER_17 }, -- /* This one is very old and rare, support has been removed. -- * { 0x7c8, 0x300, RTL_GIGA_MAC_VER_11 }, -- */ -- -- /* 8101 family. */ -- { 0x7c8, 0x448, RTL_GIGA_MAC_VER_39 }, -- { 0x7c8, 0x440, RTL_GIGA_MAC_VER_37 }, -- { 0x7cf, 0x409, RTL_GIGA_MAC_VER_29 }, -- { 0x7c8, 0x408, RTL_GIGA_MAC_VER_30 }, -- { 0x7cf, 0x349, RTL_GIGA_MAC_VER_08 }, -- { 0x7cf, 0x249, RTL_GIGA_MAC_VER_08 }, -- { 0x7cf, 0x348, RTL_GIGA_MAC_VER_07 }, -- { 0x7cf, 0x248, RTL_GIGA_MAC_VER_07 }, -- { 0x7cf, 0x240, RTL_GIGA_MAC_VER_14 }, -- { 0x7c8, 0x348, RTL_GIGA_MAC_VER_09 }, -- { 0x7c8, 0x248, RTL_GIGA_MAC_VER_09 }, -- { 0x7c8, 0x340, RTL_GIGA_MAC_VER_10 }, -- -- /* 8110 family. */ -- { 0xfc8, 0x980, RTL_GIGA_MAC_VER_06 }, -- { 0xfc8, 0x180, RTL_GIGA_MAC_VER_05 }, -- { 0xfc8, 0x100, RTL_GIGA_MAC_VER_04 }, -- { 0xfc8, 0x040, RTL_GIGA_MAC_VER_03 }, -- { 0xfc8, 0x008, RTL_GIGA_MAC_VER_02 }, -- -- /* Catch-all */ -- { 0x000, 0x000, RTL_GIGA_MAC_NONE } -+ /* Chips combining a 1Gbps MAC with a 100Mbps PHY */ -+ static const struct rtl_chip_info rtl8106eus_info = { -+ .mac_version = RTL_GIGA_MAC_VER_43, -+ .name = "RTL8106eus", -+ .fw_name = FIRMWARE_8106E_2, - }; -- const struct rtl_mac_info *p = mac_info; -- enum mac_version ver; -+ static const struct rtl_chip_info rtl8107e_info = { -+ .mac_version = RTL_GIGA_MAC_VER_48, -+ .name = "RTL8107e", -+ .fw_name = FIRMWARE_8107E_2, -+ }; -+ const struct rtl_chip_info *p = rtl_chip_infos; - - while ((xid & p->mask) != p->val) - p++; -- ver = p->ver; - -- if (ver != RTL_GIGA_MAC_NONE && !gmii) { -- if (ver == RTL_GIGA_MAC_VER_42) -- ver = RTL_GIGA_MAC_VER_43; -- else if (ver == RTL_GIGA_MAC_VER_46) -- ver = RTL_GIGA_MAC_VER_48; -- } -+ if (p->mac_version == RTL_GIGA_MAC_VER_42 && !gmii) -+ return &rtl8106eus_info; -+ if (p->mac_version == RTL_GIGA_MAC_VER_46 && !gmii) -+ return &rtl8107e_info; - -- return ver; -+ return p; - } - - static void rtl_release_firmware(struct rtl8169_private *tp) -@@ -5437,9 +5369,9 @@ static bool rtl_aspm_is_safe(struct rtl8 - - static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) - { -+ const struct rtl_chip_info *chip; - struct rtl8169_private *tp; - int jumbo_max, region, rc; -- enum mac_version chipset; - struct net_device *dev; - u32 txconfig; - u16 xid; -@@ -5489,12 +5421,13 @@ static int rtl_init_one(struct pci_dev * - xid = (txconfig >> 20) & 0xfcf; - - /* Identify chip attached to board */ -- chipset = rtl8169_get_mac_version(xid, tp->supports_gmii); -- if (chipset == RTL_GIGA_MAC_NONE) -+ chip = rtl8169_get_chip_version(xid, tp->supports_gmii); -+ if (chip->mac_version == RTL_GIGA_MAC_NONE) - return dev_err_probe(&pdev->dev, -ENODEV, - "unknown chip XID %03x, contact r8169 maintainers (see MAINTAINERS file)\n", - xid); -- tp->mac_version = chipset; -+ tp->mac_version = chip->mac_version; -+ tp->fw_name = chip->fw_name; - - /* Disable ASPM L1 as that cause random device stop working - * problems as well as full system hangs for some PCIe devices users. -@@ -5599,8 +5532,6 @@ static int rtl_init_one(struct pci_dev * - - rtl_set_irq_mask(tp); - -- tp->fw_name = rtl_chip_infos[chipset].fw_name; -- - tp->counters = dmam_alloc_coherent (&pdev->dev, sizeof(*tp->counters), - &tp->counters_phys_addr, - GFP_KERNEL); -@@ -5625,7 +5556,7 @@ static int rtl_init_one(struct pci_dev * - } - - netdev_info(dev, "%s, %pM, XID %03x, IRQ %d\n", -- rtl_chip_infos[chipset].name, dev->dev_addr, xid, tp->irq); -+ chip->name, dev->dev_addr, xid, tp->irq); - - if (jumbo_max) - netdev_info(dev, "jumbo features [frames: %d bytes, tx checksumming: %s]\n", diff --git a/target/linux/generic/backport-6.18/780-37-v6.16-r8169-add-RTL_GIGA_MAC_VER_LAST-to-facilitate-adding.patch b/target/linux/generic/backport-6.18/780-37-v6.16-r8169-add-RTL_GIGA_MAC_VER_LAST-to-facilitate-adding.patch deleted file mode 100644 index 6dad3f38e1..0000000000 --- a/target/linux/generic/backport-6.18/780-37-v6.16-r8169-add-RTL_GIGA_MAC_VER_LAST-to-facilitate-adding.patch +++ /dev/null @@ -1,159 +0,0 @@ -From fe733618b27a8c033f0d246c2efff56fca322656 Mon Sep 17 00:00:00 2001 -From: Heiner Kallweit -Date: Tue, 15 Apr 2025 21:39:23 +0200 -Subject: [PATCH] r8169: add RTL_GIGA_MAC_VER_LAST to facilitate adding support - for new chip versions - -Add a new mac_version enum value RTL_GIGA_MAC_VER_LAST. Benefit is that -when adding support for a new chip version we have to touch less code, -except something changes fundamentally. - -Signed-off-by: Heiner Kallweit -Reviewed-by: Simon Horman -Link: https://patch.msgid.link/06991f47-2aec-4aa2-8918-2c6e79332303@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/realtek/r8169.h | 3 ++- - drivers/net/ethernet/realtek/r8169_main.c | 28 +++++++++++------------ - 2 files changed, 16 insertions(+), 15 deletions(-) - ---- a/drivers/net/ethernet/realtek/r8169.h -+++ b/drivers/net/ethernet/realtek/r8169.h -@@ -73,7 +73,8 @@ enum mac_version { - RTL_GIGA_MAC_VER_66, - RTL_GIGA_MAC_VER_70, - RTL_GIGA_MAC_VER_71, -- RTL_GIGA_MAC_NONE -+ RTL_GIGA_MAC_NONE, -+ RTL_GIGA_MAC_VER_LAST = RTL_GIGA_MAC_NONE - 1 - }; - - struct rtl8169_private; ---- a/drivers/net/ethernet/realtek/r8169_main.c -+++ b/drivers/net/ethernet/realtek/r8169_main.c -@@ -1289,7 +1289,7 @@ static void rtl_writephy(struct rtl8169_ - case RTL_GIGA_MAC_VER_31: - r8168dp_2_mdio_write(tp, location, val); - break; -- case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_71: -+ case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_LAST: - r8168g_mdio_write(tp, location, val); - break; - default: -@@ -1304,7 +1304,7 @@ static int rtl_readphy(struct rtl8169_pr - case RTL_GIGA_MAC_VER_28: - case RTL_GIGA_MAC_VER_31: - return r8168dp_2_mdio_read(tp, location); -- case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_71: -+ case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_LAST: - return r8168g_mdio_read(tp, location); - default: - return r8169_mdio_read(tp, location); -@@ -1656,7 +1656,7 @@ static void __rtl8169_set_wol(struct rtl - break; - case RTL_GIGA_MAC_VER_34: - case RTL_GIGA_MAC_VER_37: -- case RTL_GIGA_MAC_VER_39 ... RTL_GIGA_MAC_VER_71: -+ case RTL_GIGA_MAC_VER_39 ... RTL_GIGA_MAC_VER_LAST: - r8169_mod_reg8_cond(tp, Config2, PME_SIGNAL, wolopts); - break; - default: -@@ -2129,7 +2129,7 @@ static void rtl_set_eee_txidle_timer(str - tp->tx_lpi_timer = timer_val; - r8168_mac_ocp_write(tp, 0xe048, timer_val); - break; -- case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_71: -+ case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_LAST: - tp->tx_lpi_timer = timer_val; - RTL_W16(tp, EEE_TXIDLE_TIMER_8125, timer_val); - break; -@@ -2491,7 +2491,7 @@ static void rtl_init_rxcfg(struct rtl816 - case RTL_GIGA_MAC_VER_61: - RTL_W32(tp, RxConfig, RX_FETCH_DFLT_8125 | RX_DMA_BURST); - break; -- case RTL_GIGA_MAC_VER_63 ... RTL_GIGA_MAC_VER_71: -+ case RTL_GIGA_MAC_VER_63 ... RTL_GIGA_MAC_VER_LAST: - RTL_W32(tp, RxConfig, RX_FETCH_DFLT_8125 | RX_DMA_BURST | - RX_PAUSE_SLOT_ON); - break; -@@ -2623,7 +2623,7 @@ static void rtl_wait_txrx_fifo_empty(str - case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_61: - rtl_loop_wait_high(tp, &rtl_rxtx_empty_cond, 100, 42); - break; -- case RTL_GIGA_MAC_VER_63 ... RTL_GIGA_MAC_VER_71: -+ case RTL_GIGA_MAC_VER_63 ... RTL_GIGA_MAC_VER_LAST: - RTL_W8(tp, ChipCmd, RTL_R8(tp, ChipCmd) | StopReq); - rtl_loop_wait_high(tp, &rtl_rxtx_empty_cond, 100, 42); - rtl_loop_wait_high(tp, &rtl_rxtx_empty_cond_2, 100, 42); -@@ -2895,7 +2895,7 @@ static void rtl_enable_exit_l1(struct rt - case RTL_GIGA_MAC_VER_37 ... RTL_GIGA_MAC_VER_38: - rtl_eri_set_bits(tp, 0xd4, 0x0c00); - break; -- case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_71: -+ case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_LAST: - r8168_mac_ocp_modify(tp, 0xc0ac, 0, 0x1f80); - break; - default: -@@ -2909,7 +2909,7 @@ static void rtl_disable_exit_l1(struct r - case RTL_GIGA_MAC_VER_34 ... RTL_GIGA_MAC_VER_38: - rtl_eri_clear_bits(tp, 0xd4, 0x1f00); - break; -- case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_71: -+ case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_LAST: - r8168_mac_ocp_modify(tp, 0xc0ac, 0x1f80, 0); - break; - default: -@@ -2947,7 +2947,7 @@ static void rtl_hw_aspm_clkreq_enable(st - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_46 ... RTL_GIGA_MAC_VER_48: -- case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_71: -+ case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_LAST: - /* reset ephy tx/rx disable timer */ - r8168_mac_ocp_modify(tp, 0xe094, 0xff00, 0); - /* chip can trigger L1.2 */ -@@ -2959,7 +2959,7 @@ static void rtl_hw_aspm_clkreq_enable(st - } else { - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_46 ... RTL_GIGA_MAC_VER_48: -- case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_71: -+ case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_LAST: - r8168_mac_ocp_modify(tp, 0xe092, 0x00ff, 0); - break; - default: -@@ -4091,7 +4091,7 @@ static void rtl8169_cleanup(struct rtl81 - RTL_W8(tp, ChipCmd, RTL_R8(tp, ChipCmd) | StopReq); - rtl_loop_wait_high(tp, &rtl_txcfg_empty_cond, 100, 666); - break; -- case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_71: -+ case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_LAST: - rtl_enable_rxdvgate(tp); - fsleep(2000); - break; -@@ -4248,7 +4248,7 @@ static unsigned int rtl_quirk_packet_pad - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_34: -- case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_71: -+ case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_LAST: - padto = max_t(unsigned int, padto, ETH_ZLEN); - break; - default: -@@ -5299,7 +5299,7 @@ static void rtl_hw_initialize(struct rtl - case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_48: - rtl_hw_init_8168g(tp); - break; -- case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_71: -+ case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_LAST: - rtl_hw_init_8125(tp); - break; - default: -@@ -5324,7 +5324,7 @@ static int rtl_jumbo_max(struct rtl8169_ - case RTL_GIGA_MAC_VER_18 ... RTL_GIGA_MAC_VER_24: - return JUMBO_6K; - /* RTL8125/8126 */ -- case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_71: -+ case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_LAST: - return JUMBO_16K; - default: - return JUMBO_9K; diff --git a/target/linux/generic/backport-6.18/780-38-v6.16-r8169-use-pci_prepare_to_sleep-in-rtl_shutdown.patch b/target/linux/generic/backport-6.18/780-38-v6.16-r8169-use-pci_prepare_to_sleep-in-rtl_shutdown.patch deleted file mode 100644 index 0f085f08e0..0000000000 --- a/target/linux/generic/backport-6.18/780-38-v6.16-r8169-use-pci_prepare_to_sleep-in-rtl_shutdown.patch +++ /dev/null @@ -1,37 +0,0 @@ -From b7ed5d5a78fccee96cf8919ac2c7a064c2f4c45b Mon Sep 17 00:00:00 2001 -From: Heiner Kallweit -Date: Mon, 21 Apr 2025 11:25:18 +0200 -Subject: [PATCH] r8169: use pci_prepare_to_sleep in rtl_shutdown - -Use pci_prepare_to_sleep() like PCI core does in pci_pm_suspend_noirq. -This aligns setting a low-power mode during shutdown with the handling -of the transition to system suspend. Also the transition to runtime -suspend uses pci_target_state() instead of setting D3hot unconditionally. - -Note: pci_prepare_to_sleep() uses device_may_wakeup() to check whether - device may generate wakeup events. So we don't lose anything by - not passing tp->saved_wolopts any longer. - -Signed-off-by: Heiner Kallweit -Reviewed-by: Jacob Keller -Link: https://patch.msgid.link/f573fdbd-ba6d-41c1-b68f-311d3c88db2c@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/realtek/r8169_main.c | 6 ++---- - 1 file changed, 2 insertions(+), 4 deletions(-) - ---- a/drivers/net/ethernet/realtek/r8169_main.c -+++ b/drivers/net/ethernet/realtek/r8169_main.c -@@ -5037,10 +5037,8 @@ static void rtl_shutdown(struct pci_dev - /* Restore original MAC address */ - rtl_rar_set(tp, tp->dev->perm_addr); - -- if (system_state == SYSTEM_POWER_OFF && !tp->dash_enabled) { -- pci_wake_from_d3(pdev, tp->saved_wolopts); -- pci_set_power_state(pdev, PCI_D3hot); -- } -+ if (system_state == SYSTEM_POWER_OFF && !tp->dash_enabled) -+ pci_prepare_to_sleep(pdev); - } - - static void rtl_remove_one(struct pci_dev *pdev) diff --git a/target/linux/generic/backport-6.18/780-39-v6.16-r8169-merge-chip-versions-70-and-71-RTL8126A.patch b/target/linux/generic/backport-6.18/780-39-v6.16-r8169-merge-chip-versions-70-and-71-RTL8126A.patch deleted file mode 100644 index caab6c69f1..0000000000 --- a/target/linux/generic/backport-6.18/780-39-v6.16-r8169-merge-chip-versions-70-and-71-RTL8126A.patch +++ /dev/null @@ -1,106 +0,0 @@ -From 4dec0702b8627c364a0e1f2c5b249e06709a1c24 Mon Sep 17 00:00:00 2001 -From: Heiner Kallweit -Date: Fri, 18 Apr 2025 11:23:45 +0200 -Subject: [PATCH] r8169: merge chip versions 70 and 71 (RTL8126A) - -Handling of both chip versions is the same, only difference is -the firmware. So we can merge handling of both chip versions. - -Signed-off-by: Heiner Kallweit -Reviewed-by: Simon Horman -Link: https://patch.msgid.link/97d7ae79-d021-4b6b-b424-89e5e305b029@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/realtek/r8169.h | 1 - - drivers/net/ethernet/realtek/r8169_main.c | 15 ++++----------- - drivers/net/ethernet/realtek/r8169_phy_config.c | 1 - - 3 files changed, 4 insertions(+), 13 deletions(-) - ---- a/drivers/net/ethernet/realtek/r8169.h -+++ b/drivers/net/ethernet/realtek/r8169.h -@@ -72,7 +72,6 @@ enum mac_version { - RTL_GIGA_MAC_VER_65, - RTL_GIGA_MAC_VER_66, - RTL_GIGA_MAC_VER_70, -- RTL_GIGA_MAC_VER_71, - RTL_GIGA_MAC_NONE, - RTL_GIGA_MAC_VER_LAST = RTL_GIGA_MAC_NONE - 1 - }; ---- a/drivers/net/ethernet/realtek/r8169_main.c -+++ b/drivers/net/ethernet/realtek/r8169_main.c -@@ -99,7 +99,7 @@ static const struct rtl_chip_info { - const char *fw_name; - } rtl_chip_infos[] = { - /* 8126A family. */ -- { 0x7cf, 0x64a, RTL_GIGA_MAC_VER_71, "RTL8126A", FIRMWARE_8126A_3 }, -+ { 0x7cf, 0x64a, RTL_GIGA_MAC_VER_70, "RTL8126A", FIRMWARE_8126A_3 }, - { 0x7cf, 0x649, RTL_GIGA_MAC_VER_70, "RTL8126A", FIRMWARE_8126A_2 }, - - /* 8125BP family. */ -@@ -2936,7 +2936,6 @@ static void rtl_hw_aspm_clkreq_enable(st - rtl_mod_config5(tp, 0, ASPM_en); - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_70: -- case RTL_GIGA_MAC_VER_71: - val8 = RTL_R8(tp, INT_CFG0_8125) | INT_CFG0_CLKREQEN; - RTL_W8(tp, INT_CFG0_8125, val8); - break; -@@ -2968,7 +2967,6 @@ static void rtl_hw_aspm_clkreq_enable(st - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_70: -- case RTL_GIGA_MAC_VER_71: - val8 = RTL_R8(tp, INT_CFG0_8125) & ~INT_CFG0_CLKREQEN; - RTL_W8(tp, INT_CFG0_8125, val8); - break; -@@ -3688,12 +3686,10 @@ static void rtl_hw_start_8125_common(str - /* disable new tx descriptor format */ - r8168_mac_ocp_modify(tp, 0xeb58, 0x0001, 0x0000); - -- if (tp->mac_version == RTL_GIGA_MAC_VER_70 || -- tp->mac_version == RTL_GIGA_MAC_VER_71) -+ if (tp->mac_version == RTL_GIGA_MAC_VER_70) - RTL_W8(tp, 0xD8, RTL_R8(tp, 0xD8) & ~0x02); - -- if (tp->mac_version == RTL_GIGA_MAC_VER_70 || -- tp->mac_version == RTL_GIGA_MAC_VER_71) -+ if (tp->mac_version == RTL_GIGA_MAC_VER_70) - r8168_mac_ocp_modify(tp, 0xe614, 0x0700, 0x0400); - else if (tp->mac_version == RTL_GIGA_MAC_VER_63) - r8168_mac_ocp_modify(tp, 0xe614, 0x0700, 0x0200); -@@ -3711,8 +3707,7 @@ static void rtl_hw_start_8125_common(str - r8168_mac_ocp_modify(tp, 0xe056, 0x00f0, 0x0000); - r8168_mac_ocp_modify(tp, 0xe040, 0x1000, 0x0000); - r8168_mac_ocp_modify(tp, 0xea1c, 0x0003, 0x0001); -- if (tp->mac_version == RTL_GIGA_MAC_VER_70 || -- tp->mac_version == RTL_GIGA_MAC_VER_71) -+ if (tp->mac_version == RTL_GIGA_MAC_VER_70) - r8168_mac_ocp_modify(tp, 0xea1c, 0x0300, 0x0000); - else - r8168_mac_ocp_modify(tp, 0xea1c, 0x0004, 0x0000); -@@ -3835,7 +3830,6 @@ static void rtl_hw_config(struct rtl8169 - [RTL_GIGA_MAC_VER_65] = rtl_hw_start_8125d, - [RTL_GIGA_MAC_VER_66] = rtl_hw_start_8125d, - [RTL_GIGA_MAC_VER_70] = rtl_hw_start_8126a, -- [RTL_GIGA_MAC_VER_71] = rtl_hw_start_8126a, - }; - - if (hw_configs[tp->mac_version]) -@@ -3859,7 +3853,6 @@ static void rtl_hw_start_8125(struct rtl - break; - case RTL_GIGA_MAC_VER_63: - case RTL_GIGA_MAC_VER_70: -- case RTL_GIGA_MAC_VER_71: - for (i = 0xa00; i < 0xa80; i += 4) - RTL_W32(tp, i, 0); - RTL_W16(tp, INT_CFG1_8125, 0x0000); ---- a/drivers/net/ethernet/realtek/r8169_phy_config.c -+++ b/drivers/net/ethernet/realtek/r8169_phy_config.c -@@ -1183,7 +1183,6 @@ void r8169_hw_phy_config(struct rtl8169_ - [RTL_GIGA_MAC_VER_65] = rtl8125d_hw_phy_config, - [RTL_GIGA_MAC_VER_66] = rtl8125bp_hw_phy_config, - [RTL_GIGA_MAC_VER_70] = rtl8126a_hw_phy_config, -- [RTL_GIGA_MAC_VER_71] = rtl8126a_hw_phy_config, - }; - - if (phy_configs[ver]) diff --git a/target/linux/generic/backport-6.18/780-40-v6.16-r8169-merge-chip-versions-64-and-65-RTL8125D.patch b/target/linux/generic/backport-6.18/780-40-v6.16-r8169-merge-chip-versions-64-and-65-RTL8125D.patch deleted file mode 100644 index 5110c2776e..0000000000 --- a/target/linux/generic/backport-6.18/780-40-v6.16-r8169-merge-chip-versions-64-and-65-RTL8125D.patch +++ /dev/null @@ -1,65 +0,0 @@ -From f372ef6ed5a6b0401c884561d4bba1843e54d46a Mon Sep 17 00:00:00 2001 -From: Heiner Kallweit -Date: Fri, 18 Apr 2025 11:24:30 +0200 -Subject: [PATCH] r8169: merge chip versions 64 and 65 (RTL8125D) - -Handling of both chip versions is the same, only difference is -the firmware. So we can merge handling of both chip versions. - -Signed-off-by: Heiner Kallweit -Reviewed-by: Simon Horman -Link: https://patch.msgid.link/0baad123-c679-4154-923f-fdc12783e900@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/realtek/r8169.h | 1 - - drivers/net/ethernet/realtek/r8169_main.c | 4 +--- - drivers/net/ethernet/realtek/r8169_phy_config.c | 1 - - 3 files changed, 1 insertion(+), 5 deletions(-) - ---- a/drivers/net/ethernet/realtek/r8169.h -+++ b/drivers/net/ethernet/realtek/r8169.h -@@ -69,7 +69,6 @@ enum mac_version { - RTL_GIGA_MAC_VER_61, - RTL_GIGA_MAC_VER_63, - RTL_GIGA_MAC_VER_64, -- RTL_GIGA_MAC_VER_65, - RTL_GIGA_MAC_VER_66, - RTL_GIGA_MAC_VER_70, - RTL_GIGA_MAC_NONE, ---- a/drivers/net/ethernet/realtek/r8169_main.c -+++ b/drivers/net/ethernet/realtek/r8169_main.c -@@ -106,7 +106,7 @@ static const struct rtl_chip_info { - { 0x7cf, 0x681, RTL_GIGA_MAC_VER_66, "RTL8125BP", FIRMWARE_8125BP_2 }, - - /* 8125D family. */ -- { 0x7cf, 0x689, RTL_GIGA_MAC_VER_65, "RTL8125D", FIRMWARE_8125D_2 }, -+ { 0x7cf, 0x689, RTL_GIGA_MAC_VER_64, "RTL8125D", FIRMWARE_8125D_2 }, - { 0x7cf, 0x688, RTL_GIGA_MAC_VER_64, "RTL8125D", FIRMWARE_8125D_1 }, - - /* 8125B family. */ -@@ -3827,7 +3827,6 @@ static void rtl_hw_config(struct rtl8169 - [RTL_GIGA_MAC_VER_61] = rtl_hw_start_8125a_2, - [RTL_GIGA_MAC_VER_63] = rtl_hw_start_8125b, - [RTL_GIGA_MAC_VER_64] = rtl_hw_start_8125d, -- [RTL_GIGA_MAC_VER_65] = rtl_hw_start_8125d, - [RTL_GIGA_MAC_VER_66] = rtl_hw_start_8125d, - [RTL_GIGA_MAC_VER_70] = rtl_hw_start_8126a, - }; -@@ -3846,7 +3845,6 @@ static void rtl_hw_start_8125(struct rtl - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_61: - case RTL_GIGA_MAC_VER_64: -- case RTL_GIGA_MAC_VER_65: - case RTL_GIGA_MAC_VER_66: - for (i = 0xa00; i < 0xb00; i += 4) - RTL_W32(tp, i, 0); ---- a/drivers/net/ethernet/realtek/r8169_phy_config.c -+++ b/drivers/net/ethernet/realtek/r8169_phy_config.c -@@ -1180,7 +1180,6 @@ void r8169_hw_phy_config(struct rtl8169_ - [RTL_GIGA_MAC_VER_61] = rtl8125a_2_hw_phy_config, - [RTL_GIGA_MAC_VER_63] = rtl8125b_hw_phy_config, - [RTL_GIGA_MAC_VER_64] = rtl8125d_hw_phy_config, -- [RTL_GIGA_MAC_VER_65] = rtl8125d_hw_phy_config, - [RTL_GIGA_MAC_VER_66] = rtl8125bp_hw_phy_config, - [RTL_GIGA_MAC_VER_70] = rtl8126a_hw_phy_config, - }; diff --git a/target/linux/generic/backport-6.18/780-41-v6.16-r8169-merge-chip-versions-52-and-53-RTL8117.patch b/target/linux/generic/backport-6.18/780-41-v6.16-r8169-merge-chip-versions-52-and-53-RTL8117.patch deleted file mode 100644 index b28c28f4e2..0000000000 --- a/target/linux/generic/backport-6.18/780-41-v6.16-r8169-merge-chip-versions-52-and-53-RTL8117.patch +++ /dev/null @@ -1,113 +0,0 @@ -From 4f51e7d370a04122fa78470b031d6487c52298b1 Mon Sep 17 00:00:00 2001 -From: Heiner Kallweit -Date: Fri, 18 Apr 2025 11:25:17 +0200 -Subject: [PATCH] r8169: merge chip versions 52 and 53 (RTL8117) - -Handling of both chip versions is the same, only difference is -the firmware. So we can merge handling of both chip versions. - -Signed-off-by: Heiner Kallweit -Reviewed-by: Simon Horman -Link: https://patch.msgid.link/ae866b71-c904-434e-befb-848c831e33ff@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/realtek/r8169.h | 1 - - drivers/net/ethernet/realtek/r8169_main.c | 17 +++++++---------- - drivers/net/ethernet/realtek/r8169_phy_config.c | 1 - - 3 files changed, 7 insertions(+), 12 deletions(-) - ---- a/drivers/net/ethernet/realtek/r8169.h -+++ b/drivers/net/ethernet/realtek/r8169.h -@@ -64,7 +64,6 @@ enum mac_version { - /* support for RTL_GIGA_MAC_VER_50 has been removed */ - RTL_GIGA_MAC_VER_51, - RTL_GIGA_MAC_VER_52, -- RTL_GIGA_MAC_VER_53, - /* support for RTL_GIGA_MAC_VER_60 has been removed */ - RTL_GIGA_MAC_VER_61, - RTL_GIGA_MAC_VER_63, ---- a/drivers/net/ethernet/realtek/r8169_main.c -+++ b/drivers/net/ethernet/realtek/r8169_main.c -@@ -116,7 +116,7 @@ static const struct rtl_chip_info { - { 0x7cf, 0x609, RTL_GIGA_MAC_VER_61, "RTL8125A", FIRMWARE_8125A_3 }, - - /* RTL8117 */ -- { 0x7cf, 0x54b, RTL_GIGA_MAC_VER_53, "RTL8168fp/RTL8117" }, -+ { 0x7cf, 0x54b, RTL_GIGA_MAC_VER_52, "RTL8168fp/RTL8117" }, - { 0x7cf, 0x54a, RTL_GIGA_MAC_VER_52, "RTL8168fp/RTL8117", - FIRMWARE_8168FP_3 }, - -@@ -830,7 +830,7 @@ static bool rtl_is_8168evl_up(struct rtl - { - return tp->mac_version >= RTL_GIGA_MAC_VER_34 && - tp->mac_version != RTL_GIGA_MAC_VER_39 && -- tp->mac_version <= RTL_GIGA_MAC_VER_53; -+ tp->mac_version <= RTL_GIGA_MAC_VER_52; - } - - static bool rtl_supports_eee(struct rtl8169_private *tp) -@@ -998,9 +998,7 @@ void r8169_get_led_name(struct rtl8169_p - static void r8168fp_adjust_ocp_cmd(struct rtl8169_private *tp, u32 *cmd, int type) - { - /* based on RTL8168FP_OOBMAC_BASE in vendor driver */ -- if (type == ERIAR_OOB && -- (tp->mac_version == RTL_GIGA_MAC_VER_52 || -- tp->mac_version == RTL_GIGA_MAC_VER_53)) -+ if (type == ERIAR_OOB && tp->mac_version == RTL_GIGA_MAC_VER_52) - *cmd |= 0xf70 << 18; - } - -@@ -1500,7 +1498,7 @@ static enum rtl_dash_type rtl_get_dash_t - case RTL_GIGA_MAC_VER_28: - case RTL_GIGA_MAC_VER_31: - return RTL_DASH_DP; -- case RTL_GIGA_MAC_VER_51 ... RTL_GIGA_MAC_VER_53: -+ case RTL_GIGA_MAC_VER_51 ... RTL_GIGA_MAC_VER_52: - return RTL_DASH_EP; - case RTL_GIGA_MAC_VER_66: - return RTL_DASH_25_BP; -@@ -2485,7 +2483,7 @@ static void rtl_init_rxcfg(struct rtl816 - case RTL_GIGA_MAC_VER_38: - RTL_W32(tp, RxConfig, RX128_INT_EN | RX_MULTI_EN | RX_DMA_BURST); - break; -- case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_53: -+ case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_52: - RTL_W32(tp, RxConfig, RX128_INT_EN | RX_MULTI_EN | RX_DMA_BURST | RX_EARLY_OFF); - break; - case RTL_GIGA_MAC_VER_61: -@@ -2616,7 +2614,7 @@ DECLARE_RTL_COND(rtl_rxtx_empty_cond_2) - static void rtl_wait_txrx_fifo_empty(struct rtl8169_private *tp) - { - switch (tp->mac_version) { -- case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_53: -+ case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_52: - rtl_loop_wait_high(tp, &rtl_txcfg_empty_cond, 100, 42); - rtl_loop_wait_high(tp, &rtl_rxtx_empty_cond, 100, 42); - break; -@@ -3823,7 +3821,6 @@ static void rtl_hw_config(struct rtl8169 - [RTL_GIGA_MAC_VER_48] = rtl_hw_start_8168h_1, - [RTL_GIGA_MAC_VER_51] = rtl_hw_start_8168ep_3, - [RTL_GIGA_MAC_VER_52] = rtl_hw_start_8117, -- [RTL_GIGA_MAC_VER_53] = rtl_hw_start_8117, - [RTL_GIGA_MAC_VER_61] = rtl_hw_start_8125a_2, - [RTL_GIGA_MAC_VER_63] = rtl_hw_start_8125b, - [RTL_GIGA_MAC_VER_64] = rtl_hw_start_8125d, -@@ -5282,7 +5279,7 @@ static void rtl_hw_init_8125(struct rtl8 - static void rtl_hw_initialize(struct rtl8169_private *tp) - { - switch (tp->mac_version) { -- case RTL_GIGA_MAC_VER_51 ... RTL_GIGA_MAC_VER_53: -+ case RTL_GIGA_MAC_VER_51 ... RTL_GIGA_MAC_VER_52: - rtl8168ep_stop_cmac(tp); - fallthrough; - case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_48: ---- a/drivers/net/ethernet/realtek/r8169_phy_config.c -+++ b/drivers/net/ethernet/realtek/r8169_phy_config.c -@@ -1176,7 +1176,6 @@ void r8169_hw_phy_config(struct rtl8169_ - [RTL_GIGA_MAC_VER_48] = rtl8168h_2_hw_phy_config, - [RTL_GIGA_MAC_VER_51] = rtl8168ep_2_hw_phy_config, - [RTL_GIGA_MAC_VER_52] = rtl8117_hw_phy_config, -- [RTL_GIGA_MAC_VER_53] = rtl8117_hw_phy_config, - [RTL_GIGA_MAC_VER_61] = rtl8125a_2_hw_phy_config, - [RTL_GIGA_MAC_VER_63] = rtl8125b_hw_phy_config, - [RTL_GIGA_MAC_VER_64] = rtl8125d_hw_phy_config, diff --git a/target/linux/generic/backport-6.18/780-42-v6.16-r8169-add-support-for-RTL8127A.patch b/target/linux/generic/backport-6.18/780-42-v6.16-r8169-add-support-for-RTL8127A.patch deleted file mode 100644 index 45587a39b7..0000000000 --- a/target/linux/generic/backport-6.18/780-42-v6.16-r8169-add-support-for-RTL8127A.patch +++ /dev/null @@ -1,323 +0,0 @@ -From f24f7b2f3af9e008ded20f804d7829ee2efd43f2 Mon Sep 17 00:00:00 2001 -From: ChunHao Lin -Date: Thu, 15 May 2025 17:53:03 +0800 -Subject: [PATCH] r8169: add support for RTL8127A - -This adds support for 10Gbs chip RTL8127A. - -Signed-off-by: ChunHao Lin -Reviewed-by: Heiner Kallweit -Link: https://patch.msgid.link/20250515095303.3138-1-hau@realtek.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/realtek/r8169.h | 1 + - drivers/net/ethernet/realtek/r8169_main.c | 29 ++- - .../net/ethernet/realtek/r8169_phy_config.c | 166 ++++++++++++++++++ - 3 files changed, 193 insertions(+), 3 deletions(-) - ---- a/drivers/net/ethernet/realtek/r8169.h -+++ b/drivers/net/ethernet/realtek/r8169.h -@@ -70,6 +70,7 @@ enum mac_version { - RTL_GIGA_MAC_VER_64, - RTL_GIGA_MAC_VER_66, - RTL_GIGA_MAC_VER_70, -+ RTL_GIGA_MAC_VER_80, - RTL_GIGA_MAC_NONE, - RTL_GIGA_MAC_VER_LAST = RTL_GIGA_MAC_NONE - 1 - }; ---- a/drivers/net/ethernet/realtek/r8169_main.c -+++ b/drivers/net/ethernet/realtek/r8169_main.c -@@ -60,6 +60,7 @@ - #define FIRMWARE_8125BP_2 "rtl_nic/rtl8125bp-2.fw" - #define FIRMWARE_8126A_2 "rtl_nic/rtl8126a-2.fw" - #define FIRMWARE_8126A_3 "rtl_nic/rtl8126a-3.fw" -+#define FIRMWARE_8127A_1 "rtl_nic/rtl8127a-1.fw" - - #define TX_DMA_BURST 7 /* Maximum PCI burst, '7' is unlimited */ - #define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */ -@@ -98,6 +99,9 @@ static const struct rtl_chip_info { - const char *name; - const char *fw_name; - } rtl_chip_infos[] = { -+ /* 8127A family. */ -+ { 0x7cf, 0x6c9, RTL_GIGA_MAC_VER_80, "RTL8127A", FIRMWARE_8127A_1 }, -+ - /* 8126A family. */ - { 0x7cf, 0x64a, RTL_GIGA_MAC_VER_70, "RTL8126A", FIRMWARE_8126A_3 }, - { 0x7cf, 0x649, RTL_GIGA_MAC_VER_70, "RTL8126A", FIRMWARE_8126A_2 }, -@@ -222,8 +226,10 @@ static const struct pci_device_id rtl816 - { 0x0001, 0x8168, PCI_ANY_ID, 0x2410 }, - { PCI_VDEVICE(REALTEK, 0x8125) }, - { PCI_VDEVICE(REALTEK, 0x8126) }, -+ { PCI_VDEVICE(REALTEK, 0x8127) }, - { PCI_VDEVICE(REALTEK, 0x3000) }, - { PCI_VDEVICE(REALTEK, 0x5000) }, -+ { PCI_VDEVICE(REALTEK, 0x0e10) }, - {} - }; - -@@ -769,6 +775,7 @@ MODULE_FIRMWARE(FIRMWARE_8125D_2); - MODULE_FIRMWARE(FIRMWARE_8125BP_2); - MODULE_FIRMWARE(FIRMWARE_8126A_2); - MODULE_FIRMWARE(FIRMWARE_8126A_3); -+MODULE_FIRMWARE(FIRMWARE_8127A_1); - - static inline struct device *tp_to_dev(struct rtl8169_private *tp) - { -@@ -2934,6 +2941,7 @@ static void rtl_hw_aspm_clkreq_enable(st - rtl_mod_config5(tp, 0, ASPM_en); - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_70: -+ case RTL_GIGA_MAC_VER_80: - val8 = RTL_R8(tp, INT_CFG0_8125) | INT_CFG0_CLKREQEN; - RTL_W8(tp, INT_CFG0_8125, val8); - break; -@@ -2965,6 +2973,7 @@ static void rtl_hw_aspm_clkreq_enable(st - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_70: -+ case RTL_GIGA_MAC_VER_80: - val8 = RTL_R8(tp, INT_CFG0_8125) & ~INT_CFG0_CLKREQEN; - RTL_W8(tp, INT_CFG0_8125, val8); - break; -@@ -3684,10 +3693,13 @@ static void rtl_hw_start_8125_common(str - /* disable new tx descriptor format */ - r8168_mac_ocp_modify(tp, 0xeb58, 0x0001, 0x0000); - -- if (tp->mac_version == RTL_GIGA_MAC_VER_70) -+ if (tp->mac_version == RTL_GIGA_MAC_VER_70 || -+ tp->mac_version == RTL_GIGA_MAC_VER_80) - RTL_W8(tp, 0xD8, RTL_R8(tp, 0xD8) & ~0x02); - -- if (tp->mac_version == RTL_GIGA_MAC_VER_70) -+ if (tp->mac_version == RTL_GIGA_MAC_VER_80) -+ r8168_mac_ocp_modify(tp, 0xe614, 0x0f00, 0x0f00); -+ else if (tp->mac_version == RTL_GIGA_MAC_VER_70) - r8168_mac_ocp_modify(tp, 0xe614, 0x0700, 0x0400); - else if (tp->mac_version == RTL_GIGA_MAC_VER_63) - r8168_mac_ocp_modify(tp, 0xe614, 0x0700, 0x0200); -@@ -3705,7 +3717,8 @@ static void rtl_hw_start_8125_common(str - r8168_mac_ocp_modify(tp, 0xe056, 0x00f0, 0x0000); - r8168_mac_ocp_modify(tp, 0xe040, 0x1000, 0x0000); - r8168_mac_ocp_modify(tp, 0xea1c, 0x0003, 0x0001); -- if (tp->mac_version == RTL_GIGA_MAC_VER_70) -+ if (tp->mac_version == RTL_GIGA_MAC_VER_70 || -+ tp->mac_version == RTL_GIGA_MAC_VER_80) - r8168_mac_ocp_modify(tp, 0xea1c, 0x0300, 0x0000); - else - r8168_mac_ocp_modify(tp, 0xea1c, 0x0004, 0x0000); -@@ -3783,6 +3796,12 @@ static void rtl_hw_start_8126a(struct rt - rtl_hw_start_8125_common(tp); - } - -+static void rtl_hw_start_8127a(struct rtl8169_private *tp) -+{ -+ rtl_set_def_aspm_entry_latency(tp); -+ rtl_hw_start_8125_common(tp); -+} -+ - static void rtl_hw_config(struct rtl8169_private *tp) - { - static const rtl_generic_fct hw_configs[] = { -@@ -3826,6 +3845,7 @@ static void rtl_hw_config(struct rtl8169 - [RTL_GIGA_MAC_VER_64] = rtl_hw_start_8125d, - [RTL_GIGA_MAC_VER_66] = rtl_hw_start_8125d, - [RTL_GIGA_MAC_VER_70] = rtl_hw_start_8126a, -+ [RTL_GIGA_MAC_VER_80] = rtl_hw_start_8127a, - }; - - if (hw_configs[tp->mac_version]) -@@ -3843,8 +3863,11 @@ static void rtl_hw_start_8125(struct rtl - case RTL_GIGA_MAC_VER_61: - case RTL_GIGA_MAC_VER_64: - case RTL_GIGA_MAC_VER_66: -+ case RTL_GIGA_MAC_VER_80: - for (i = 0xa00; i < 0xb00; i += 4) - RTL_W32(tp, i, 0); -+ if (tp->mac_version == RTL_GIGA_MAC_VER_80) -+ RTL_W16(tp, INT_CFG1_8125, 0x0000); - break; - case RTL_GIGA_MAC_VER_63: - case RTL_GIGA_MAC_VER_70: ---- a/drivers/net/ethernet/realtek/r8169_phy_config.c -+++ b/drivers/net/ethernet/realtek/r8169_phy_config.c -@@ -1130,6 +1130,171 @@ static void rtl8126a_hw_phy_config(struc - rtl8125_common_config_eee_phy(phydev); - } - -+static void rtl8127a_1_hw_phy_config(struct rtl8169_private *tp, -+ struct phy_device *phydev) -+{ -+ r8169_apply_firmware(tp); -+ rtl8168g_enable_gphy_10m(phydev); -+ -+ r8168g_phy_param(phydev, 0x8415, 0xff00, 0x9300); -+ r8168g_phy_param(phydev, 0x81a3, 0xff00, 0x0f00); -+ r8168g_phy_param(phydev, 0x81ae, 0xff00, 0x0f00); -+ r8168g_phy_param(phydev, 0x81b9, 0xff00, 0xb900); -+ rtl8125_phy_param(phydev, 0x83b0, 0x0e00, 0x0000); -+ rtl8125_phy_param(phydev, 0x83C5, 0x0e00, 0x0000); -+ rtl8125_phy_param(phydev, 0x83da, 0x0e00, 0x0000); -+ rtl8125_phy_param(phydev, 0x83ef, 0x0e00, 0x0000); -+ phy_modify_paged(phydev, 0x0bf3, 0x14, 0x01f0, 0x0160); -+ phy_modify_paged(phydev, 0x0bf3, 0x15, 0x001f, 0x0014); -+ phy_modify_paged(phydev, 0x0bf2, 0x14, 0x6000, 0x0000); -+ phy_modify_paged(phydev, 0x0bf2, 0x16, 0xc000, 0x0000); -+ phy_modify_paged(phydev, 0x0bf2, 0x14, 0x1fff, 0x0187); -+ phy_modify_paged(phydev, 0x0bf2, 0x15, 0x003f, 0x0003); -+ -+ r8168g_phy_param(phydev, 0x8173, 0xffff, 0x8620); -+ r8168g_phy_param(phydev, 0x8175, 0xffff, 0x8671); -+ r8168g_phy_param(phydev, 0x817c, 0x0000, 0x2000); -+ r8168g_phy_param(phydev, 0x8187, 0x0000, 0x2000); -+ r8168g_phy_param(phydev, 0x8192, 0x0000, 0x2000); -+ r8168g_phy_param(phydev, 0x819d, 0x0000, 0x2000); -+ r8168g_phy_param(phydev, 0x81a8, 0x2000, 0x0000); -+ r8168g_phy_param(phydev, 0x81b3, 0x2000, 0x0000); -+ r8168g_phy_param(phydev, 0x81be, 0x0000, 0x2000); -+ r8168g_phy_param(phydev, 0x817d, 0xff00, 0xa600); -+ r8168g_phy_param(phydev, 0x8188, 0xff00, 0xa600); -+ r8168g_phy_param(phydev, 0x8193, 0xff00, 0xa600); -+ r8168g_phy_param(phydev, 0x819e, 0xff00, 0xa600); -+ r8168g_phy_param(phydev, 0x81a9, 0xff00, 0x1400); -+ r8168g_phy_param(phydev, 0x81b4, 0xff00, 0x1400); -+ r8168g_phy_param(phydev, 0x81bf, 0xff00, 0xa600); -+ -+ phy_modify_paged(phydev, 0x0aea, 0x15, 0x0028, 0x0000); -+ -+ rtl8125_phy_param(phydev, 0x84f0, 0xffff, 0x201c); -+ rtl8125_phy_param(phydev, 0x84f2, 0xffff, 0x3117); -+ -+ phy_write_paged(phydev, 0x0aec, 0x13, 0x0000); -+ phy_write_paged(phydev, 0x0ae2, 0x10, 0xffff); -+ phy_write_paged(phydev, 0x0aec, 0x17, 0xffff); -+ phy_write_paged(phydev, 0x0aed, 0x11, 0xffff); -+ phy_write_paged(phydev, 0x0aec, 0x14, 0x0000); -+ phy_modify_paged(phydev, 0x0aed, 0x10, 0x0001, 0x0000); -+ phy_write_paged(phydev, 0x0adb, 0x14, 0x0150); -+ rtl8125_phy_param(phydev, 0x8197, 0xff00, 0x5000); -+ rtl8125_phy_param(phydev, 0x8231, 0xff00, 0x5000); -+ rtl8125_phy_param(phydev, 0x82cb, 0xff00, 0x5000); -+ rtl8125_phy_param(phydev, 0x82cd, 0xff00, 0x5700); -+ rtl8125_phy_param(phydev, 0x8233, 0xff00, 0x5700); -+ rtl8125_phy_param(phydev, 0x8199, 0xff00, 0x5700); -+ -+ rtl8125_phy_param(phydev, 0x815a, 0xffff, 0x0150); -+ rtl8125_phy_param(phydev, 0x81f4, 0xffff, 0x0150); -+ rtl8125_phy_param(phydev, 0x828e, 0xffff, 0x0150); -+ rtl8125_phy_param(phydev, 0x81b1, 0xffff, 0x0000); -+ rtl8125_phy_param(phydev, 0x824b, 0xffff, 0x0000); -+ rtl8125_phy_param(phydev, 0x82e5, 0xffff, 0x0000); -+ -+ rtl8125_phy_param(phydev, 0x84f7, 0xff00, 0x2800); -+ phy_modify_paged(phydev, 0x0aec, 0x11, 0x0000, 0x1000); -+ rtl8125_phy_param(phydev, 0x81b3, 0xff00, 0xad00); -+ rtl8125_phy_param(phydev, 0x824d, 0xff00, 0xad00); -+ rtl8125_phy_param(phydev, 0x82e7, 0xff00, 0xad00); -+ phy_modify_paged(phydev, 0x0ae4, 0x17, 0x000f, 0x0001); -+ rtl8125_phy_param(phydev, 0x82ce, 0xf000, 0x4000); -+ -+ rtl8125_phy_param(phydev, 0x84ac, 0xffff, 0x0000); -+ rtl8125_phy_param(phydev, 0x84ae, 0xffff, 0x0000); -+ rtl8125_phy_param(phydev, 0x84b0, 0xffff, 0xf818); -+ rtl8125_phy_param(phydev, 0x84b2, 0xff00, 0x6000); -+ -+ rtl8125_phy_param(phydev, 0x8ffc, 0xffff, 0x6008); -+ rtl8125_phy_param(phydev, 0x8ffe, 0xffff, 0xf450); -+ -+ rtl8125_phy_param(phydev, 0x8015, 0x0000, 0x0200); -+ rtl8125_phy_param(phydev, 0x8016, 0x0800, 0x0000); -+ rtl8125_phy_param(phydev, 0x8fe6, 0xff00, 0x0800); -+ rtl8125_phy_param(phydev, 0x8fe4, 0xffff, 0x2114); -+ -+ rtl8125_phy_param(phydev, 0x8647, 0xffff, 0xa7b1); -+ rtl8125_phy_param(phydev, 0x8649, 0xffff, 0xbbca); -+ rtl8125_phy_param(phydev, 0x864b, 0xff00, 0xdc00); -+ -+ rtl8125_phy_param(phydev, 0x8154, 0xc000, 0x4000); -+ rtl8125_phy_param(phydev, 0x8158, 0xc000, 0x0000); -+ -+ rtl8125_phy_param(phydev, 0x826c, 0xffff, 0xffff); -+ rtl8125_phy_param(phydev, 0x826e, 0xffff, 0xffff); -+ -+ rtl8125_phy_param(phydev, 0x8872, 0xff00, 0x0e00); -+ r8168g_phy_param(phydev, 0x8012, 0x0000, 0x0800); -+ r8168g_phy_param(phydev, 0x8012, 0x0000, 0x4000); -+ phy_modify_paged(phydev, 0x0b57, 0x13, 0x0000, 0x0001); -+ r8168g_phy_param(phydev, 0x834a, 0xff00, 0x0700); -+ rtl8125_phy_param(phydev, 0x8217, 0x3f00, 0x2a00); -+ r8168g_phy_param(phydev, 0x81b1, 0xff00, 0x0b00); -+ rtl8125_phy_param(phydev, 0x8fed, 0xff00, 0x4e00); -+ -+ rtl8125_phy_param(phydev, 0x88ac, 0xff00, 0x2300); -+ phy_modify_paged(phydev, 0x0bf0, 0x16, 0x0000, 0x3800); -+ rtl8125_phy_param(phydev, 0x88de, 0xff00, 0x0000); -+ rtl8125_phy_param(phydev, 0x80b4, 0xffff, 0x5195); -+ -+ r8168g_phy_param(phydev, 0x8370, 0xffff, 0x8671); -+ r8168g_phy_param(phydev, 0x8372, 0xffff, 0x86c8); -+ -+ r8168g_phy_param(phydev, 0x8401, 0xffff, 0x86c8); -+ r8168g_phy_param(phydev, 0x8403, 0xffff, 0x86da); -+ r8168g_phy_param(phydev, 0x8406, 0x1800, 0x1000); -+ r8168g_phy_param(phydev, 0x8408, 0x1800, 0x1000); -+ r8168g_phy_param(phydev, 0x840a, 0x1800, 0x1000); -+ r8168g_phy_param(phydev, 0x840c, 0x1800, 0x1000); -+ r8168g_phy_param(phydev, 0x840e, 0x1800, 0x1000); -+ r8168g_phy_param(phydev, 0x8410, 0x1800, 0x1000); -+ r8168g_phy_param(phydev, 0x8412, 0x1800, 0x1000); -+ r8168g_phy_param(phydev, 0x8414, 0x1800, 0x1000); -+ r8168g_phy_param(phydev, 0x8416, 0x1800, 0x1000); -+ -+ r8168g_phy_param(phydev, 0x82bd, 0xffff, 0x1f40); -+ -+ phy_modify_paged(phydev, 0x0bfb, 0x12, 0x07ff, 0x0328); -+ phy_write_paged(phydev, 0x0bfb, 0x13, 0x3e14); -+ -+ r8168g_phy_param(phydev, 0x81c4, 0xffff, 0x003b); -+ r8168g_phy_param(phydev, 0x81c6, 0xffff, 0x0086); -+ r8168g_phy_param(phydev, 0x81c8, 0xffff, 0x00b7); -+ r8168g_phy_param(phydev, 0x81ca, 0xffff, 0x00db); -+ r8168g_phy_param(phydev, 0x81cc, 0xffff, 0x00fe); -+ r8168g_phy_param(phydev, 0x81ce, 0xffff, 0x00fe); -+ r8168g_phy_param(phydev, 0x81d0, 0xffff, 0x00fe); -+ r8168g_phy_param(phydev, 0x81d2, 0xffff, 0x00fe); -+ r8168g_phy_param(phydev, 0x81d4, 0xffff, 0x00c3); -+ r8168g_phy_param(phydev, 0x81d6, 0xffff, 0x0078); -+ r8168g_phy_param(phydev, 0x81d8, 0xffff, 0x0047); -+ r8168g_phy_param(phydev, 0x81da, 0xffff, 0x0023); -+ -+ rtl8125_phy_param(phydev, 0x88d7, 0xffff, 0x01a0); -+ rtl8125_phy_param(phydev, 0x88d9, 0xffff, 0x01a0); -+ rtl8125_phy_param(phydev, 0x8ffa, 0xffff, 0x002a); -+ -+ rtl8125_phy_param(phydev, 0x8fee, 0xffff, 0xffdf); -+ rtl8125_phy_param(phydev, 0x8ff0, 0xffff, 0xffff); -+ rtl8125_phy_param(phydev, 0x8ff2, 0xffff, 0x0a4a); -+ rtl8125_phy_param(phydev, 0x8ff4, 0xffff, 0xaa5a); -+ rtl8125_phy_param(phydev, 0x8ff6, 0xffff, 0x0a4a); -+ -+ rtl8125_phy_param(phydev, 0x8ff8, 0xffff, 0xaa5a); -+ rtl8125_phy_param(phydev, 0x88d5, 0xff00, 0x0200); -+ -+ r8168g_phy_param(phydev, 0x84bb, 0xff00, 0x0a00); -+ r8168g_phy_param(phydev, 0x84c0, 0xff00, 0x1600); -+ -+ phy_modify_paged(phydev, 0x0a43, 0x10, 0x0000, 0x0003); -+ -+ rtl8125_legacy_force_mode(phydev); -+ rtl8168g_disable_aldps(phydev); -+ rtl8125_common_config_eee_phy(phydev); -+} -+ - void r8169_hw_phy_config(struct rtl8169_private *tp, struct phy_device *phydev, - enum mac_version ver) - { -@@ -1181,6 +1346,7 @@ void r8169_hw_phy_config(struct rtl8169_ - [RTL_GIGA_MAC_VER_64] = rtl8125d_hw_phy_config, - [RTL_GIGA_MAC_VER_66] = rtl8125bp_hw_phy_config, - [RTL_GIGA_MAC_VER_70] = rtl8126a_hw_phy_config, -+ [RTL_GIGA_MAC_VER_80] = rtl8127a_1_hw_phy_config, - }; - - if (phy_configs[ver]) diff --git a/target/linux/generic/backport-6.18/781-01-v6.13-net-phy-realtek-read-duplex-and-gbit-master-from-PHY.patch b/target/linux/generic/backport-6.18/781-01-v6.13-net-phy-realtek-read-duplex-and-gbit-master-from-PHY.patch deleted file mode 100644 index 31b8aabf7a..0000000000 --- a/target/linux/generic/backport-6.18/781-01-v6.13-net-phy-realtek-read-duplex-and-gbit-master-from-PHY.patch +++ /dev/null @@ -1,106 +0,0 @@ -From 081c9c0265c91b8333165aa6230c20bcbc6f7cbf Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Thu, 10 Oct 2024 14:07:16 +0100 -Subject: [PATCH] net: phy: realtek: read duplex and gbit master from PHYSR - register - -The PHYSR MMD register is present and defined equally for all RTL82xx -Ethernet PHYs. -Read duplex and Gbit master bits from rtlgen_decode_speed() and rename -it to rtlgen_decode_physr(). - -Signed-off-by: Daniel Golle -Link: https://patch.msgid.link/b9a76341da851a18c985bc4774fa295babec79bb.1728565530.git.daniel@makrotopia.org -Signed-off-by: Paolo Abeni ---- - drivers/net/phy/realtek.c | 41 +++++++++++++++++++++++++++++++-------- - 1 file changed, 33 insertions(+), 8 deletions(-) - ---- a/drivers/net/phy/realtek.c -+++ b/drivers/net/phy/realtek.c -@@ -80,15 +80,18 @@ - - #define RTL822X_VND2_GANLPAR 0xa414 - --#define RTL822X_VND2_PHYSR 0xa434 -- - #define RTL8366RB_POWER_SAVE 0x15 - #define RTL8366RB_POWER_SAVE_ON BIT(12) - - #define RTL9000A_GINMR 0x14 - #define RTL9000A_GINMR_LINK_STATUS BIT(4) - --#define RTLGEN_SPEED_MASK 0x0630 -+#define RTL_VND2_PHYSR 0xa434 -+#define RTL_VND2_PHYSR_DUPLEX BIT(3) -+#define RTL_VND2_PHYSR_SPEEDL GENMASK(5, 4) -+#define RTL_VND2_PHYSR_SPEEDH GENMASK(10, 9) -+#define RTL_VND2_PHYSR_MASTER BIT(11) -+#define RTL_VND2_PHYSR_SPEED_MASK (RTL_VND2_PHYSR_SPEEDL | RTL_VND2_PHYSR_SPEEDH) - - #define RTL_GENERIC_PHYID 0x001cc800 - #define RTL_8211FVD_PHYID 0x001cc878 -@@ -661,9 +664,18 @@ static int rtl8366rb_config_init(struct - } - - /* get actual speed to cover the downshift case */ --static void rtlgen_decode_speed(struct phy_device *phydev, int val) -+static void rtlgen_decode_physr(struct phy_device *phydev, int val) - { -- switch (val & RTLGEN_SPEED_MASK) { -+ /* bit 3 -+ * 0: Half Duplex -+ * 1: Full Duplex -+ */ -+ if (val & RTL_VND2_PHYSR_DUPLEX) -+ phydev->duplex = DUPLEX_FULL; -+ else -+ phydev->duplex = DUPLEX_HALF; -+ -+ switch (val & RTL_VND2_PHYSR_SPEED_MASK) { - case 0x0000: - phydev->speed = SPEED_10; - break; -@@ -685,6 +697,19 @@ static void rtlgen_decode_speed(struct p - default: - break; - } -+ -+ /* bit 11 -+ * 0: Slave Mode -+ * 1: Master Mode -+ */ -+ if (phydev->speed >= 1000) { -+ if (val & RTL_VND2_PHYSR_MASTER) -+ phydev->master_slave_state = MASTER_SLAVE_STATE_MASTER; -+ else -+ phydev->master_slave_state = MASTER_SLAVE_STATE_SLAVE; -+ } else { -+ phydev->master_slave_state = MASTER_SLAVE_STATE_UNSUPPORTED; -+ } - } - - static int rtlgen_read_status(struct phy_device *phydev) -@@ -702,7 +727,7 @@ static int rtlgen_read_status(struct phy - if (val < 0) - return val; - -- rtlgen_decode_speed(phydev, val); -+ rtlgen_decode_physr(phydev, val); - - return 0; - } -@@ -1008,11 +1033,11 @@ static int rtl822x_c45_read_status(struc - return 0; - - /* Read actual speed from vendor register. */ -- val = phy_read_mmd(phydev, MDIO_MMD_VEND2, RTL822X_VND2_PHYSR); -+ val = phy_read_mmd(phydev, MDIO_MMD_VEND2, RTL_VND2_PHYSR); - if (val < 0) - return val; - -- rtlgen_decode_speed(phydev, val); -+ rtlgen_decode_physr(phydev, val); - - return 0; - } diff --git a/target/linux/generic/backport-6.18/781-02-v6.13-net-phy-realtek-change-order-of-calls-in-C22-read_st.patch b/target/linux/generic/backport-6.18/781-02-v6.13-net-phy-realtek-change-order-of-calls-in-C22-read_st.patch deleted file mode 100644 index 2e5d7bb3b4..0000000000 --- a/target/linux/generic/backport-6.18/781-02-v6.13-net-phy-realtek-change-order-of-calls-in-C22-read_st.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 68d5cd09e8919679ce13b85950debea4b2e98e04 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Thu, 10 Oct 2024 14:07:26 +0100 -Subject: [PATCH] net: phy: realtek: change order of calls in C22 read_status() - -Always call rtlgen_read_status() first, so genphy_read_status() which -is called by it clears bits in case auto-negotiation has not completed. -Also clear 10GBT link-partner advertisement bits in case auto-negotiation -is disabled or has not completed. - -Suggested-by: Russell King (Oracle) -Signed-off-by: Daniel Golle -Link: https://patch.msgid.link/b15929a41621d215c6b2b57393368086589569ec.1728565530.git.daniel@makrotopia.org -Signed-off-by: Paolo Abeni ---- - drivers/net/phy/realtek.c | 22 +++++++++++++++------- - 1 file changed, 15 insertions(+), 7 deletions(-) - ---- a/drivers/net/phy/realtek.c -+++ b/drivers/net/phy/realtek.c -@@ -950,17 +950,25 @@ static void rtl822xb_update_interface(st - - static int rtl822x_read_status(struct phy_device *phydev) - { -- if (phydev->autoneg == AUTONEG_ENABLE) { -- int lpadv = phy_read_paged(phydev, 0xa5d, 0x13); -+ int lpadv, ret; - -- if (lpadv < 0) -- return lpadv; -+ ret = rtlgen_read_status(phydev); -+ if (ret < 0) -+ return ret; - -- mii_10gbt_stat_mod_linkmode_lpa_t(phydev->lp_advertising, -- lpadv); -+ if (phydev->autoneg == AUTONEG_DISABLE || -+ !phydev->autoneg_complete) { -+ mii_10gbt_stat_mod_linkmode_lpa_t(phydev->lp_advertising, 0); -+ return 0; - } - -- return rtlgen_read_status(phydev); -+ lpadv = phy_read_paged(phydev, 0xa5d, 0x13); -+ if (lpadv < 0) -+ return lpadv; -+ -+ mii_10gbt_stat_mod_linkmode_lpa_t(phydev->lp_advertising, lpadv); -+ -+ return 0; - } - - static int rtl822xb_read_status(struct phy_device *phydev) diff --git a/target/linux/generic/backport-6.18/781-03-v6.13-net-phy-realtek-clear-1000Base-T-link-partner-advert.patch b/target/linux/generic/backport-6.18/781-03-v6.13-net-phy-realtek-clear-1000Base-T-link-partner-advert.patch deleted file mode 100644 index f7d8a5aa16..0000000000 --- a/target/linux/generic/backport-6.18/781-03-v6.13-net-phy-realtek-clear-1000Base-T-link-partner-advert.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 5cb409b3960e75467cbb0a8e1e5596b4490570e3 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Thu, 10 Oct 2024 14:07:39 +0100 -Subject: [PATCH] net: phy: realtek: clear 1000Base-T link partner - advertisement - -Clear 1000Base-T link partner advertisement bits in Clause-45 -read_status() function in case auto-negotiation is disabled or has not -been completed. - -Signed-off-by: Daniel Golle -Link: https://patch.msgid.link/9dc9b47b2d675708afef3ad366bfd78eb584d958.1728565530.git.daniel@makrotopia.org -Signed-off-by: Paolo Abeni ---- - drivers/net/phy/realtek.c | 4 ++++ - 1 file changed, 4 insertions(+) - ---- a/drivers/net/phy/realtek.c -+++ b/drivers/net/phy/realtek.c -@@ -1027,6 +1027,10 @@ static int rtl822x_c45_read_status(struc - if (ret < 0) - return ret; - -+ if (phydev->autoneg == AUTONEG_DISABLE || -+ !genphy_c45_aneg_done(phydev)) -+ mii_stat1000_mod_linkmode_lpa_t(phydev->lp_advertising, 0); -+ - /* Vendor register as C45 has no standardized support for 1000BaseT */ - if (phydev->autoneg == AUTONEG_ENABLE) { - val = phy_read_mmd(phydev, MDIO_MMD_VEND2, diff --git a/target/linux/generic/backport-6.18/781-06-v6.14-net-phy-realtek-add-support-for-reading-MDIO_MMD_VEN.patch b/target/linux/generic/backport-6.18/781-06-v6.14-net-phy-realtek-add-support-for-reading-MDIO_MMD_VEN.patch deleted file mode 100644 index 2add672f44..0000000000 --- a/target/linux/generic/backport-6.18/781-06-v6.14-net-phy-realtek-add-support-for-reading-MDIO_MMD_VEN.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 3d483a10327f38595f714f9f9e9dde43a622cb0f Mon Sep 17 00:00:00 2001 -From: Heiner Kallweit -Date: Sat, 11 Jan 2025 21:49:31 +0100 -Subject: [PATCH] net: phy: realtek: add support for reading MDIO_MMD_VEND2 - regs on RTL8125/RTL8126 - -RTL8125/RTL8126 don't support MMD access to the internal PHY, but -provide a mechanism to access at least all MDIO_MMD_VEND2 registers. -By exposing this mechanism standard MMD access functions can be used -to access the MDIO_MMD_VEND2 registers. - -Signed-off-by: Heiner Kallweit -Reviewed-by: Andrew Lunn -Link: https://patch.msgid.link/e821b302-5fe6-49ab-aabd-05da500581c0@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/realtek.c | 12 ++++++++++-- - 1 file changed, 10 insertions(+), 2 deletions(-) - ---- a/drivers/net/phy/realtek.c -+++ b/drivers/net/phy/realtek.c -@@ -736,7 +736,11 @@ static int rtlgen_read_mmd(struct phy_de - { - int ret; - -- if (devnum == MDIO_MMD_PCS && regnum == MDIO_PCS_EEE_ABLE) { -+ if (devnum == MDIO_MMD_VEND2) { -+ rtl821x_write_page(phydev, regnum >> 4); -+ ret = __phy_read(phydev, 0x10 + ((regnum & 0xf) >> 1)); -+ rtl821x_write_page(phydev, 0); -+ } else if (devnum == MDIO_MMD_PCS && regnum == MDIO_PCS_EEE_ABLE) { - rtl821x_write_page(phydev, 0xa5c); - ret = __phy_read(phydev, 0x12); - rtl821x_write_page(phydev, 0); -@@ -760,7 +764,11 @@ static int rtlgen_write_mmd(struct phy_d - { - int ret; - -- if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_ADV) { -+ if (devnum == MDIO_MMD_VEND2) { -+ rtl821x_write_page(phydev, regnum >> 4); -+ ret = __phy_write(phydev, 0x10 + ((regnum & 0xf) >> 1), val); -+ rtl821x_write_page(phydev, 0); -+ } else if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_ADV) { - rtl821x_write_page(phydev, 0xa5d); - ret = __phy_write(phydev, 0x10, val); - rtl821x_write_page(phydev, 0); diff --git a/target/linux/generic/backport-6.18/781-07-v6.14-net-phy-realtek-clear-1000Base-T-lpa-if-link-is-down.patch b/target/linux/generic/backport-6.18/781-07-v6.14-net-phy-realtek-clear-1000Base-T-lpa-if-link-is-down.patch deleted file mode 100644 index 002b99e4d5..0000000000 --- a/target/linux/generic/backport-6.18/781-07-v6.14-net-phy-realtek-clear-1000Base-T-lpa-if-link-is-down.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 34d5a86ff7bbe225fba3ad91f9b4dc85fb408e18 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Wed, 15 Jan 2025 14:43:35 +0000 -Subject: [PATCH] net: phy: realtek: clear 1000Base-T lpa if link is down - -Only read 1000Base-T link partner advertisement if autonegotiation has -completed and otherwise 1000Base-T link partner advertisement bits. - -This fixes bogus 1000Base-T link partner advertisement after link goes -down (eg. by disconnecting the wire). -Fixes: 5cb409b3960e ("net: phy: realtek: clear 1000Base-T link partner advertisement") -Signed-off-by: Daniel Golle -Reviewed-by: Michal Swiatkowski -Signed-off-by: David S. Miller ---- - drivers/net/phy/realtek.c | 19 ++++++++----------- - 1 file changed, 8 insertions(+), 11 deletions(-) - ---- a/drivers/net/phy/realtek.c -+++ b/drivers/net/phy/realtek.c -@@ -1031,23 +1031,20 @@ static int rtl822x_c45_read_status(struc - { - int ret, val; - -- ret = genphy_c45_read_status(phydev); -- if (ret < 0) -- return ret; -- -- if (phydev->autoneg == AUTONEG_DISABLE || -- !genphy_c45_aneg_done(phydev)) -- mii_stat1000_mod_linkmode_lpa_t(phydev->lp_advertising, 0); -- - /* Vendor register as C45 has no standardized support for 1000BaseT */ -- if (phydev->autoneg == AUTONEG_ENABLE) { -+ if (phydev->autoneg == AUTONEG_ENABLE && genphy_c45_aneg_done(phydev)) { - val = phy_read_mmd(phydev, MDIO_MMD_VEND2, - RTL822X_VND2_GANLPAR); - if (val < 0) - return val; -- -- mii_stat1000_mod_linkmode_lpa_t(phydev->lp_advertising, val); -+ } else { -+ val = 0; - } -+ mii_stat1000_mod_linkmode_lpa_t(phydev->lp_advertising, val); -+ -+ ret = genphy_c45_read_status(phydev); -+ if (ret < 0) -+ return ret; - - if (!phydev->link) - return 0; diff --git a/target/linux/generic/backport-6.18/781-08-v6.14-net-phy-realtek-clear-master_slave_state-if-link-is-.patch b/target/linux/generic/backport-6.18/781-08-v6.14-net-phy-realtek-clear-master_slave_state-if-link-is-.patch deleted file mode 100644 index f8cfc4d131..0000000000 --- a/target/linux/generic/backport-6.18/781-08-v6.14-net-phy-realtek-clear-master_slave_state-if-link-is-.patch +++ /dev/null @@ -1,35 +0,0 @@ -From ea8318cb33e593bbfc59d637eae45a69732c5387 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Wed, 15 Jan 2025 14:43:43 +0000 -Subject: [PATCH] net: phy: realtek: clear master_slave_state if link is down - -rtlgen_decode_physr() which sets master_slave_state isn't called in case -the link is down and other than rtlgen_read_status(), -rtl822x_c45_read_status() doesn't implicitely clear master_slave_state. - -Avoid stale master_slave_state by always setting it to -MASTER_SLAVE_STATE_UNKNOWN in rtl822x_c45_read_status() in case the link -is down. - -Fixes: 081c9c0265c9 ("net: phy: realtek: read duplex and gbit master from PHYSR register") -Signed-off-by: Daniel Golle -Reviewed-by: Michal Swiatkowski -Signed-off-by: David S. Miller ---- - drivers/net/phy/realtek.c | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - ---- a/drivers/net/phy/realtek.c -+++ b/drivers/net/phy/realtek.c -@@ -1046,8 +1046,10 @@ static int rtl822x_c45_read_status(struc - if (ret < 0) - return ret; - -- if (!phydev->link) -+ if (!phydev->link) { -+ phydev->master_slave_state = MASTER_SLAVE_STATE_UNKNOWN; - return 0; -+ } - - /* Read actual speed from vendor register. */ - val = phy_read_mmd(phydev, MDIO_MMD_VEND2, RTL_VND2_PHYSR); diff --git a/target/linux/generic/backport-6.18/781-09-v6.14-net-phy-realtek-always-clear-NBase-T-lpa.patch b/target/linux/generic/backport-6.18/781-09-v6.14-net-phy-realtek-always-clear-NBase-T-lpa.patch deleted file mode 100644 index e628bed6b4..0000000000 --- a/target/linux/generic/backport-6.18/781-09-v6.14-net-phy-realtek-always-clear-NBase-T-lpa.patch +++ /dev/null @@ -1,42 +0,0 @@ -From d3eb58549842c60ed46f37da7f4da969e3d6ecd3 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Wed, 15 Jan 2025 14:45:00 +0000 -Subject: [PATCH] net: phy: realtek: always clear NBase-T lpa - -Clear NBase-T link partner advertisement before calling -rtlgen_read_status() to avoid phy_resolve_aneg_linkmode() wrongly -setting speed and duplex. - -This fixes bogus 2.5G/5G/10G link partner advertisement and thus -speed and duplex being set by phy_resolve_aneg_linkmode() due to stale -NBase-T lpa. - -Fixes: 68d5cd09e891 ("net: phy: realtek: change order of calls in C22 read_status()") -Signed-off-by: Daniel Golle -Reviewed-by: Michal Swiatkowski -Signed-off-by: David S. Miller ---- - drivers/net/phy/realtek.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - ---- a/drivers/net/phy/realtek.c -+++ b/drivers/net/phy/realtek.c -@@ -960,15 +960,15 @@ static int rtl822x_read_status(struct ph - { - int lpadv, ret; - -+ mii_10gbt_stat_mod_linkmode_lpa_t(phydev->lp_advertising, 0); -+ - ret = rtlgen_read_status(phydev); - if (ret < 0) - return ret; - - if (phydev->autoneg == AUTONEG_DISABLE || -- !phydev->autoneg_complete) { -- mii_10gbt_stat_mod_linkmode_lpa_t(phydev->lp_advertising, 0); -+ !phydev->autoneg_complete) - return 0; -- } - - lpadv = phy_read_paged(phydev, 0xa5d, 0x13); - if (lpadv < 0) diff --git a/target/linux/generic/backport-6.18/781-10-v6.14-net-phy-move-realtek-PHY-driver-to-its-own-subdirect.patch b/target/linux/generic/backport-6.18/781-10-v6.14-net-phy-move-realtek-PHY-driver-to-its-own-subdirect.patch deleted file mode 100644 index 633468f93a..0000000000 --- a/target/linux/generic/backport-6.18/781-10-v6.14-net-phy-move-realtek-PHY-driver-to-its-own-subdirect.patch +++ /dev/null @@ -1,3247 +0,0 @@ -From 1416a9b2ba710d31954131c06d46f298e340aa2c Mon Sep 17 00:00:00 2001 -From: Heiner Kallweit -Date: Sat, 11 Jan 2025 21:50:19 +0100 -Subject: [PATCH] net: phy: move realtek PHY driver to its own subdirectory - -In preparation of adding a source file with hwmon support, move the -Realtek PHY driver to its own subdirectory and rename realtek.c to -realtek_main.c. - -Signed-off-by: Heiner Kallweit -Reviewed-by: Andrew Lunn -Link: https://patch.msgid.link/c566551b-c915-4e34-9b33-129a6ddd6e4c@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/Kconfig | 5 +---- - drivers/net/phy/Makefile | 2 +- - drivers/net/phy/realtek/Kconfig | 5 +++++ - drivers/net/phy/realtek/Makefile | 3 +++ - drivers/net/phy/{realtek.c => realtek/realtek_main.c} | 0 - 5 files changed, 10 insertions(+), 5 deletions(-) - create mode 100644 drivers/net/phy/realtek/Kconfig - create mode 100644 drivers/net/phy/realtek/Makefile - rename drivers/net/phy/{realtek.c => realtek/realtek_main.c} (100%) - ---- a/drivers/net/phy/Kconfig -+++ b/drivers/net/phy/Kconfig -@@ -343,10 +343,7 @@ config QSEMI_PHY - help - Currently supports the qs6612 - --config REALTEK_PHY -- tristate "Realtek PHYs" -- help -- Supports the Realtek 821x PHY. -+source "drivers/net/phy/realtek/Kconfig" - - config RENESAS_PHY - tristate "Renesas PHYs" ---- a/drivers/net/phy/Makefile -+++ b/drivers/net/phy/Makefile -@@ -94,7 +94,7 @@ obj-$(CONFIG_NXP_CBTX_PHY) += nxp-cbtx.o - obj-$(CONFIG_NXP_TJA11XX_PHY) += nxp-tja11xx.o - obj-y += qcom/ - obj-$(CONFIG_QSEMI_PHY) += qsemi.o --obj-$(CONFIG_REALTEK_PHY) += realtek.o -+obj-$(CONFIG_REALTEK_PHY) += realtek/ - obj-$(CONFIG_RENESAS_PHY) += uPD60620.o - obj-$(CONFIG_ROCKCHIP_PHY) += rockchip.o - obj-$(CONFIG_SMSC_PHY) += smsc.o ---- /dev/null -+++ b/drivers/net/phy/realtek/Kconfig -@@ -0,0 +1,5 @@ -+# SPDX-License-Identifier: GPL-2.0-only -+config REALTEK_PHY -+ tristate "Realtek PHYs" -+ help -+ Currently supports RTL821x/RTL822x and fast ethernet PHYs ---- /dev/null -+++ b/drivers/net/phy/realtek/Makefile -@@ -0,0 +1,3 @@ -+# SPDX-License-Identifier: GPL-2.0 -+realtek-y += realtek_main.o -+obj-$(CONFIG_REALTEK_PHY) += realtek.o ---- a/drivers/net/phy/realtek.c -+++ /dev/null -@@ -1,1589 +0,0 @@ --// SPDX-License-Identifier: GPL-2.0+ --/* drivers/net/phy/realtek.c -- * -- * Driver for Realtek PHYs -- * -- * Author: Johnson Leung -- * -- * Copyright (c) 2004 Freescale Semiconductor, Inc. -- */ --#include --#include --#include --#include --#include --#include -- --#define RTL821x_PHYSR 0x11 --#define RTL821x_PHYSR_DUPLEX BIT(13) --#define RTL821x_PHYSR_SPEED GENMASK(15, 14) -- --#define RTL821x_INER 0x12 --#define RTL8211B_INER_INIT 0x6400 --#define RTL8211E_INER_LINK_STATUS BIT(10) --#define RTL8211F_INER_LINK_STATUS BIT(4) -- --#define RTL821x_INSR 0x13 -- --#define RTL821x_EXT_PAGE_SELECT 0x1e --#define RTL821x_PAGE_SELECT 0x1f -- --#define RTL8211F_PHYCR1 0x18 --#define RTL8211F_PHYCR2 0x19 --#define RTL8211F_INSR 0x1d -- --#define RTL8211F_LEDCR 0x10 --#define RTL8211F_LEDCR_MODE BIT(15) --#define RTL8211F_LEDCR_ACT_TXRX BIT(4) --#define RTL8211F_LEDCR_LINK_1000 BIT(3) --#define RTL8211F_LEDCR_LINK_100 BIT(1) --#define RTL8211F_LEDCR_LINK_10 BIT(0) --#define RTL8211F_LEDCR_MASK GENMASK(4, 0) --#define RTL8211F_LEDCR_SHIFT 5 -- --#define RTL8211F_TX_DELAY BIT(8) --#define RTL8211F_RX_DELAY BIT(3) -- --#define RTL8211F_ALDPS_PLL_OFF BIT(1) --#define RTL8211F_ALDPS_ENABLE BIT(2) --#define RTL8211F_ALDPS_XTAL_OFF BIT(12) -- --#define RTL8211E_CTRL_DELAY BIT(13) --#define RTL8211E_TX_DELAY BIT(12) --#define RTL8211E_RX_DELAY BIT(11) -- --#define RTL8211F_CLKOUT_EN BIT(0) -- --#define RTL8201F_ISR 0x1e --#define RTL8201F_ISR_ANERR BIT(15) --#define RTL8201F_ISR_DUPLEX BIT(13) --#define RTL8201F_ISR_LINK BIT(11) --#define RTL8201F_ISR_MASK (RTL8201F_ISR_ANERR | \ -- RTL8201F_ISR_DUPLEX | \ -- RTL8201F_ISR_LINK) --#define RTL8201F_IER 0x13 -- --#define RTL822X_VND1_SERDES_OPTION 0x697a --#define RTL822X_VND1_SERDES_OPTION_MODE_MASK GENMASK(5, 0) --#define RTL822X_VND1_SERDES_OPTION_MODE_2500BASEX_SGMII 0 --#define RTL822X_VND1_SERDES_OPTION_MODE_2500BASEX 2 -- --#define RTL822X_VND1_SERDES_CTRL3 0x7580 --#define RTL822X_VND1_SERDES_CTRL3_MODE_MASK GENMASK(5, 0) --#define RTL822X_VND1_SERDES_CTRL3_MODE_SGMII 0x02 --#define RTL822X_VND1_SERDES_CTRL3_MODE_2500BASEX 0x16 -- --/* RTL822X_VND2_XXXXX registers are only accessible when phydev->is_c45 -- * is set, they cannot be accessed by C45-over-C22. -- */ --#define RTL822X_VND2_GBCR 0xa412 -- --#define RTL822X_VND2_GANLPAR 0xa414 -- --#define RTL8366RB_POWER_SAVE 0x15 --#define RTL8366RB_POWER_SAVE_ON BIT(12) -- --#define RTL9000A_GINMR 0x14 --#define RTL9000A_GINMR_LINK_STATUS BIT(4) -- --#define RTL_VND2_PHYSR 0xa434 --#define RTL_VND2_PHYSR_DUPLEX BIT(3) --#define RTL_VND2_PHYSR_SPEEDL GENMASK(5, 4) --#define RTL_VND2_PHYSR_SPEEDH GENMASK(10, 9) --#define RTL_VND2_PHYSR_MASTER BIT(11) --#define RTL_VND2_PHYSR_SPEED_MASK (RTL_VND2_PHYSR_SPEEDL | RTL_VND2_PHYSR_SPEEDH) -- --#define RTL_GENERIC_PHYID 0x001cc800 --#define RTL_8211FVD_PHYID 0x001cc878 --#define RTL_8221B 0x001cc840 --#define RTL_8221B_VB_CG 0x001cc849 --#define RTL_8221B_VN_CG 0x001cc84a --#define RTL_8251B 0x001cc862 -- --#define RTL8211F_LED_COUNT 3 -- --MODULE_DESCRIPTION("Realtek PHY driver"); --MODULE_AUTHOR("Johnson Leung"); --MODULE_LICENSE("GPL"); -- --struct rtl821x_priv { -- u16 phycr1; -- u16 phycr2; -- bool has_phycr2; -- struct clk *clk; --}; -- --static int rtl821x_read_page(struct phy_device *phydev) --{ -- return __phy_read(phydev, RTL821x_PAGE_SELECT); --} -- --static int rtl821x_write_page(struct phy_device *phydev, int page) --{ -- return __phy_write(phydev, RTL821x_PAGE_SELECT, page); --} -- --static int rtl821x_probe(struct phy_device *phydev) --{ -- struct device *dev = &phydev->mdio.dev; -- struct rtl821x_priv *priv; -- u32 phy_id = phydev->drv->phy_id; -- int ret; -- -- priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); -- if (!priv) -- return -ENOMEM; -- -- priv->clk = devm_clk_get_optional_enabled(dev, NULL); -- if (IS_ERR(priv->clk)) -- return dev_err_probe(dev, PTR_ERR(priv->clk), -- "failed to get phy clock\n"); -- -- ret = phy_read_paged(phydev, 0xa43, RTL8211F_PHYCR1); -- if (ret < 0) -- return ret; -- -- priv->phycr1 = ret & (RTL8211F_ALDPS_PLL_OFF | RTL8211F_ALDPS_ENABLE | RTL8211F_ALDPS_XTAL_OFF); -- if (of_property_read_bool(dev->of_node, "realtek,aldps-enable")) -- priv->phycr1 |= RTL8211F_ALDPS_PLL_OFF | RTL8211F_ALDPS_ENABLE | RTL8211F_ALDPS_XTAL_OFF; -- -- priv->has_phycr2 = !(phy_id == RTL_8211FVD_PHYID); -- if (priv->has_phycr2) { -- ret = phy_read_paged(phydev, 0xa43, RTL8211F_PHYCR2); -- if (ret < 0) -- return ret; -- -- priv->phycr2 = ret & RTL8211F_CLKOUT_EN; -- if (of_property_read_bool(dev->of_node, "realtek,clkout-disable")) -- priv->phycr2 &= ~RTL8211F_CLKOUT_EN; -- } -- -- phydev->priv = priv; -- -- return 0; --} -- --static int rtl8201_ack_interrupt(struct phy_device *phydev) --{ -- int err; -- -- err = phy_read(phydev, RTL8201F_ISR); -- -- return (err < 0) ? err : 0; --} -- --static int rtl821x_ack_interrupt(struct phy_device *phydev) --{ -- int err; -- -- err = phy_read(phydev, RTL821x_INSR); -- -- return (err < 0) ? err : 0; --} -- --static int rtl8211f_ack_interrupt(struct phy_device *phydev) --{ -- int err; -- -- err = phy_read_paged(phydev, 0xa43, RTL8211F_INSR); -- -- return (err < 0) ? err : 0; --} -- --static int rtl8201_config_intr(struct phy_device *phydev) --{ -- u16 val; -- int err; -- -- if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { -- err = rtl8201_ack_interrupt(phydev); -- if (err) -- return err; -- -- val = BIT(13) | BIT(12) | BIT(11); -- err = phy_write_paged(phydev, 0x7, RTL8201F_IER, val); -- } else { -- val = 0; -- err = phy_write_paged(phydev, 0x7, RTL8201F_IER, val); -- if (err) -- return err; -- -- err = rtl8201_ack_interrupt(phydev); -- } -- -- return err; --} -- --static int rtl8211b_config_intr(struct phy_device *phydev) --{ -- int err; -- -- if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { -- err = rtl821x_ack_interrupt(phydev); -- if (err) -- return err; -- -- err = phy_write(phydev, RTL821x_INER, -- RTL8211B_INER_INIT); -- } else { -- err = phy_write(phydev, RTL821x_INER, 0); -- if (err) -- return err; -- -- err = rtl821x_ack_interrupt(phydev); -- } -- -- return err; --} -- --static int rtl8211e_config_intr(struct phy_device *phydev) --{ -- int err; -- -- if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { -- err = rtl821x_ack_interrupt(phydev); -- if (err) -- return err; -- -- err = phy_write(phydev, RTL821x_INER, -- RTL8211E_INER_LINK_STATUS); -- } else { -- err = phy_write(phydev, RTL821x_INER, 0); -- if (err) -- return err; -- -- err = rtl821x_ack_interrupt(phydev); -- } -- -- return err; --} -- --static int rtl8211f_config_intr(struct phy_device *phydev) --{ -- u16 val; -- int err; -- -- if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { -- err = rtl8211f_ack_interrupt(phydev); -- if (err) -- return err; -- -- val = RTL8211F_INER_LINK_STATUS; -- err = phy_write_paged(phydev, 0xa42, RTL821x_INER, val); -- } else { -- val = 0; -- err = phy_write_paged(phydev, 0xa42, RTL821x_INER, val); -- if (err) -- return err; -- -- err = rtl8211f_ack_interrupt(phydev); -- } -- -- return err; --} -- --static irqreturn_t rtl8201_handle_interrupt(struct phy_device *phydev) --{ -- int irq_status; -- -- irq_status = phy_read(phydev, RTL8201F_ISR); -- if (irq_status < 0) { -- phy_error(phydev); -- return IRQ_NONE; -- } -- -- if (!(irq_status & RTL8201F_ISR_MASK)) -- return IRQ_NONE; -- -- phy_trigger_machine(phydev); -- -- return IRQ_HANDLED; --} -- --static irqreturn_t rtl821x_handle_interrupt(struct phy_device *phydev) --{ -- int irq_status, irq_enabled; -- -- irq_status = phy_read(phydev, RTL821x_INSR); -- if (irq_status < 0) { -- phy_error(phydev); -- return IRQ_NONE; -- } -- -- irq_enabled = phy_read(phydev, RTL821x_INER); -- if (irq_enabled < 0) { -- phy_error(phydev); -- return IRQ_NONE; -- } -- -- if (!(irq_status & irq_enabled)) -- return IRQ_NONE; -- -- phy_trigger_machine(phydev); -- -- return IRQ_HANDLED; --} -- --static irqreturn_t rtl8211f_handle_interrupt(struct phy_device *phydev) --{ -- int irq_status; -- -- irq_status = phy_read_paged(phydev, 0xa43, RTL8211F_INSR); -- if (irq_status < 0) { -- phy_error(phydev); -- return IRQ_NONE; -- } -- -- if (!(irq_status & RTL8211F_INER_LINK_STATUS)) -- return IRQ_NONE; -- -- phy_trigger_machine(phydev); -- -- return IRQ_HANDLED; --} -- --static int rtl8211_config_aneg(struct phy_device *phydev) --{ -- int ret; -- -- ret = genphy_config_aneg(phydev); -- if (ret < 0) -- return ret; -- -- /* Quirk was copied from vendor driver. Unfortunately it includes no -- * description of the magic numbers. -- */ -- if (phydev->speed == SPEED_100 && phydev->autoneg == AUTONEG_DISABLE) { -- phy_write(phydev, 0x17, 0x2138); -- phy_write(phydev, 0x0e, 0x0260); -- } else { -- phy_write(phydev, 0x17, 0x2108); -- phy_write(phydev, 0x0e, 0x0000); -- } -- -- return 0; --} -- --static int rtl8211c_config_init(struct phy_device *phydev) --{ -- /* RTL8211C has an issue when operating in Gigabit slave mode */ -- return phy_set_bits(phydev, MII_CTRL1000, -- CTL1000_ENABLE_MASTER | CTL1000_AS_MASTER); --} -- --static int rtl8211f_config_init(struct phy_device *phydev) --{ -- struct rtl821x_priv *priv = phydev->priv; -- struct device *dev = &phydev->mdio.dev; -- u16 val_txdly, val_rxdly; -- int ret; -- -- ret = phy_modify_paged_changed(phydev, 0xa43, RTL8211F_PHYCR1, -- RTL8211F_ALDPS_PLL_OFF | RTL8211F_ALDPS_ENABLE | RTL8211F_ALDPS_XTAL_OFF, -- priv->phycr1); -- if (ret < 0) { -- dev_err(dev, "aldps mode configuration failed: %pe\n", -- ERR_PTR(ret)); -- return ret; -- } -- -- switch (phydev->interface) { -- case PHY_INTERFACE_MODE_RGMII: -- val_txdly = 0; -- val_rxdly = 0; -- break; -- -- case PHY_INTERFACE_MODE_RGMII_RXID: -- val_txdly = 0; -- val_rxdly = RTL8211F_RX_DELAY; -- break; -- -- case PHY_INTERFACE_MODE_RGMII_TXID: -- val_txdly = RTL8211F_TX_DELAY; -- val_rxdly = 0; -- break; -- -- case PHY_INTERFACE_MODE_RGMII_ID: -- val_txdly = RTL8211F_TX_DELAY; -- val_rxdly = RTL8211F_RX_DELAY; -- break; -- -- default: /* the rest of the modes imply leaving delay as is. */ -- return 0; -- } -- -- ret = phy_modify_paged_changed(phydev, 0xd08, 0x11, RTL8211F_TX_DELAY, -- val_txdly); -- if (ret < 0) { -- dev_err(dev, "Failed to update the TX delay register\n"); -- return ret; -- } else if (ret) { -- dev_dbg(dev, -- "%s 2ns TX delay (and changing the value from pin-strapping RXD1 or the bootloader)\n", -- val_txdly ? "Enabling" : "Disabling"); -- } else { -- dev_dbg(dev, -- "2ns TX delay was already %s (by pin-strapping RXD1 or bootloader configuration)\n", -- val_txdly ? "enabled" : "disabled"); -- } -- -- ret = phy_modify_paged_changed(phydev, 0xd08, 0x15, RTL8211F_RX_DELAY, -- val_rxdly); -- if (ret < 0) { -- dev_err(dev, "Failed to update the RX delay register\n"); -- return ret; -- } else if (ret) { -- dev_dbg(dev, -- "%s 2ns RX delay (and changing the value from pin-strapping RXD0 or the bootloader)\n", -- val_rxdly ? "Enabling" : "Disabling"); -- } else { -- dev_dbg(dev, -- "2ns RX delay was already %s (by pin-strapping RXD0 or bootloader configuration)\n", -- val_rxdly ? "enabled" : "disabled"); -- } -- -- if (priv->has_phycr2) { -- ret = phy_modify_paged(phydev, 0xa43, RTL8211F_PHYCR2, -- RTL8211F_CLKOUT_EN, priv->phycr2); -- if (ret < 0) { -- dev_err(dev, "clkout configuration failed: %pe\n", -- ERR_PTR(ret)); -- return ret; -- } -- -- return genphy_soft_reset(phydev); -- } -- -- return 0; --} -- --static int rtl821x_suspend(struct phy_device *phydev) --{ -- struct rtl821x_priv *priv = phydev->priv; -- int ret = 0; -- -- if (!phydev->wol_enabled) { -- ret = genphy_suspend(phydev); -- -- if (ret) -- return ret; -- -- clk_disable_unprepare(priv->clk); -- } -- -- return ret; --} -- --static int rtl821x_resume(struct phy_device *phydev) --{ -- struct rtl821x_priv *priv = phydev->priv; -- int ret; -- -- if (!phydev->wol_enabled) -- clk_prepare_enable(priv->clk); -- -- ret = genphy_resume(phydev); -- if (ret < 0) -- return ret; -- -- msleep(20); -- -- return 0; --} -- --static int rtl8211f_led_hw_is_supported(struct phy_device *phydev, u8 index, -- unsigned long rules) --{ -- const unsigned long mask = BIT(TRIGGER_NETDEV_LINK_10) | -- BIT(TRIGGER_NETDEV_LINK_100) | -- BIT(TRIGGER_NETDEV_LINK_1000) | -- BIT(TRIGGER_NETDEV_RX) | -- BIT(TRIGGER_NETDEV_TX); -- -- /* The RTL8211F PHY supports these LED settings on up to three LEDs: -- * - Link: Configurable subset of 10/100/1000 link rates -- * - Active: Blink on activity, RX or TX is not differentiated -- * The Active option has two modes, A and B: -- * - A: Link and Active indication at configurable, but matching, -- * subset of 10/100/1000 link rates -- * - B: Link indication at configurable subset of 10/100/1000 link -- * rates and Active indication always at all three 10+100+1000 -- * link rates. -- * This code currently uses mode B only. -- */ -- -- if (index >= RTL8211F_LED_COUNT) -- return -EINVAL; -- -- /* Filter out any other unsupported triggers. */ -- if (rules & ~mask) -- return -EOPNOTSUPP; -- -- /* RX and TX are not differentiated, either both are set or not set. */ -- if (!(rules & BIT(TRIGGER_NETDEV_RX)) ^ !(rules & BIT(TRIGGER_NETDEV_TX))) -- return -EOPNOTSUPP; -- -- return 0; --} -- --static int rtl8211f_led_hw_control_get(struct phy_device *phydev, u8 index, -- unsigned long *rules) --{ -- int val; -- -- if (index >= RTL8211F_LED_COUNT) -- return -EINVAL; -- -- val = phy_read_paged(phydev, 0xd04, RTL8211F_LEDCR); -- if (val < 0) -- return val; -- -- val >>= RTL8211F_LEDCR_SHIFT * index; -- val &= RTL8211F_LEDCR_MASK; -- -- if (val & RTL8211F_LEDCR_LINK_10) -- set_bit(TRIGGER_NETDEV_LINK_10, rules); -- -- if (val & RTL8211F_LEDCR_LINK_100) -- set_bit(TRIGGER_NETDEV_LINK_100, rules); -- -- if (val & RTL8211F_LEDCR_LINK_1000) -- set_bit(TRIGGER_NETDEV_LINK_1000, rules); -- -- if (val & RTL8211F_LEDCR_ACT_TXRX) { -- set_bit(TRIGGER_NETDEV_RX, rules); -- set_bit(TRIGGER_NETDEV_TX, rules); -- } -- -- return 0; --} -- --static int rtl8211f_led_hw_control_set(struct phy_device *phydev, u8 index, -- unsigned long rules) --{ -- const u16 mask = RTL8211F_LEDCR_MASK << (RTL8211F_LEDCR_SHIFT * index); -- u16 reg = 0; -- -- if (index >= RTL8211F_LED_COUNT) -- return -EINVAL; -- -- if (test_bit(TRIGGER_NETDEV_LINK_10, &rules)) -- reg |= RTL8211F_LEDCR_LINK_10; -- -- if (test_bit(TRIGGER_NETDEV_LINK_100, &rules)) -- reg |= RTL8211F_LEDCR_LINK_100; -- -- if (test_bit(TRIGGER_NETDEV_LINK_1000, &rules)) -- reg |= RTL8211F_LEDCR_LINK_1000; -- -- if (test_bit(TRIGGER_NETDEV_RX, &rules) || -- test_bit(TRIGGER_NETDEV_TX, &rules)) { -- reg |= RTL8211F_LEDCR_ACT_TXRX; -- } -- -- reg <<= RTL8211F_LEDCR_SHIFT * index; -- reg |= RTL8211F_LEDCR_MODE; /* Mode B */ -- -- return phy_modify_paged(phydev, 0xd04, RTL8211F_LEDCR, mask, reg); --} -- --static int rtl8211e_config_init(struct phy_device *phydev) --{ -- int ret = 0, oldpage; -- u16 val; -- -- /* enable TX/RX delay for rgmii-* modes, and disable them for rgmii. */ -- switch (phydev->interface) { -- case PHY_INTERFACE_MODE_RGMII: -- val = RTL8211E_CTRL_DELAY | 0; -- break; -- case PHY_INTERFACE_MODE_RGMII_ID: -- val = RTL8211E_CTRL_DELAY | RTL8211E_TX_DELAY | RTL8211E_RX_DELAY; -- break; -- case PHY_INTERFACE_MODE_RGMII_RXID: -- val = RTL8211E_CTRL_DELAY | RTL8211E_RX_DELAY; -- break; -- case PHY_INTERFACE_MODE_RGMII_TXID: -- val = RTL8211E_CTRL_DELAY | RTL8211E_TX_DELAY; -- break; -- default: /* the rest of the modes imply leaving delays as is. */ -- return 0; -- } -- -- /* According to a sample driver there is a 0x1c config register on the -- * 0xa4 extension page (0x7) layout. It can be used to disable/enable -- * the RX/TX delays otherwise controlled by RXDLY/TXDLY pins. -- * The configuration register definition: -- * 14 = reserved -- * 13 = Force Tx RX Delay controlled by bit12 bit11, -- * 12 = RX Delay, 11 = TX Delay -- * 10:0 = Test && debug settings reserved by realtek -- */ -- oldpage = phy_select_page(phydev, 0x7); -- if (oldpage < 0) -- goto err_restore_page; -- -- ret = __phy_write(phydev, RTL821x_EXT_PAGE_SELECT, 0xa4); -- if (ret) -- goto err_restore_page; -- -- ret = __phy_modify(phydev, 0x1c, RTL8211E_CTRL_DELAY -- | RTL8211E_TX_DELAY | RTL8211E_RX_DELAY, -- val); -- --err_restore_page: -- return phy_restore_page(phydev, oldpage, ret); --} -- --static int rtl8211b_suspend(struct phy_device *phydev) --{ -- phy_write(phydev, MII_MMD_DATA, BIT(9)); -- -- return genphy_suspend(phydev); --} -- --static int rtl8211b_resume(struct phy_device *phydev) --{ -- phy_write(phydev, MII_MMD_DATA, 0); -- -- return genphy_resume(phydev); --} -- --static int rtl8366rb_config_init(struct phy_device *phydev) --{ -- int ret; -- -- ret = phy_set_bits(phydev, RTL8366RB_POWER_SAVE, -- RTL8366RB_POWER_SAVE_ON); -- if (ret) { -- dev_err(&phydev->mdio.dev, -- "error enabling power management\n"); -- } -- -- return ret; --} -- --/* get actual speed to cover the downshift case */ --static void rtlgen_decode_physr(struct phy_device *phydev, int val) --{ -- /* bit 3 -- * 0: Half Duplex -- * 1: Full Duplex -- */ -- if (val & RTL_VND2_PHYSR_DUPLEX) -- phydev->duplex = DUPLEX_FULL; -- else -- phydev->duplex = DUPLEX_HALF; -- -- switch (val & RTL_VND2_PHYSR_SPEED_MASK) { -- case 0x0000: -- phydev->speed = SPEED_10; -- break; -- case 0x0010: -- phydev->speed = SPEED_100; -- break; -- case 0x0020: -- phydev->speed = SPEED_1000; -- break; -- case 0x0200: -- phydev->speed = SPEED_10000; -- break; -- case 0x0210: -- phydev->speed = SPEED_2500; -- break; -- case 0x0220: -- phydev->speed = SPEED_5000; -- break; -- default: -- break; -- } -- -- /* bit 11 -- * 0: Slave Mode -- * 1: Master Mode -- */ -- if (phydev->speed >= 1000) { -- if (val & RTL_VND2_PHYSR_MASTER) -- phydev->master_slave_state = MASTER_SLAVE_STATE_MASTER; -- else -- phydev->master_slave_state = MASTER_SLAVE_STATE_SLAVE; -- } else { -- phydev->master_slave_state = MASTER_SLAVE_STATE_UNSUPPORTED; -- } --} -- --static int rtlgen_read_status(struct phy_device *phydev) --{ -- int ret, val; -- -- ret = genphy_read_status(phydev); -- if (ret < 0) -- return ret; -- -- if (!phydev->link) -- return 0; -- -- val = phy_read_paged(phydev, 0xa43, 0x12); -- if (val < 0) -- return val; -- -- rtlgen_decode_physr(phydev, val); -- -- return 0; --} -- --static int rtlgen_read_mmd(struct phy_device *phydev, int devnum, u16 regnum) --{ -- int ret; -- -- if (devnum == MDIO_MMD_VEND2) { -- rtl821x_write_page(phydev, regnum >> 4); -- ret = __phy_read(phydev, 0x10 + ((regnum & 0xf) >> 1)); -- rtl821x_write_page(phydev, 0); -- } else if (devnum == MDIO_MMD_PCS && regnum == MDIO_PCS_EEE_ABLE) { -- rtl821x_write_page(phydev, 0xa5c); -- ret = __phy_read(phydev, 0x12); -- rtl821x_write_page(phydev, 0); -- } else if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_ADV) { -- rtl821x_write_page(phydev, 0xa5d); -- ret = __phy_read(phydev, 0x10); -- rtl821x_write_page(phydev, 0); -- } else if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_LPABLE) { -- rtl821x_write_page(phydev, 0xa5d); -- ret = __phy_read(phydev, 0x11); -- rtl821x_write_page(phydev, 0); -- } else { -- ret = -EOPNOTSUPP; -- } -- -- return ret; --} -- --static int rtlgen_write_mmd(struct phy_device *phydev, int devnum, u16 regnum, -- u16 val) --{ -- int ret; -- -- if (devnum == MDIO_MMD_VEND2) { -- rtl821x_write_page(phydev, regnum >> 4); -- ret = __phy_write(phydev, 0x10 + ((regnum & 0xf) >> 1), val); -- rtl821x_write_page(phydev, 0); -- } else if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_ADV) { -- rtl821x_write_page(phydev, 0xa5d); -- ret = __phy_write(phydev, 0x10, val); -- rtl821x_write_page(phydev, 0); -- } else { -- ret = -EOPNOTSUPP; -- } -- -- return ret; --} -- --static int rtl822x_read_mmd(struct phy_device *phydev, int devnum, u16 regnum) --{ -- int ret = rtlgen_read_mmd(phydev, devnum, regnum); -- -- if (ret != -EOPNOTSUPP) -- return ret; -- -- if (devnum == MDIO_MMD_PCS && regnum == MDIO_PCS_EEE_ABLE2) { -- rtl821x_write_page(phydev, 0xa6e); -- ret = __phy_read(phydev, 0x16); -- rtl821x_write_page(phydev, 0); -- } else if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_ADV2) { -- rtl821x_write_page(phydev, 0xa6d); -- ret = __phy_read(phydev, 0x12); -- rtl821x_write_page(phydev, 0); -- } else if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_LPABLE2) { -- rtl821x_write_page(phydev, 0xa6d); -- ret = __phy_read(phydev, 0x10); -- rtl821x_write_page(phydev, 0); -- } -- -- return ret; --} -- --static int rtl822x_write_mmd(struct phy_device *phydev, int devnum, u16 regnum, -- u16 val) --{ -- int ret = rtlgen_write_mmd(phydev, devnum, regnum, val); -- -- if (ret != -EOPNOTSUPP) -- return ret; -- -- if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_ADV2) { -- rtl821x_write_page(phydev, 0xa6d); -- ret = __phy_write(phydev, 0x12, val); -- rtl821x_write_page(phydev, 0); -- } -- -- return ret; --} -- --static int rtl822xb_config_init(struct phy_device *phydev) --{ -- bool has_2500, has_sgmii; -- u16 mode; -- int ret; -- -- has_2500 = test_bit(PHY_INTERFACE_MODE_2500BASEX, -- phydev->host_interfaces) || -- phydev->interface == PHY_INTERFACE_MODE_2500BASEX; -- -- has_sgmii = test_bit(PHY_INTERFACE_MODE_SGMII, -- phydev->host_interfaces) || -- phydev->interface == PHY_INTERFACE_MODE_SGMII; -- -- /* fill in possible interfaces */ -- __assign_bit(PHY_INTERFACE_MODE_2500BASEX, phydev->possible_interfaces, -- has_2500); -- __assign_bit(PHY_INTERFACE_MODE_SGMII, phydev->possible_interfaces, -- has_sgmii); -- -- if (!has_2500 && !has_sgmii) -- return 0; -- -- /* determine SerDes option mode */ -- if (has_2500 && !has_sgmii) { -- mode = RTL822X_VND1_SERDES_OPTION_MODE_2500BASEX; -- phydev->rate_matching = RATE_MATCH_PAUSE; -- } else { -- mode = RTL822X_VND1_SERDES_OPTION_MODE_2500BASEX_SGMII; -- phydev->rate_matching = RATE_MATCH_NONE; -- } -- -- /* the following sequence with magic numbers sets up the SerDes -- * option mode -- */ -- ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x75f3, 0); -- if (ret < 0) -- return ret; -- -- ret = phy_modify_mmd_changed(phydev, MDIO_MMD_VEND1, -- RTL822X_VND1_SERDES_OPTION, -- RTL822X_VND1_SERDES_OPTION_MODE_MASK, -- mode); -- if (ret < 0) -- return ret; -- -- ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x6a04, 0x0503); -- if (ret < 0) -- return ret; -- -- ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x6f10, 0xd455); -- if (ret < 0) -- return ret; -- -- return phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x6f11, 0x8020); --} -- --static int rtl822xb_get_rate_matching(struct phy_device *phydev, -- phy_interface_t iface) --{ -- int val; -- -- /* Only rate matching at 2500base-x */ -- if (iface != PHY_INTERFACE_MODE_2500BASEX) -- return RATE_MATCH_NONE; -- -- val = phy_read_mmd(phydev, MDIO_MMD_VEND1, RTL822X_VND1_SERDES_OPTION); -- if (val < 0) -- return val; -- -- if ((val & RTL822X_VND1_SERDES_OPTION_MODE_MASK) == -- RTL822X_VND1_SERDES_OPTION_MODE_2500BASEX) -- return RATE_MATCH_PAUSE; -- -- /* RTL822X_VND1_SERDES_OPTION_MODE_2500BASEX_SGMII */ -- return RATE_MATCH_NONE; --} -- --static int rtl822x_get_features(struct phy_device *phydev) --{ -- int val; -- -- val = phy_read_paged(phydev, 0xa61, 0x13); -- if (val < 0) -- return val; -- -- linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, -- phydev->supported, val & MDIO_PMA_SPEED_2_5G); -- linkmode_mod_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT, -- phydev->supported, val & MDIO_PMA_SPEED_5G); -- linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT, -- phydev->supported, val & MDIO_SPEED_10G); -- -- return genphy_read_abilities(phydev); --} -- --static int rtl822x_config_aneg(struct phy_device *phydev) --{ -- int ret = 0; -- -- if (phydev->autoneg == AUTONEG_ENABLE) { -- u16 adv = linkmode_adv_to_mii_10gbt_adv_t(phydev->advertising); -- -- ret = phy_modify_paged_changed(phydev, 0xa5d, 0x12, -- MDIO_AN_10GBT_CTRL_ADV2_5G | -- MDIO_AN_10GBT_CTRL_ADV5G, -- adv); -- if (ret < 0) -- return ret; -- } -- -- return __genphy_config_aneg(phydev, ret); --} -- --static void rtl822xb_update_interface(struct phy_device *phydev) --{ -- int val; -- -- if (!phydev->link) -- return; -- -- /* Change interface according to serdes mode */ -- val = phy_read_mmd(phydev, MDIO_MMD_VEND1, RTL822X_VND1_SERDES_CTRL3); -- if (val < 0) -- return; -- -- switch (val & RTL822X_VND1_SERDES_CTRL3_MODE_MASK) { -- case RTL822X_VND1_SERDES_CTRL3_MODE_2500BASEX: -- phydev->interface = PHY_INTERFACE_MODE_2500BASEX; -- break; -- case RTL822X_VND1_SERDES_CTRL3_MODE_SGMII: -- phydev->interface = PHY_INTERFACE_MODE_SGMII; -- break; -- } --} -- --static int rtl822x_read_status(struct phy_device *phydev) --{ -- int lpadv, ret; -- -- mii_10gbt_stat_mod_linkmode_lpa_t(phydev->lp_advertising, 0); -- -- ret = rtlgen_read_status(phydev); -- if (ret < 0) -- return ret; -- -- if (phydev->autoneg == AUTONEG_DISABLE || -- !phydev->autoneg_complete) -- return 0; -- -- lpadv = phy_read_paged(phydev, 0xa5d, 0x13); -- if (lpadv < 0) -- return lpadv; -- -- mii_10gbt_stat_mod_linkmode_lpa_t(phydev->lp_advertising, lpadv); -- -- return 0; --} -- --static int rtl822xb_read_status(struct phy_device *phydev) --{ -- int ret; -- -- ret = rtl822x_read_status(phydev); -- if (ret < 0) -- return ret; -- -- rtl822xb_update_interface(phydev); -- -- return 0; --} -- --static int rtl822x_c45_get_features(struct phy_device *phydev) --{ -- linkmode_set_bit(ETHTOOL_LINK_MODE_TP_BIT, -- phydev->supported); -- -- return genphy_c45_pma_read_abilities(phydev); --} -- --static int rtl822x_c45_config_aneg(struct phy_device *phydev) --{ -- bool changed = false; -- int ret, val; -- -- if (phydev->autoneg == AUTONEG_DISABLE) -- return genphy_c45_pma_setup_forced(phydev); -- -- ret = genphy_c45_an_config_aneg(phydev); -- if (ret < 0) -- return ret; -- if (ret > 0) -- changed = true; -- -- val = linkmode_adv_to_mii_ctrl1000_t(phydev->advertising); -- -- /* Vendor register as C45 has no standardized support for 1000BaseT */ -- ret = phy_modify_mmd_changed(phydev, MDIO_MMD_VEND2, RTL822X_VND2_GBCR, -- ADVERTISE_1000FULL, val); -- if (ret < 0) -- return ret; -- if (ret > 0) -- changed = true; -- -- return genphy_c45_check_and_restart_aneg(phydev, changed); --} -- --static int rtl822x_c45_read_status(struct phy_device *phydev) --{ -- int ret, val; -- -- /* Vendor register as C45 has no standardized support for 1000BaseT */ -- if (phydev->autoneg == AUTONEG_ENABLE && genphy_c45_aneg_done(phydev)) { -- val = phy_read_mmd(phydev, MDIO_MMD_VEND2, -- RTL822X_VND2_GANLPAR); -- if (val < 0) -- return val; -- } else { -- val = 0; -- } -- mii_stat1000_mod_linkmode_lpa_t(phydev->lp_advertising, val); -- -- ret = genphy_c45_read_status(phydev); -- if (ret < 0) -- return ret; -- -- if (!phydev->link) { -- phydev->master_slave_state = MASTER_SLAVE_STATE_UNKNOWN; -- return 0; -- } -- -- /* Read actual speed from vendor register. */ -- val = phy_read_mmd(phydev, MDIO_MMD_VEND2, RTL_VND2_PHYSR); -- if (val < 0) -- return val; -- -- rtlgen_decode_physr(phydev, val); -- -- return 0; --} -- --static int rtl822xb_c45_read_status(struct phy_device *phydev) --{ -- int ret; -- -- ret = rtl822x_c45_read_status(phydev); -- if (ret < 0) -- return ret; -- -- rtl822xb_update_interface(phydev); -- -- return 0; --} -- --static bool rtlgen_supports_2_5gbps(struct phy_device *phydev) --{ -- int val; -- -- phy_write(phydev, RTL821x_PAGE_SELECT, 0xa61); -- val = phy_read(phydev, 0x13); -- phy_write(phydev, RTL821x_PAGE_SELECT, 0); -- -- return val >= 0 && val & MDIO_PMA_SPEED_2_5G; --} -- --/* On internal PHY's MMD reads over C22 always return 0. -- * Check a MMD register which is known to be non-zero. -- */ --static bool rtlgen_supports_mmd(struct phy_device *phydev) --{ -- int val; -- -- phy_lock_mdio_bus(phydev); -- __phy_write(phydev, MII_MMD_CTRL, MDIO_MMD_PCS); -- __phy_write(phydev, MII_MMD_DATA, MDIO_PCS_EEE_ABLE); -- __phy_write(phydev, MII_MMD_CTRL, MDIO_MMD_PCS | MII_MMD_CTRL_NOINCR); -- val = __phy_read(phydev, MII_MMD_DATA); -- phy_unlock_mdio_bus(phydev); -- -- return val > 0; --} -- --static int rtlgen_match_phy_device(struct phy_device *phydev) --{ -- return phydev->phy_id == RTL_GENERIC_PHYID && -- !rtlgen_supports_2_5gbps(phydev); --} -- --static int rtl8226_match_phy_device(struct phy_device *phydev) --{ -- return phydev->phy_id == RTL_GENERIC_PHYID && -- rtlgen_supports_2_5gbps(phydev) && -- rtlgen_supports_mmd(phydev); --} -- --static int rtlgen_is_c45_match(struct phy_device *phydev, unsigned int id, -- bool is_c45) --{ -- if (phydev->is_c45) -- return is_c45 && (id == phydev->c45_ids.device_ids[1]); -- else -- return !is_c45 && (id == phydev->phy_id); --} -- --static int rtl8221b_match_phy_device(struct phy_device *phydev) --{ -- return phydev->phy_id == RTL_8221B && rtlgen_supports_mmd(phydev); --} -- --static int rtl8221b_vb_cg_c22_match_phy_device(struct phy_device *phydev) --{ -- return rtlgen_is_c45_match(phydev, RTL_8221B_VB_CG, false); --} -- --static int rtl8221b_vb_cg_c45_match_phy_device(struct phy_device *phydev) --{ -- return rtlgen_is_c45_match(phydev, RTL_8221B_VB_CG, true); --} -- --static int rtl8221b_vn_cg_c22_match_phy_device(struct phy_device *phydev) --{ -- return rtlgen_is_c45_match(phydev, RTL_8221B_VN_CG, false); --} -- --static int rtl8221b_vn_cg_c45_match_phy_device(struct phy_device *phydev) --{ -- return rtlgen_is_c45_match(phydev, RTL_8221B_VN_CG, true); --} -- --static int rtl_internal_nbaset_match_phy_device(struct phy_device *phydev) --{ -- if (phydev->is_c45) -- return false; -- -- switch (phydev->phy_id) { -- case RTL_GENERIC_PHYID: -- case RTL_8221B: -- case RTL_8251B: -- case 0x001cc841: -- break; -- default: -- return false; -- } -- -- return rtlgen_supports_2_5gbps(phydev) && !rtlgen_supports_mmd(phydev); --} -- --static int rtl8251b_c45_match_phy_device(struct phy_device *phydev) --{ -- return rtlgen_is_c45_match(phydev, RTL_8251B, true); --} -- --static int rtlgen_resume(struct phy_device *phydev) --{ -- int ret = genphy_resume(phydev); -- -- /* Internal PHY's from RTL8168h up may not be instantly ready */ -- msleep(20); -- -- return ret; --} -- --static int rtlgen_c45_resume(struct phy_device *phydev) --{ -- int ret = genphy_c45_pma_resume(phydev); -- -- msleep(20); -- -- return ret; --} -- --static int rtl9000a_config_init(struct phy_device *phydev) --{ -- phydev->autoneg = AUTONEG_DISABLE; -- phydev->speed = SPEED_100; -- phydev->duplex = DUPLEX_FULL; -- -- return 0; --} -- --static int rtl9000a_config_aneg(struct phy_device *phydev) --{ -- int ret; -- u16 ctl = 0; -- -- switch (phydev->master_slave_set) { -- case MASTER_SLAVE_CFG_MASTER_FORCE: -- ctl |= CTL1000_AS_MASTER; -- break; -- case MASTER_SLAVE_CFG_SLAVE_FORCE: -- break; -- case MASTER_SLAVE_CFG_UNKNOWN: -- case MASTER_SLAVE_CFG_UNSUPPORTED: -- return 0; -- default: -- phydev_warn(phydev, "Unsupported Master/Slave mode\n"); -- return -EOPNOTSUPP; -- } -- -- ret = phy_modify_changed(phydev, MII_CTRL1000, CTL1000_AS_MASTER, ctl); -- if (ret == 1) -- ret = genphy_soft_reset(phydev); -- -- return ret; --} -- --static int rtl9000a_read_status(struct phy_device *phydev) --{ -- int ret; -- -- phydev->master_slave_get = MASTER_SLAVE_CFG_UNKNOWN; -- phydev->master_slave_state = MASTER_SLAVE_STATE_UNKNOWN; -- -- ret = genphy_update_link(phydev); -- if (ret) -- return ret; -- -- ret = phy_read(phydev, MII_CTRL1000); -- if (ret < 0) -- return ret; -- if (ret & CTL1000_AS_MASTER) -- phydev->master_slave_get = MASTER_SLAVE_CFG_MASTER_FORCE; -- else -- phydev->master_slave_get = MASTER_SLAVE_CFG_SLAVE_FORCE; -- -- ret = phy_read(phydev, MII_STAT1000); -- if (ret < 0) -- return ret; -- if (ret & LPA_1000MSRES) -- phydev->master_slave_state = MASTER_SLAVE_STATE_MASTER; -- else -- phydev->master_slave_state = MASTER_SLAVE_STATE_SLAVE; -- -- return 0; --} -- --static int rtl9000a_ack_interrupt(struct phy_device *phydev) --{ -- int err; -- -- err = phy_read(phydev, RTL8211F_INSR); -- -- return (err < 0) ? err : 0; --} -- --static int rtl9000a_config_intr(struct phy_device *phydev) --{ -- u16 val; -- int err; -- -- if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { -- err = rtl9000a_ack_interrupt(phydev); -- if (err) -- return err; -- -- val = (u16)~RTL9000A_GINMR_LINK_STATUS; -- err = phy_write_paged(phydev, 0xa42, RTL9000A_GINMR, val); -- } else { -- val = ~0; -- err = phy_write_paged(phydev, 0xa42, RTL9000A_GINMR, val); -- if (err) -- return err; -- -- err = rtl9000a_ack_interrupt(phydev); -- } -- -- return phy_write_paged(phydev, 0xa42, RTL9000A_GINMR, val); --} -- --static irqreturn_t rtl9000a_handle_interrupt(struct phy_device *phydev) --{ -- int irq_status; -- -- irq_status = phy_read(phydev, RTL8211F_INSR); -- if (irq_status < 0) { -- phy_error(phydev); -- return IRQ_NONE; -- } -- -- if (!(irq_status & RTL8211F_INER_LINK_STATUS)) -- return IRQ_NONE; -- -- phy_trigger_machine(phydev); -- -- return IRQ_HANDLED; --} -- --static struct phy_driver realtek_drvs[] = { -- { -- PHY_ID_MATCH_EXACT(0x00008201), -- .name = "RTL8201CP Ethernet", -- .read_page = rtl821x_read_page, -- .write_page = rtl821x_write_page, -- }, { -- PHY_ID_MATCH_EXACT(0x001cc816), -- .name = "RTL8201F Fast Ethernet", -- .config_intr = &rtl8201_config_intr, -- .handle_interrupt = rtl8201_handle_interrupt, -- .suspend = genphy_suspend, -- .resume = genphy_resume, -- .read_page = rtl821x_read_page, -- .write_page = rtl821x_write_page, -- }, { -- PHY_ID_MATCH_MODEL(0x001cc880), -- .name = "RTL8208 Fast Ethernet", -- .read_mmd = genphy_read_mmd_unsupported, -- .write_mmd = genphy_write_mmd_unsupported, -- .suspend = genphy_suspend, -- .resume = genphy_resume, -- .read_page = rtl821x_read_page, -- .write_page = rtl821x_write_page, -- }, { -- PHY_ID_MATCH_EXACT(0x001cc910), -- .name = "RTL8211 Gigabit Ethernet", -- .config_aneg = rtl8211_config_aneg, -- .read_mmd = &genphy_read_mmd_unsupported, -- .write_mmd = &genphy_write_mmd_unsupported, -- .read_page = rtl821x_read_page, -- .write_page = rtl821x_write_page, -- }, { -- PHY_ID_MATCH_EXACT(0x001cc912), -- .name = "RTL8211B Gigabit Ethernet", -- .config_intr = &rtl8211b_config_intr, -- .handle_interrupt = rtl821x_handle_interrupt, -- .read_mmd = &genphy_read_mmd_unsupported, -- .write_mmd = &genphy_write_mmd_unsupported, -- .suspend = rtl8211b_suspend, -- .resume = rtl8211b_resume, -- .read_page = rtl821x_read_page, -- .write_page = rtl821x_write_page, -- }, { -- PHY_ID_MATCH_EXACT(0x001cc913), -- .name = "RTL8211C Gigabit Ethernet", -- .config_init = rtl8211c_config_init, -- .read_mmd = &genphy_read_mmd_unsupported, -- .write_mmd = &genphy_write_mmd_unsupported, -- .read_page = rtl821x_read_page, -- .write_page = rtl821x_write_page, -- }, { -- PHY_ID_MATCH_EXACT(0x001cc914), -- .name = "RTL8211DN Gigabit Ethernet", -- .config_intr = rtl8211e_config_intr, -- .handle_interrupt = rtl821x_handle_interrupt, -- .suspend = genphy_suspend, -- .resume = genphy_resume, -- .read_page = rtl821x_read_page, -- .write_page = rtl821x_write_page, -- }, { -- PHY_ID_MATCH_EXACT(0x001cc915), -- .name = "RTL8211E Gigabit Ethernet", -- .config_init = &rtl8211e_config_init, -- .config_intr = &rtl8211e_config_intr, -- .handle_interrupt = rtl821x_handle_interrupt, -- .suspend = genphy_suspend, -- .resume = genphy_resume, -- .read_page = rtl821x_read_page, -- .write_page = rtl821x_write_page, -- }, { -- PHY_ID_MATCH_EXACT(0x001cc916), -- .name = "RTL8211F Gigabit Ethernet", -- .probe = rtl821x_probe, -- .config_init = &rtl8211f_config_init, -- .read_status = rtlgen_read_status, -- .config_intr = &rtl8211f_config_intr, -- .handle_interrupt = rtl8211f_handle_interrupt, -- .suspend = rtl821x_suspend, -- .resume = rtl821x_resume, -- .read_page = rtl821x_read_page, -- .write_page = rtl821x_write_page, -- .flags = PHY_ALWAYS_CALL_SUSPEND, -- .led_hw_is_supported = rtl8211f_led_hw_is_supported, -- .led_hw_control_get = rtl8211f_led_hw_control_get, -- .led_hw_control_set = rtl8211f_led_hw_control_set, -- }, { -- PHY_ID_MATCH_EXACT(RTL_8211FVD_PHYID), -- .name = "RTL8211F-VD Gigabit Ethernet", -- .probe = rtl821x_probe, -- .config_init = &rtl8211f_config_init, -- .read_status = rtlgen_read_status, -- .config_intr = &rtl8211f_config_intr, -- .handle_interrupt = rtl8211f_handle_interrupt, -- .suspend = rtl821x_suspend, -- .resume = rtl821x_resume, -- .read_page = rtl821x_read_page, -- .write_page = rtl821x_write_page, -- .flags = PHY_ALWAYS_CALL_SUSPEND, -- }, { -- .name = "Generic FE-GE Realtek PHY", -- .match_phy_device = rtlgen_match_phy_device, -- .read_status = rtlgen_read_status, -- .suspend = genphy_suspend, -- .resume = rtlgen_resume, -- .read_page = rtl821x_read_page, -- .write_page = rtl821x_write_page, -- .read_mmd = rtlgen_read_mmd, -- .write_mmd = rtlgen_write_mmd, -- }, { -- .name = "RTL8226 2.5Gbps PHY", -- .match_phy_device = rtl8226_match_phy_device, -- .get_features = rtl822x_get_features, -- .config_aneg = rtl822x_config_aneg, -- .read_status = rtl822x_read_status, -- .suspend = genphy_suspend, -- .resume = rtlgen_resume, -- .read_page = rtl821x_read_page, -- .write_page = rtl821x_write_page, -- }, { -- .match_phy_device = rtl8221b_match_phy_device, -- .name = "RTL8226B_RTL8221B 2.5Gbps PHY", -- .get_features = rtl822x_get_features, -- .config_aneg = rtl822x_config_aneg, -- .config_init = rtl822xb_config_init, -- .get_rate_matching = rtl822xb_get_rate_matching, -- .read_status = rtl822xb_read_status, -- .suspend = genphy_suspend, -- .resume = rtlgen_resume, -- .read_page = rtl821x_read_page, -- .write_page = rtl821x_write_page, -- }, { -- PHY_ID_MATCH_EXACT(0x001cc838), -- .name = "RTL8226-CG 2.5Gbps PHY", -- .get_features = rtl822x_get_features, -- .config_aneg = rtl822x_config_aneg, -- .read_status = rtl822x_read_status, -- .suspend = genphy_suspend, -- .resume = rtlgen_resume, -- .read_page = rtl821x_read_page, -- .write_page = rtl821x_write_page, -- }, { -- PHY_ID_MATCH_EXACT(0x001cc848), -- .name = "RTL8226B-CG_RTL8221B-CG 2.5Gbps PHY", -- .get_features = rtl822x_get_features, -- .config_aneg = rtl822x_config_aneg, -- .config_init = rtl822xb_config_init, -- .get_rate_matching = rtl822xb_get_rate_matching, -- .read_status = rtl822xb_read_status, -- .suspend = genphy_suspend, -- .resume = rtlgen_resume, -- .read_page = rtl821x_read_page, -- .write_page = rtl821x_write_page, -- }, { -- .match_phy_device = rtl8221b_vb_cg_c22_match_phy_device, -- .name = "RTL8221B-VB-CG 2.5Gbps PHY (C22)", -- .get_features = rtl822x_get_features, -- .config_aneg = rtl822x_config_aneg, -- .config_init = rtl822xb_config_init, -- .get_rate_matching = rtl822xb_get_rate_matching, -- .read_status = rtl822xb_read_status, -- .suspend = genphy_suspend, -- .resume = rtlgen_resume, -- .read_page = rtl821x_read_page, -- .write_page = rtl821x_write_page, -- }, { -- .match_phy_device = rtl8221b_vb_cg_c45_match_phy_device, -- .name = "RTL8221B-VB-CG 2.5Gbps PHY (C45)", -- .config_init = rtl822xb_config_init, -- .get_rate_matching = rtl822xb_get_rate_matching, -- .get_features = rtl822x_c45_get_features, -- .config_aneg = rtl822x_c45_config_aneg, -- .read_status = rtl822xb_c45_read_status, -- .suspend = genphy_c45_pma_suspend, -- .resume = rtlgen_c45_resume, -- }, { -- .match_phy_device = rtl8221b_vn_cg_c22_match_phy_device, -- .name = "RTL8221B-VM-CG 2.5Gbps PHY (C22)", -- .get_features = rtl822x_get_features, -- .config_aneg = rtl822x_config_aneg, -- .config_init = rtl822xb_config_init, -- .get_rate_matching = rtl822xb_get_rate_matching, -- .read_status = rtl822xb_read_status, -- .suspend = genphy_suspend, -- .resume = rtlgen_resume, -- .read_page = rtl821x_read_page, -- .write_page = rtl821x_write_page, -- }, { -- .match_phy_device = rtl8221b_vn_cg_c45_match_phy_device, -- .name = "RTL8221B-VN-CG 2.5Gbps PHY (C45)", -- .config_init = rtl822xb_config_init, -- .get_rate_matching = rtl822xb_get_rate_matching, -- .get_features = rtl822x_c45_get_features, -- .config_aneg = rtl822x_c45_config_aneg, -- .read_status = rtl822xb_c45_read_status, -- .suspend = genphy_c45_pma_suspend, -- .resume = rtlgen_c45_resume, -- }, { -- .match_phy_device = rtl8251b_c45_match_phy_device, -- .name = "RTL8251B 5Gbps PHY", -- .get_features = rtl822x_get_features, -- .config_aneg = rtl822x_config_aneg, -- .read_status = rtl822x_read_status, -- .suspend = genphy_suspend, -- .resume = rtlgen_resume, -- .read_page = rtl821x_read_page, -- .write_page = rtl821x_write_page, -- }, { -- .match_phy_device = rtl_internal_nbaset_match_phy_device, -- .name = "Realtek Internal NBASE-T PHY", -- .flags = PHY_IS_INTERNAL, -- .get_features = rtl822x_get_features, -- .config_aneg = rtl822x_config_aneg, -- .read_status = rtl822x_read_status, -- .suspend = genphy_suspend, -- .resume = rtlgen_resume, -- .read_page = rtl821x_read_page, -- .write_page = rtl821x_write_page, -- .read_mmd = rtl822x_read_mmd, -- .write_mmd = rtl822x_write_mmd, -- }, { -- PHY_ID_MATCH_EXACT(0x001ccad0), -- .name = "RTL8224 2.5Gbps PHY", -- .get_features = rtl822x_c45_get_features, -- .config_aneg = rtl822x_c45_config_aneg, -- .read_status = rtl822x_c45_read_status, -- .suspend = genphy_c45_pma_suspend, -- .resume = rtlgen_c45_resume, -- }, { -- PHY_ID_MATCH_EXACT(0x001cc961), -- .name = "RTL8366RB Gigabit Ethernet", -- .config_init = &rtl8366rb_config_init, -- /* These interrupts are handled by the irq controller -- * embedded inside the RTL8366RB, they get unmasked when the -- * irq is requested and ACKed by reading the status register, -- * which is done by the irqchip code. -- */ -- .config_intr = genphy_no_config_intr, -- .handle_interrupt = genphy_handle_interrupt_no_ack, -- .suspend = genphy_suspend, -- .resume = genphy_resume, -- }, { -- PHY_ID_MATCH_EXACT(0x001ccb00), -- .name = "RTL9000AA_RTL9000AN Ethernet", -- .features = PHY_BASIC_T1_FEATURES, -- .config_init = rtl9000a_config_init, -- .config_aneg = rtl9000a_config_aneg, -- .read_status = rtl9000a_read_status, -- .config_intr = rtl9000a_config_intr, -- .handle_interrupt = rtl9000a_handle_interrupt, -- .suspend = genphy_suspend, -- .resume = genphy_resume, -- .read_page = rtl821x_read_page, -- .write_page = rtl821x_write_page, -- }, { -- PHY_ID_MATCH_EXACT(0x001cc942), -- .name = "RTL8365MB-VC Gigabit Ethernet", -- /* Interrupt handling analogous to RTL8366RB */ -- .config_intr = genphy_no_config_intr, -- .handle_interrupt = genphy_handle_interrupt_no_ack, -- .suspend = genphy_suspend, -- .resume = genphy_resume, -- }, { -- PHY_ID_MATCH_EXACT(0x001cc960), -- .name = "RTL8366S Gigabit Ethernet", -- .suspend = genphy_suspend, -- .resume = genphy_resume, -- .read_mmd = genphy_read_mmd_unsupported, -- .write_mmd = genphy_write_mmd_unsupported, -- }, --}; -- --module_phy_driver(realtek_drvs); -- --static const struct mdio_device_id __maybe_unused realtek_tbl[] = { -- { PHY_ID_MATCH_VENDOR(0x001cc800) }, -- { } --}; -- --MODULE_DEVICE_TABLE(mdio, realtek_tbl); ---- /dev/null -+++ b/drivers/net/phy/realtek/realtek_main.c -@@ -0,0 +1,1589 @@ -+// SPDX-License-Identifier: GPL-2.0+ -+/* drivers/net/phy/realtek.c -+ * -+ * Driver for Realtek PHYs -+ * -+ * Author: Johnson Leung -+ * -+ * Copyright (c) 2004 Freescale Semiconductor, Inc. -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define RTL821x_PHYSR 0x11 -+#define RTL821x_PHYSR_DUPLEX BIT(13) -+#define RTL821x_PHYSR_SPEED GENMASK(15, 14) -+ -+#define RTL821x_INER 0x12 -+#define RTL8211B_INER_INIT 0x6400 -+#define RTL8211E_INER_LINK_STATUS BIT(10) -+#define RTL8211F_INER_LINK_STATUS BIT(4) -+ -+#define RTL821x_INSR 0x13 -+ -+#define RTL821x_EXT_PAGE_SELECT 0x1e -+#define RTL821x_PAGE_SELECT 0x1f -+ -+#define RTL8211F_PHYCR1 0x18 -+#define RTL8211F_PHYCR2 0x19 -+#define RTL8211F_INSR 0x1d -+ -+#define RTL8211F_LEDCR 0x10 -+#define RTL8211F_LEDCR_MODE BIT(15) -+#define RTL8211F_LEDCR_ACT_TXRX BIT(4) -+#define RTL8211F_LEDCR_LINK_1000 BIT(3) -+#define RTL8211F_LEDCR_LINK_100 BIT(1) -+#define RTL8211F_LEDCR_LINK_10 BIT(0) -+#define RTL8211F_LEDCR_MASK GENMASK(4, 0) -+#define RTL8211F_LEDCR_SHIFT 5 -+ -+#define RTL8211F_TX_DELAY BIT(8) -+#define RTL8211F_RX_DELAY BIT(3) -+ -+#define RTL8211F_ALDPS_PLL_OFF BIT(1) -+#define RTL8211F_ALDPS_ENABLE BIT(2) -+#define RTL8211F_ALDPS_XTAL_OFF BIT(12) -+ -+#define RTL8211E_CTRL_DELAY BIT(13) -+#define RTL8211E_TX_DELAY BIT(12) -+#define RTL8211E_RX_DELAY BIT(11) -+ -+#define RTL8211F_CLKOUT_EN BIT(0) -+ -+#define RTL8201F_ISR 0x1e -+#define RTL8201F_ISR_ANERR BIT(15) -+#define RTL8201F_ISR_DUPLEX BIT(13) -+#define RTL8201F_ISR_LINK BIT(11) -+#define RTL8201F_ISR_MASK (RTL8201F_ISR_ANERR | \ -+ RTL8201F_ISR_DUPLEX | \ -+ RTL8201F_ISR_LINK) -+#define RTL8201F_IER 0x13 -+ -+#define RTL822X_VND1_SERDES_OPTION 0x697a -+#define RTL822X_VND1_SERDES_OPTION_MODE_MASK GENMASK(5, 0) -+#define RTL822X_VND1_SERDES_OPTION_MODE_2500BASEX_SGMII 0 -+#define RTL822X_VND1_SERDES_OPTION_MODE_2500BASEX 2 -+ -+#define RTL822X_VND1_SERDES_CTRL3 0x7580 -+#define RTL822X_VND1_SERDES_CTRL3_MODE_MASK GENMASK(5, 0) -+#define RTL822X_VND1_SERDES_CTRL3_MODE_SGMII 0x02 -+#define RTL822X_VND1_SERDES_CTRL3_MODE_2500BASEX 0x16 -+ -+/* RTL822X_VND2_XXXXX registers are only accessible when phydev->is_c45 -+ * is set, they cannot be accessed by C45-over-C22. -+ */ -+#define RTL822X_VND2_GBCR 0xa412 -+ -+#define RTL822X_VND2_GANLPAR 0xa414 -+ -+#define RTL8366RB_POWER_SAVE 0x15 -+#define RTL8366RB_POWER_SAVE_ON BIT(12) -+ -+#define RTL9000A_GINMR 0x14 -+#define RTL9000A_GINMR_LINK_STATUS BIT(4) -+ -+#define RTL_VND2_PHYSR 0xa434 -+#define RTL_VND2_PHYSR_DUPLEX BIT(3) -+#define RTL_VND2_PHYSR_SPEEDL GENMASK(5, 4) -+#define RTL_VND2_PHYSR_SPEEDH GENMASK(10, 9) -+#define RTL_VND2_PHYSR_MASTER BIT(11) -+#define RTL_VND2_PHYSR_SPEED_MASK (RTL_VND2_PHYSR_SPEEDL | RTL_VND2_PHYSR_SPEEDH) -+ -+#define RTL_GENERIC_PHYID 0x001cc800 -+#define RTL_8211FVD_PHYID 0x001cc878 -+#define RTL_8221B 0x001cc840 -+#define RTL_8221B_VB_CG 0x001cc849 -+#define RTL_8221B_VN_CG 0x001cc84a -+#define RTL_8251B 0x001cc862 -+ -+#define RTL8211F_LED_COUNT 3 -+ -+MODULE_DESCRIPTION("Realtek PHY driver"); -+MODULE_AUTHOR("Johnson Leung"); -+MODULE_LICENSE("GPL"); -+ -+struct rtl821x_priv { -+ u16 phycr1; -+ u16 phycr2; -+ bool has_phycr2; -+ struct clk *clk; -+}; -+ -+static int rtl821x_read_page(struct phy_device *phydev) -+{ -+ return __phy_read(phydev, RTL821x_PAGE_SELECT); -+} -+ -+static int rtl821x_write_page(struct phy_device *phydev, int page) -+{ -+ return __phy_write(phydev, RTL821x_PAGE_SELECT, page); -+} -+ -+static int rtl821x_probe(struct phy_device *phydev) -+{ -+ struct device *dev = &phydev->mdio.dev; -+ struct rtl821x_priv *priv; -+ u32 phy_id = phydev->drv->phy_id; -+ int ret; -+ -+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); -+ if (!priv) -+ return -ENOMEM; -+ -+ priv->clk = devm_clk_get_optional_enabled(dev, NULL); -+ if (IS_ERR(priv->clk)) -+ return dev_err_probe(dev, PTR_ERR(priv->clk), -+ "failed to get phy clock\n"); -+ -+ ret = phy_read_paged(phydev, 0xa43, RTL8211F_PHYCR1); -+ if (ret < 0) -+ return ret; -+ -+ priv->phycr1 = ret & (RTL8211F_ALDPS_PLL_OFF | RTL8211F_ALDPS_ENABLE | RTL8211F_ALDPS_XTAL_OFF); -+ if (of_property_read_bool(dev->of_node, "realtek,aldps-enable")) -+ priv->phycr1 |= RTL8211F_ALDPS_PLL_OFF | RTL8211F_ALDPS_ENABLE | RTL8211F_ALDPS_XTAL_OFF; -+ -+ priv->has_phycr2 = !(phy_id == RTL_8211FVD_PHYID); -+ if (priv->has_phycr2) { -+ ret = phy_read_paged(phydev, 0xa43, RTL8211F_PHYCR2); -+ if (ret < 0) -+ return ret; -+ -+ priv->phycr2 = ret & RTL8211F_CLKOUT_EN; -+ if (of_property_read_bool(dev->of_node, "realtek,clkout-disable")) -+ priv->phycr2 &= ~RTL8211F_CLKOUT_EN; -+ } -+ -+ phydev->priv = priv; -+ -+ return 0; -+} -+ -+static int rtl8201_ack_interrupt(struct phy_device *phydev) -+{ -+ int err; -+ -+ err = phy_read(phydev, RTL8201F_ISR); -+ -+ return (err < 0) ? err : 0; -+} -+ -+static int rtl821x_ack_interrupt(struct phy_device *phydev) -+{ -+ int err; -+ -+ err = phy_read(phydev, RTL821x_INSR); -+ -+ return (err < 0) ? err : 0; -+} -+ -+static int rtl8211f_ack_interrupt(struct phy_device *phydev) -+{ -+ int err; -+ -+ err = phy_read_paged(phydev, 0xa43, RTL8211F_INSR); -+ -+ return (err < 0) ? err : 0; -+} -+ -+static int rtl8201_config_intr(struct phy_device *phydev) -+{ -+ u16 val; -+ int err; -+ -+ if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { -+ err = rtl8201_ack_interrupt(phydev); -+ if (err) -+ return err; -+ -+ val = BIT(13) | BIT(12) | BIT(11); -+ err = phy_write_paged(phydev, 0x7, RTL8201F_IER, val); -+ } else { -+ val = 0; -+ err = phy_write_paged(phydev, 0x7, RTL8201F_IER, val); -+ if (err) -+ return err; -+ -+ err = rtl8201_ack_interrupt(phydev); -+ } -+ -+ return err; -+} -+ -+static int rtl8211b_config_intr(struct phy_device *phydev) -+{ -+ int err; -+ -+ if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { -+ err = rtl821x_ack_interrupt(phydev); -+ if (err) -+ return err; -+ -+ err = phy_write(phydev, RTL821x_INER, -+ RTL8211B_INER_INIT); -+ } else { -+ err = phy_write(phydev, RTL821x_INER, 0); -+ if (err) -+ return err; -+ -+ err = rtl821x_ack_interrupt(phydev); -+ } -+ -+ return err; -+} -+ -+static int rtl8211e_config_intr(struct phy_device *phydev) -+{ -+ int err; -+ -+ if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { -+ err = rtl821x_ack_interrupt(phydev); -+ if (err) -+ return err; -+ -+ err = phy_write(phydev, RTL821x_INER, -+ RTL8211E_INER_LINK_STATUS); -+ } else { -+ err = phy_write(phydev, RTL821x_INER, 0); -+ if (err) -+ return err; -+ -+ err = rtl821x_ack_interrupt(phydev); -+ } -+ -+ return err; -+} -+ -+static int rtl8211f_config_intr(struct phy_device *phydev) -+{ -+ u16 val; -+ int err; -+ -+ if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { -+ err = rtl8211f_ack_interrupt(phydev); -+ if (err) -+ return err; -+ -+ val = RTL8211F_INER_LINK_STATUS; -+ err = phy_write_paged(phydev, 0xa42, RTL821x_INER, val); -+ } else { -+ val = 0; -+ err = phy_write_paged(phydev, 0xa42, RTL821x_INER, val); -+ if (err) -+ return err; -+ -+ err = rtl8211f_ack_interrupt(phydev); -+ } -+ -+ return err; -+} -+ -+static irqreturn_t rtl8201_handle_interrupt(struct phy_device *phydev) -+{ -+ int irq_status; -+ -+ irq_status = phy_read(phydev, RTL8201F_ISR); -+ if (irq_status < 0) { -+ phy_error(phydev); -+ return IRQ_NONE; -+ } -+ -+ if (!(irq_status & RTL8201F_ISR_MASK)) -+ return IRQ_NONE; -+ -+ phy_trigger_machine(phydev); -+ -+ return IRQ_HANDLED; -+} -+ -+static irqreturn_t rtl821x_handle_interrupt(struct phy_device *phydev) -+{ -+ int irq_status, irq_enabled; -+ -+ irq_status = phy_read(phydev, RTL821x_INSR); -+ if (irq_status < 0) { -+ phy_error(phydev); -+ return IRQ_NONE; -+ } -+ -+ irq_enabled = phy_read(phydev, RTL821x_INER); -+ if (irq_enabled < 0) { -+ phy_error(phydev); -+ return IRQ_NONE; -+ } -+ -+ if (!(irq_status & irq_enabled)) -+ return IRQ_NONE; -+ -+ phy_trigger_machine(phydev); -+ -+ return IRQ_HANDLED; -+} -+ -+static irqreturn_t rtl8211f_handle_interrupt(struct phy_device *phydev) -+{ -+ int irq_status; -+ -+ irq_status = phy_read_paged(phydev, 0xa43, RTL8211F_INSR); -+ if (irq_status < 0) { -+ phy_error(phydev); -+ return IRQ_NONE; -+ } -+ -+ if (!(irq_status & RTL8211F_INER_LINK_STATUS)) -+ return IRQ_NONE; -+ -+ phy_trigger_machine(phydev); -+ -+ return IRQ_HANDLED; -+} -+ -+static int rtl8211_config_aneg(struct phy_device *phydev) -+{ -+ int ret; -+ -+ ret = genphy_config_aneg(phydev); -+ if (ret < 0) -+ return ret; -+ -+ /* Quirk was copied from vendor driver. Unfortunately it includes no -+ * description of the magic numbers. -+ */ -+ if (phydev->speed == SPEED_100 && phydev->autoneg == AUTONEG_DISABLE) { -+ phy_write(phydev, 0x17, 0x2138); -+ phy_write(phydev, 0x0e, 0x0260); -+ } else { -+ phy_write(phydev, 0x17, 0x2108); -+ phy_write(phydev, 0x0e, 0x0000); -+ } -+ -+ return 0; -+} -+ -+static int rtl8211c_config_init(struct phy_device *phydev) -+{ -+ /* RTL8211C has an issue when operating in Gigabit slave mode */ -+ return phy_set_bits(phydev, MII_CTRL1000, -+ CTL1000_ENABLE_MASTER | CTL1000_AS_MASTER); -+} -+ -+static int rtl8211f_config_init(struct phy_device *phydev) -+{ -+ struct rtl821x_priv *priv = phydev->priv; -+ struct device *dev = &phydev->mdio.dev; -+ u16 val_txdly, val_rxdly; -+ int ret; -+ -+ ret = phy_modify_paged_changed(phydev, 0xa43, RTL8211F_PHYCR1, -+ RTL8211F_ALDPS_PLL_OFF | RTL8211F_ALDPS_ENABLE | RTL8211F_ALDPS_XTAL_OFF, -+ priv->phycr1); -+ if (ret < 0) { -+ dev_err(dev, "aldps mode configuration failed: %pe\n", -+ ERR_PTR(ret)); -+ return ret; -+ } -+ -+ switch (phydev->interface) { -+ case PHY_INTERFACE_MODE_RGMII: -+ val_txdly = 0; -+ val_rxdly = 0; -+ break; -+ -+ case PHY_INTERFACE_MODE_RGMII_RXID: -+ val_txdly = 0; -+ val_rxdly = RTL8211F_RX_DELAY; -+ break; -+ -+ case PHY_INTERFACE_MODE_RGMII_TXID: -+ val_txdly = RTL8211F_TX_DELAY; -+ val_rxdly = 0; -+ break; -+ -+ case PHY_INTERFACE_MODE_RGMII_ID: -+ val_txdly = RTL8211F_TX_DELAY; -+ val_rxdly = RTL8211F_RX_DELAY; -+ break; -+ -+ default: /* the rest of the modes imply leaving delay as is. */ -+ return 0; -+ } -+ -+ ret = phy_modify_paged_changed(phydev, 0xd08, 0x11, RTL8211F_TX_DELAY, -+ val_txdly); -+ if (ret < 0) { -+ dev_err(dev, "Failed to update the TX delay register\n"); -+ return ret; -+ } else if (ret) { -+ dev_dbg(dev, -+ "%s 2ns TX delay (and changing the value from pin-strapping RXD1 or the bootloader)\n", -+ val_txdly ? "Enabling" : "Disabling"); -+ } else { -+ dev_dbg(dev, -+ "2ns TX delay was already %s (by pin-strapping RXD1 or bootloader configuration)\n", -+ val_txdly ? "enabled" : "disabled"); -+ } -+ -+ ret = phy_modify_paged_changed(phydev, 0xd08, 0x15, RTL8211F_RX_DELAY, -+ val_rxdly); -+ if (ret < 0) { -+ dev_err(dev, "Failed to update the RX delay register\n"); -+ return ret; -+ } else if (ret) { -+ dev_dbg(dev, -+ "%s 2ns RX delay (and changing the value from pin-strapping RXD0 or the bootloader)\n", -+ val_rxdly ? "Enabling" : "Disabling"); -+ } else { -+ dev_dbg(dev, -+ "2ns RX delay was already %s (by pin-strapping RXD0 or bootloader configuration)\n", -+ val_rxdly ? "enabled" : "disabled"); -+ } -+ -+ if (priv->has_phycr2) { -+ ret = phy_modify_paged(phydev, 0xa43, RTL8211F_PHYCR2, -+ RTL8211F_CLKOUT_EN, priv->phycr2); -+ if (ret < 0) { -+ dev_err(dev, "clkout configuration failed: %pe\n", -+ ERR_PTR(ret)); -+ return ret; -+ } -+ -+ return genphy_soft_reset(phydev); -+ } -+ -+ return 0; -+} -+ -+static int rtl821x_suspend(struct phy_device *phydev) -+{ -+ struct rtl821x_priv *priv = phydev->priv; -+ int ret = 0; -+ -+ if (!phydev->wol_enabled) { -+ ret = genphy_suspend(phydev); -+ -+ if (ret) -+ return ret; -+ -+ clk_disable_unprepare(priv->clk); -+ } -+ -+ return ret; -+} -+ -+static int rtl821x_resume(struct phy_device *phydev) -+{ -+ struct rtl821x_priv *priv = phydev->priv; -+ int ret; -+ -+ if (!phydev->wol_enabled) -+ clk_prepare_enable(priv->clk); -+ -+ ret = genphy_resume(phydev); -+ if (ret < 0) -+ return ret; -+ -+ msleep(20); -+ -+ return 0; -+} -+ -+static int rtl8211f_led_hw_is_supported(struct phy_device *phydev, u8 index, -+ unsigned long rules) -+{ -+ const unsigned long mask = BIT(TRIGGER_NETDEV_LINK_10) | -+ BIT(TRIGGER_NETDEV_LINK_100) | -+ BIT(TRIGGER_NETDEV_LINK_1000) | -+ BIT(TRIGGER_NETDEV_RX) | -+ BIT(TRIGGER_NETDEV_TX); -+ -+ /* The RTL8211F PHY supports these LED settings on up to three LEDs: -+ * - Link: Configurable subset of 10/100/1000 link rates -+ * - Active: Blink on activity, RX or TX is not differentiated -+ * The Active option has two modes, A and B: -+ * - A: Link and Active indication at configurable, but matching, -+ * subset of 10/100/1000 link rates -+ * - B: Link indication at configurable subset of 10/100/1000 link -+ * rates and Active indication always at all three 10+100+1000 -+ * link rates. -+ * This code currently uses mode B only. -+ */ -+ -+ if (index >= RTL8211F_LED_COUNT) -+ return -EINVAL; -+ -+ /* Filter out any other unsupported triggers. */ -+ if (rules & ~mask) -+ return -EOPNOTSUPP; -+ -+ /* RX and TX are not differentiated, either both are set or not set. */ -+ if (!(rules & BIT(TRIGGER_NETDEV_RX)) ^ !(rules & BIT(TRIGGER_NETDEV_TX))) -+ return -EOPNOTSUPP; -+ -+ return 0; -+} -+ -+static int rtl8211f_led_hw_control_get(struct phy_device *phydev, u8 index, -+ unsigned long *rules) -+{ -+ int val; -+ -+ if (index >= RTL8211F_LED_COUNT) -+ return -EINVAL; -+ -+ val = phy_read_paged(phydev, 0xd04, RTL8211F_LEDCR); -+ if (val < 0) -+ return val; -+ -+ val >>= RTL8211F_LEDCR_SHIFT * index; -+ val &= RTL8211F_LEDCR_MASK; -+ -+ if (val & RTL8211F_LEDCR_LINK_10) -+ set_bit(TRIGGER_NETDEV_LINK_10, rules); -+ -+ if (val & RTL8211F_LEDCR_LINK_100) -+ set_bit(TRIGGER_NETDEV_LINK_100, rules); -+ -+ if (val & RTL8211F_LEDCR_LINK_1000) -+ set_bit(TRIGGER_NETDEV_LINK_1000, rules); -+ -+ if (val & RTL8211F_LEDCR_ACT_TXRX) { -+ set_bit(TRIGGER_NETDEV_RX, rules); -+ set_bit(TRIGGER_NETDEV_TX, rules); -+ } -+ -+ return 0; -+} -+ -+static int rtl8211f_led_hw_control_set(struct phy_device *phydev, u8 index, -+ unsigned long rules) -+{ -+ const u16 mask = RTL8211F_LEDCR_MASK << (RTL8211F_LEDCR_SHIFT * index); -+ u16 reg = 0; -+ -+ if (index >= RTL8211F_LED_COUNT) -+ return -EINVAL; -+ -+ if (test_bit(TRIGGER_NETDEV_LINK_10, &rules)) -+ reg |= RTL8211F_LEDCR_LINK_10; -+ -+ if (test_bit(TRIGGER_NETDEV_LINK_100, &rules)) -+ reg |= RTL8211F_LEDCR_LINK_100; -+ -+ if (test_bit(TRIGGER_NETDEV_LINK_1000, &rules)) -+ reg |= RTL8211F_LEDCR_LINK_1000; -+ -+ if (test_bit(TRIGGER_NETDEV_RX, &rules) || -+ test_bit(TRIGGER_NETDEV_TX, &rules)) { -+ reg |= RTL8211F_LEDCR_ACT_TXRX; -+ } -+ -+ reg <<= RTL8211F_LEDCR_SHIFT * index; -+ reg |= RTL8211F_LEDCR_MODE; /* Mode B */ -+ -+ return phy_modify_paged(phydev, 0xd04, RTL8211F_LEDCR, mask, reg); -+} -+ -+static int rtl8211e_config_init(struct phy_device *phydev) -+{ -+ int ret = 0, oldpage; -+ u16 val; -+ -+ /* enable TX/RX delay for rgmii-* modes, and disable them for rgmii. */ -+ switch (phydev->interface) { -+ case PHY_INTERFACE_MODE_RGMII: -+ val = RTL8211E_CTRL_DELAY | 0; -+ break; -+ case PHY_INTERFACE_MODE_RGMII_ID: -+ val = RTL8211E_CTRL_DELAY | RTL8211E_TX_DELAY | RTL8211E_RX_DELAY; -+ break; -+ case PHY_INTERFACE_MODE_RGMII_RXID: -+ val = RTL8211E_CTRL_DELAY | RTL8211E_RX_DELAY; -+ break; -+ case PHY_INTERFACE_MODE_RGMII_TXID: -+ val = RTL8211E_CTRL_DELAY | RTL8211E_TX_DELAY; -+ break; -+ default: /* the rest of the modes imply leaving delays as is. */ -+ return 0; -+ } -+ -+ /* According to a sample driver there is a 0x1c config register on the -+ * 0xa4 extension page (0x7) layout. It can be used to disable/enable -+ * the RX/TX delays otherwise controlled by RXDLY/TXDLY pins. -+ * The configuration register definition: -+ * 14 = reserved -+ * 13 = Force Tx RX Delay controlled by bit12 bit11, -+ * 12 = RX Delay, 11 = TX Delay -+ * 10:0 = Test && debug settings reserved by realtek -+ */ -+ oldpage = phy_select_page(phydev, 0x7); -+ if (oldpage < 0) -+ goto err_restore_page; -+ -+ ret = __phy_write(phydev, RTL821x_EXT_PAGE_SELECT, 0xa4); -+ if (ret) -+ goto err_restore_page; -+ -+ ret = __phy_modify(phydev, 0x1c, RTL8211E_CTRL_DELAY -+ | RTL8211E_TX_DELAY | RTL8211E_RX_DELAY, -+ val); -+ -+err_restore_page: -+ return phy_restore_page(phydev, oldpage, ret); -+} -+ -+static int rtl8211b_suspend(struct phy_device *phydev) -+{ -+ phy_write(phydev, MII_MMD_DATA, BIT(9)); -+ -+ return genphy_suspend(phydev); -+} -+ -+static int rtl8211b_resume(struct phy_device *phydev) -+{ -+ phy_write(phydev, MII_MMD_DATA, 0); -+ -+ return genphy_resume(phydev); -+} -+ -+static int rtl8366rb_config_init(struct phy_device *phydev) -+{ -+ int ret; -+ -+ ret = phy_set_bits(phydev, RTL8366RB_POWER_SAVE, -+ RTL8366RB_POWER_SAVE_ON); -+ if (ret) { -+ dev_err(&phydev->mdio.dev, -+ "error enabling power management\n"); -+ } -+ -+ return ret; -+} -+ -+/* get actual speed to cover the downshift case */ -+static void rtlgen_decode_physr(struct phy_device *phydev, int val) -+{ -+ /* bit 3 -+ * 0: Half Duplex -+ * 1: Full Duplex -+ */ -+ if (val & RTL_VND2_PHYSR_DUPLEX) -+ phydev->duplex = DUPLEX_FULL; -+ else -+ phydev->duplex = DUPLEX_HALF; -+ -+ switch (val & RTL_VND2_PHYSR_SPEED_MASK) { -+ case 0x0000: -+ phydev->speed = SPEED_10; -+ break; -+ case 0x0010: -+ phydev->speed = SPEED_100; -+ break; -+ case 0x0020: -+ phydev->speed = SPEED_1000; -+ break; -+ case 0x0200: -+ phydev->speed = SPEED_10000; -+ break; -+ case 0x0210: -+ phydev->speed = SPEED_2500; -+ break; -+ case 0x0220: -+ phydev->speed = SPEED_5000; -+ break; -+ default: -+ break; -+ } -+ -+ /* bit 11 -+ * 0: Slave Mode -+ * 1: Master Mode -+ */ -+ if (phydev->speed >= 1000) { -+ if (val & RTL_VND2_PHYSR_MASTER) -+ phydev->master_slave_state = MASTER_SLAVE_STATE_MASTER; -+ else -+ phydev->master_slave_state = MASTER_SLAVE_STATE_SLAVE; -+ } else { -+ phydev->master_slave_state = MASTER_SLAVE_STATE_UNSUPPORTED; -+ } -+} -+ -+static int rtlgen_read_status(struct phy_device *phydev) -+{ -+ int ret, val; -+ -+ ret = genphy_read_status(phydev); -+ if (ret < 0) -+ return ret; -+ -+ if (!phydev->link) -+ return 0; -+ -+ val = phy_read_paged(phydev, 0xa43, 0x12); -+ if (val < 0) -+ return val; -+ -+ rtlgen_decode_physr(phydev, val); -+ -+ return 0; -+} -+ -+static int rtlgen_read_mmd(struct phy_device *phydev, int devnum, u16 regnum) -+{ -+ int ret; -+ -+ if (devnum == MDIO_MMD_VEND2) { -+ rtl821x_write_page(phydev, regnum >> 4); -+ ret = __phy_read(phydev, 0x10 + ((regnum & 0xf) >> 1)); -+ rtl821x_write_page(phydev, 0); -+ } else if (devnum == MDIO_MMD_PCS && regnum == MDIO_PCS_EEE_ABLE) { -+ rtl821x_write_page(phydev, 0xa5c); -+ ret = __phy_read(phydev, 0x12); -+ rtl821x_write_page(phydev, 0); -+ } else if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_ADV) { -+ rtl821x_write_page(phydev, 0xa5d); -+ ret = __phy_read(phydev, 0x10); -+ rtl821x_write_page(phydev, 0); -+ } else if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_LPABLE) { -+ rtl821x_write_page(phydev, 0xa5d); -+ ret = __phy_read(phydev, 0x11); -+ rtl821x_write_page(phydev, 0); -+ } else { -+ ret = -EOPNOTSUPP; -+ } -+ -+ return ret; -+} -+ -+static int rtlgen_write_mmd(struct phy_device *phydev, int devnum, u16 regnum, -+ u16 val) -+{ -+ int ret; -+ -+ if (devnum == MDIO_MMD_VEND2) { -+ rtl821x_write_page(phydev, regnum >> 4); -+ ret = __phy_write(phydev, 0x10 + ((regnum & 0xf) >> 1), val); -+ rtl821x_write_page(phydev, 0); -+ } else if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_ADV) { -+ rtl821x_write_page(phydev, 0xa5d); -+ ret = __phy_write(phydev, 0x10, val); -+ rtl821x_write_page(phydev, 0); -+ } else { -+ ret = -EOPNOTSUPP; -+ } -+ -+ return ret; -+} -+ -+static int rtl822x_read_mmd(struct phy_device *phydev, int devnum, u16 regnum) -+{ -+ int ret = rtlgen_read_mmd(phydev, devnum, regnum); -+ -+ if (ret != -EOPNOTSUPP) -+ return ret; -+ -+ if (devnum == MDIO_MMD_PCS && regnum == MDIO_PCS_EEE_ABLE2) { -+ rtl821x_write_page(phydev, 0xa6e); -+ ret = __phy_read(phydev, 0x16); -+ rtl821x_write_page(phydev, 0); -+ } else if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_ADV2) { -+ rtl821x_write_page(phydev, 0xa6d); -+ ret = __phy_read(phydev, 0x12); -+ rtl821x_write_page(phydev, 0); -+ } else if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_LPABLE2) { -+ rtl821x_write_page(phydev, 0xa6d); -+ ret = __phy_read(phydev, 0x10); -+ rtl821x_write_page(phydev, 0); -+ } -+ -+ return ret; -+} -+ -+static int rtl822x_write_mmd(struct phy_device *phydev, int devnum, u16 regnum, -+ u16 val) -+{ -+ int ret = rtlgen_write_mmd(phydev, devnum, regnum, val); -+ -+ if (ret != -EOPNOTSUPP) -+ return ret; -+ -+ if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_ADV2) { -+ rtl821x_write_page(phydev, 0xa6d); -+ ret = __phy_write(phydev, 0x12, val); -+ rtl821x_write_page(phydev, 0); -+ } -+ -+ return ret; -+} -+ -+static int rtl822xb_config_init(struct phy_device *phydev) -+{ -+ bool has_2500, has_sgmii; -+ u16 mode; -+ int ret; -+ -+ has_2500 = test_bit(PHY_INTERFACE_MODE_2500BASEX, -+ phydev->host_interfaces) || -+ phydev->interface == PHY_INTERFACE_MODE_2500BASEX; -+ -+ has_sgmii = test_bit(PHY_INTERFACE_MODE_SGMII, -+ phydev->host_interfaces) || -+ phydev->interface == PHY_INTERFACE_MODE_SGMII; -+ -+ /* fill in possible interfaces */ -+ __assign_bit(PHY_INTERFACE_MODE_2500BASEX, phydev->possible_interfaces, -+ has_2500); -+ __assign_bit(PHY_INTERFACE_MODE_SGMII, phydev->possible_interfaces, -+ has_sgmii); -+ -+ if (!has_2500 && !has_sgmii) -+ return 0; -+ -+ /* determine SerDes option mode */ -+ if (has_2500 && !has_sgmii) { -+ mode = RTL822X_VND1_SERDES_OPTION_MODE_2500BASEX; -+ phydev->rate_matching = RATE_MATCH_PAUSE; -+ } else { -+ mode = RTL822X_VND1_SERDES_OPTION_MODE_2500BASEX_SGMII; -+ phydev->rate_matching = RATE_MATCH_NONE; -+ } -+ -+ /* the following sequence with magic numbers sets up the SerDes -+ * option mode -+ */ -+ ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x75f3, 0); -+ if (ret < 0) -+ return ret; -+ -+ ret = phy_modify_mmd_changed(phydev, MDIO_MMD_VEND1, -+ RTL822X_VND1_SERDES_OPTION, -+ RTL822X_VND1_SERDES_OPTION_MODE_MASK, -+ mode); -+ if (ret < 0) -+ return ret; -+ -+ ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x6a04, 0x0503); -+ if (ret < 0) -+ return ret; -+ -+ ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x6f10, 0xd455); -+ if (ret < 0) -+ return ret; -+ -+ return phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x6f11, 0x8020); -+} -+ -+static int rtl822xb_get_rate_matching(struct phy_device *phydev, -+ phy_interface_t iface) -+{ -+ int val; -+ -+ /* Only rate matching at 2500base-x */ -+ if (iface != PHY_INTERFACE_MODE_2500BASEX) -+ return RATE_MATCH_NONE; -+ -+ val = phy_read_mmd(phydev, MDIO_MMD_VEND1, RTL822X_VND1_SERDES_OPTION); -+ if (val < 0) -+ return val; -+ -+ if ((val & RTL822X_VND1_SERDES_OPTION_MODE_MASK) == -+ RTL822X_VND1_SERDES_OPTION_MODE_2500BASEX) -+ return RATE_MATCH_PAUSE; -+ -+ /* RTL822X_VND1_SERDES_OPTION_MODE_2500BASEX_SGMII */ -+ return RATE_MATCH_NONE; -+} -+ -+static int rtl822x_get_features(struct phy_device *phydev) -+{ -+ int val; -+ -+ val = phy_read_paged(phydev, 0xa61, 0x13); -+ if (val < 0) -+ return val; -+ -+ linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, -+ phydev->supported, val & MDIO_PMA_SPEED_2_5G); -+ linkmode_mod_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT, -+ phydev->supported, val & MDIO_PMA_SPEED_5G); -+ linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT, -+ phydev->supported, val & MDIO_SPEED_10G); -+ -+ return genphy_read_abilities(phydev); -+} -+ -+static int rtl822x_config_aneg(struct phy_device *phydev) -+{ -+ int ret = 0; -+ -+ if (phydev->autoneg == AUTONEG_ENABLE) { -+ u16 adv = linkmode_adv_to_mii_10gbt_adv_t(phydev->advertising); -+ -+ ret = phy_modify_paged_changed(phydev, 0xa5d, 0x12, -+ MDIO_AN_10GBT_CTRL_ADV2_5G | -+ MDIO_AN_10GBT_CTRL_ADV5G, -+ adv); -+ if (ret < 0) -+ return ret; -+ } -+ -+ return __genphy_config_aneg(phydev, ret); -+} -+ -+static void rtl822xb_update_interface(struct phy_device *phydev) -+{ -+ int val; -+ -+ if (!phydev->link) -+ return; -+ -+ /* Change interface according to serdes mode */ -+ val = phy_read_mmd(phydev, MDIO_MMD_VEND1, RTL822X_VND1_SERDES_CTRL3); -+ if (val < 0) -+ return; -+ -+ switch (val & RTL822X_VND1_SERDES_CTRL3_MODE_MASK) { -+ case RTL822X_VND1_SERDES_CTRL3_MODE_2500BASEX: -+ phydev->interface = PHY_INTERFACE_MODE_2500BASEX; -+ break; -+ case RTL822X_VND1_SERDES_CTRL3_MODE_SGMII: -+ phydev->interface = PHY_INTERFACE_MODE_SGMII; -+ break; -+ } -+} -+ -+static int rtl822x_read_status(struct phy_device *phydev) -+{ -+ int lpadv, ret; -+ -+ mii_10gbt_stat_mod_linkmode_lpa_t(phydev->lp_advertising, 0); -+ -+ ret = rtlgen_read_status(phydev); -+ if (ret < 0) -+ return ret; -+ -+ if (phydev->autoneg == AUTONEG_DISABLE || -+ !phydev->autoneg_complete) -+ return 0; -+ -+ lpadv = phy_read_paged(phydev, 0xa5d, 0x13); -+ if (lpadv < 0) -+ return lpadv; -+ -+ mii_10gbt_stat_mod_linkmode_lpa_t(phydev->lp_advertising, lpadv); -+ -+ return 0; -+} -+ -+static int rtl822xb_read_status(struct phy_device *phydev) -+{ -+ int ret; -+ -+ ret = rtl822x_read_status(phydev); -+ if (ret < 0) -+ return ret; -+ -+ rtl822xb_update_interface(phydev); -+ -+ return 0; -+} -+ -+static int rtl822x_c45_get_features(struct phy_device *phydev) -+{ -+ linkmode_set_bit(ETHTOOL_LINK_MODE_TP_BIT, -+ phydev->supported); -+ -+ return genphy_c45_pma_read_abilities(phydev); -+} -+ -+static int rtl822x_c45_config_aneg(struct phy_device *phydev) -+{ -+ bool changed = false; -+ int ret, val; -+ -+ if (phydev->autoneg == AUTONEG_DISABLE) -+ return genphy_c45_pma_setup_forced(phydev); -+ -+ ret = genphy_c45_an_config_aneg(phydev); -+ if (ret < 0) -+ return ret; -+ if (ret > 0) -+ changed = true; -+ -+ val = linkmode_adv_to_mii_ctrl1000_t(phydev->advertising); -+ -+ /* Vendor register as C45 has no standardized support for 1000BaseT */ -+ ret = phy_modify_mmd_changed(phydev, MDIO_MMD_VEND2, RTL822X_VND2_GBCR, -+ ADVERTISE_1000FULL, val); -+ if (ret < 0) -+ return ret; -+ if (ret > 0) -+ changed = true; -+ -+ return genphy_c45_check_and_restart_aneg(phydev, changed); -+} -+ -+static int rtl822x_c45_read_status(struct phy_device *phydev) -+{ -+ int ret, val; -+ -+ /* Vendor register as C45 has no standardized support for 1000BaseT */ -+ if (phydev->autoneg == AUTONEG_ENABLE && genphy_c45_aneg_done(phydev)) { -+ val = phy_read_mmd(phydev, MDIO_MMD_VEND2, -+ RTL822X_VND2_GANLPAR); -+ if (val < 0) -+ return val; -+ } else { -+ val = 0; -+ } -+ mii_stat1000_mod_linkmode_lpa_t(phydev->lp_advertising, val); -+ -+ ret = genphy_c45_read_status(phydev); -+ if (ret < 0) -+ return ret; -+ -+ if (!phydev->link) { -+ phydev->master_slave_state = MASTER_SLAVE_STATE_UNKNOWN; -+ return 0; -+ } -+ -+ /* Read actual speed from vendor register. */ -+ val = phy_read_mmd(phydev, MDIO_MMD_VEND2, RTL_VND2_PHYSR); -+ if (val < 0) -+ return val; -+ -+ rtlgen_decode_physr(phydev, val); -+ -+ return 0; -+} -+ -+static int rtl822xb_c45_read_status(struct phy_device *phydev) -+{ -+ int ret; -+ -+ ret = rtl822x_c45_read_status(phydev); -+ if (ret < 0) -+ return ret; -+ -+ rtl822xb_update_interface(phydev); -+ -+ return 0; -+} -+ -+static bool rtlgen_supports_2_5gbps(struct phy_device *phydev) -+{ -+ int val; -+ -+ phy_write(phydev, RTL821x_PAGE_SELECT, 0xa61); -+ val = phy_read(phydev, 0x13); -+ phy_write(phydev, RTL821x_PAGE_SELECT, 0); -+ -+ return val >= 0 && val & MDIO_PMA_SPEED_2_5G; -+} -+ -+/* On internal PHY's MMD reads over C22 always return 0. -+ * Check a MMD register which is known to be non-zero. -+ */ -+static bool rtlgen_supports_mmd(struct phy_device *phydev) -+{ -+ int val; -+ -+ phy_lock_mdio_bus(phydev); -+ __phy_write(phydev, MII_MMD_CTRL, MDIO_MMD_PCS); -+ __phy_write(phydev, MII_MMD_DATA, MDIO_PCS_EEE_ABLE); -+ __phy_write(phydev, MII_MMD_CTRL, MDIO_MMD_PCS | MII_MMD_CTRL_NOINCR); -+ val = __phy_read(phydev, MII_MMD_DATA); -+ phy_unlock_mdio_bus(phydev); -+ -+ return val > 0; -+} -+ -+static int rtlgen_match_phy_device(struct phy_device *phydev) -+{ -+ return phydev->phy_id == RTL_GENERIC_PHYID && -+ !rtlgen_supports_2_5gbps(phydev); -+} -+ -+static int rtl8226_match_phy_device(struct phy_device *phydev) -+{ -+ return phydev->phy_id == RTL_GENERIC_PHYID && -+ rtlgen_supports_2_5gbps(phydev) && -+ rtlgen_supports_mmd(phydev); -+} -+ -+static int rtlgen_is_c45_match(struct phy_device *phydev, unsigned int id, -+ bool is_c45) -+{ -+ if (phydev->is_c45) -+ return is_c45 && (id == phydev->c45_ids.device_ids[1]); -+ else -+ return !is_c45 && (id == phydev->phy_id); -+} -+ -+static int rtl8221b_match_phy_device(struct phy_device *phydev) -+{ -+ return phydev->phy_id == RTL_8221B && rtlgen_supports_mmd(phydev); -+} -+ -+static int rtl8221b_vb_cg_c22_match_phy_device(struct phy_device *phydev) -+{ -+ return rtlgen_is_c45_match(phydev, RTL_8221B_VB_CG, false); -+} -+ -+static int rtl8221b_vb_cg_c45_match_phy_device(struct phy_device *phydev) -+{ -+ return rtlgen_is_c45_match(phydev, RTL_8221B_VB_CG, true); -+} -+ -+static int rtl8221b_vn_cg_c22_match_phy_device(struct phy_device *phydev) -+{ -+ return rtlgen_is_c45_match(phydev, RTL_8221B_VN_CG, false); -+} -+ -+static int rtl8221b_vn_cg_c45_match_phy_device(struct phy_device *phydev) -+{ -+ return rtlgen_is_c45_match(phydev, RTL_8221B_VN_CG, true); -+} -+ -+static int rtl_internal_nbaset_match_phy_device(struct phy_device *phydev) -+{ -+ if (phydev->is_c45) -+ return false; -+ -+ switch (phydev->phy_id) { -+ case RTL_GENERIC_PHYID: -+ case RTL_8221B: -+ case RTL_8251B: -+ case 0x001cc841: -+ break; -+ default: -+ return false; -+ } -+ -+ return rtlgen_supports_2_5gbps(phydev) && !rtlgen_supports_mmd(phydev); -+} -+ -+static int rtl8251b_c45_match_phy_device(struct phy_device *phydev) -+{ -+ return rtlgen_is_c45_match(phydev, RTL_8251B, true); -+} -+ -+static int rtlgen_resume(struct phy_device *phydev) -+{ -+ int ret = genphy_resume(phydev); -+ -+ /* Internal PHY's from RTL8168h up may not be instantly ready */ -+ msleep(20); -+ -+ return ret; -+} -+ -+static int rtlgen_c45_resume(struct phy_device *phydev) -+{ -+ int ret = genphy_c45_pma_resume(phydev); -+ -+ msleep(20); -+ -+ return ret; -+} -+ -+static int rtl9000a_config_init(struct phy_device *phydev) -+{ -+ phydev->autoneg = AUTONEG_DISABLE; -+ phydev->speed = SPEED_100; -+ phydev->duplex = DUPLEX_FULL; -+ -+ return 0; -+} -+ -+static int rtl9000a_config_aneg(struct phy_device *phydev) -+{ -+ int ret; -+ u16 ctl = 0; -+ -+ switch (phydev->master_slave_set) { -+ case MASTER_SLAVE_CFG_MASTER_FORCE: -+ ctl |= CTL1000_AS_MASTER; -+ break; -+ case MASTER_SLAVE_CFG_SLAVE_FORCE: -+ break; -+ case MASTER_SLAVE_CFG_UNKNOWN: -+ case MASTER_SLAVE_CFG_UNSUPPORTED: -+ return 0; -+ default: -+ phydev_warn(phydev, "Unsupported Master/Slave mode\n"); -+ return -EOPNOTSUPP; -+ } -+ -+ ret = phy_modify_changed(phydev, MII_CTRL1000, CTL1000_AS_MASTER, ctl); -+ if (ret == 1) -+ ret = genphy_soft_reset(phydev); -+ -+ return ret; -+} -+ -+static int rtl9000a_read_status(struct phy_device *phydev) -+{ -+ int ret; -+ -+ phydev->master_slave_get = MASTER_SLAVE_CFG_UNKNOWN; -+ phydev->master_slave_state = MASTER_SLAVE_STATE_UNKNOWN; -+ -+ ret = genphy_update_link(phydev); -+ if (ret) -+ return ret; -+ -+ ret = phy_read(phydev, MII_CTRL1000); -+ if (ret < 0) -+ return ret; -+ if (ret & CTL1000_AS_MASTER) -+ phydev->master_slave_get = MASTER_SLAVE_CFG_MASTER_FORCE; -+ else -+ phydev->master_slave_get = MASTER_SLAVE_CFG_SLAVE_FORCE; -+ -+ ret = phy_read(phydev, MII_STAT1000); -+ if (ret < 0) -+ return ret; -+ if (ret & LPA_1000MSRES) -+ phydev->master_slave_state = MASTER_SLAVE_STATE_MASTER; -+ else -+ phydev->master_slave_state = MASTER_SLAVE_STATE_SLAVE; -+ -+ return 0; -+} -+ -+static int rtl9000a_ack_interrupt(struct phy_device *phydev) -+{ -+ int err; -+ -+ err = phy_read(phydev, RTL8211F_INSR); -+ -+ return (err < 0) ? err : 0; -+} -+ -+static int rtl9000a_config_intr(struct phy_device *phydev) -+{ -+ u16 val; -+ int err; -+ -+ if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { -+ err = rtl9000a_ack_interrupt(phydev); -+ if (err) -+ return err; -+ -+ val = (u16)~RTL9000A_GINMR_LINK_STATUS; -+ err = phy_write_paged(phydev, 0xa42, RTL9000A_GINMR, val); -+ } else { -+ val = ~0; -+ err = phy_write_paged(phydev, 0xa42, RTL9000A_GINMR, val); -+ if (err) -+ return err; -+ -+ err = rtl9000a_ack_interrupt(phydev); -+ } -+ -+ return phy_write_paged(phydev, 0xa42, RTL9000A_GINMR, val); -+} -+ -+static irqreturn_t rtl9000a_handle_interrupt(struct phy_device *phydev) -+{ -+ int irq_status; -+ -+ irq_status = phy_read(phydev, RTL8211F_INSR); -+ if (irq_status < 0) { -+ phy_error(phydev); -+ return IRQ_NONE; -+ } -+ -+ if (!(irq_status & RTL8211F_INER_LINK_STATUS)) -+ return IRQ_NONE; -+ -+ phy_trigger_machine(phydev); -+ -+ return IRQ_HANDLED; -+} -+ -+static struct phy_driver realtek_drvs[] = { -+ { -+ PHY_ID_MATCH_EXACT(0x00008201), -+ .name = "RTL8201CP Ethernet", -+ .read_page = rtl821x_read_page, -+ .write_page = rtl821x_write_page, -+ }, { -+ PHY_ID_MATCH_EXACT(0x001cc816), -+ .name = "RTL8201F Fast Ethernet", -+ .config_intr = &rtl8201_config_intr, -+ .handle_interrupt = rtl8201_handle_interrupt, -+ .suspend = genphy_suspend, -+ .resume = genphy_resume, -+ .read_page = rtl821x_read_page, -+ .write_page = rtl821x_write_page, -+ }, { -+ PHY_ID_MATCH_MODEL(0x001cc880), -+ .name = "RTL8208 Fast Ethernet", -+ .read_mmd = genphy_read_mmd_unsupported, -+ .write_mmd = genphy_write_mmd_unsupported, -+ .suspend = genphy_suspend, -+ .resume = genphy_resume, -+ .read_page = rtl821x_read_page, -+ .write_page = rtl821x_write_page, -+ }, { -+ PHY_ID_MATCH_EXACT(0x001cc910), -+ .name = "RTL8211 Gigabit Ethernet", -+ .config_aneg = rtl8211_config_aneg, -+ .read_mmd = &genphy_read_mmd_unsupported, -+ .write_mmd = &genphy_write_mmd_unsupported, -+ .read_page = rtl821x_read_page, -+ .write_page = rtl821x_write_page, -+ }, { -+ PHY_ID_MATCH_EXACT(0x001cc912), -+ .name = "RTL8211B Gigabit Ethernet", -+ .config_intr = &rtl8211b_config_intr, -+ .handle_interrupt = rtl821x_handle_interrupt, -+ .read_mmd = &genphy_read_mmd_unsupported, -+ .write_mmd = &genphy_write_mmd_unsupported, -+ .suspend = rtl8211b_suspend, -+ .resume = rtl8211b_resume, -+ .read_page = rtl821x_read_page, -+ .write_page = rtl821x_write_page, -+ }, { -+ PHY_ID_MATCH_EXACT(0x001cc913), -+ .name = "RTL8211C Gigabit Ethernet", -+ .config_init = rtl8211c_config_init, -+ .read_mmd = &genphy_read_mmd_unsupported, -+ .write_mmd = &genphy_write_mmd_unsupported, -+ .read_page = rtl821x_read_page, -+ .write_page = rtl821x_write_page, -+ }, { -+ PHY_ID_MATCH_EXACT(0x001cc914), -+ .name = "RTL8211DN Gigabit Ethernet", -+ .config_intr = rtl8211e_config_intr, -+ .handle_interrupt = rtl821x_handle_interrupt, -+ .suspend = genphy_suspend, -+ .resume = genphy_resume, -+ .read_page = rtl821x_read_page, -+ .write_page = rtl821x_write_page, -+ }, { -+ PHY_ID_MATCH_EXACT(0x001cc915), -+ .name = "RTL8211E Gigabit Ethernet", -+ .config_init = &rtl8211e_config_init, -+ .config_intr = &rtl8211e_config_intr, -+ .handle_interrupt = rtl821x_handle_interrupt, -+ .suspend = genphy_suspend, -+ .resume = genphy_resume, -+ .read_page = rtl821x_read_page, -+ .write_page = rtl821x_write_page, -+ }, { -+ PHY_ID_MATCH_EXACT(0x001cc916), -+ .name = "RTL8211F Gigabit Ethernet", -+ .probe = rtl821x_probe, -+ .config_init = &rtl8211f_config_init, -+ .read_status = rtlgen_read_status, -+ .config_intr = &rtl8211f_config_intr, -+ .handle_interrupt = rtl8211f_handle_interrupt, -+ .suspend = rtl821x_suspend, -+ .resume = rtl821x_resume, -+ .read_page = rtl821x_read_page, -+ .write_page = rtl821x_write_page, -+ .flags = PHY_ALWAYS_CALL_SUSPEND, -+ .led_hw_is_supported = rtl8211f_led_hw_is_supported, -+ .led_hw_control_get = rtl8211f_led_hw_control_get, -+ .led_hw_control_set = rtl8211f_led_hw_control_set, -+ }, { -+ PHY_ID_MATCH_EXACT(RTL_8211FVD_PHYID), -+ .name = "RTL8211F-VD Gigabit Ethernet", -+ .probe = rtl821x_probe, -+ .config_init = &rtl8211f_config_init, -+ .read_status = rtlgen_read_status, -+ .config_intr = &rtl8211f_config_intr, -+ .handle_interrupt = rtl8211f_handle_interrupt, -+ .suspend = rtl821x_suspend, -+ .resume = rtl821x_resume, -+ .read_page = rtl821x_read_page, -+ .write_page = rtl821x_write_page, -+ .flags = PHY_ALWAYS_CALL_SUSPEND, -+ }, { -+ .name = "Generic FE-GE Realtek PHY", -+ .match_phy_device = rtlgen_match_phy_device, -+ .read_status = rtlgen_read_status, -+ .suspend = genphy_suspend, -+ .resume = rtlgen_resume, -+ .read_page = rtl821x_read_page, -+ .write_page = rtl821x_write_page, -+ .read_mmd = rtlgen_read_mmd, -+ .write_mmd = rtlgen_write_mmd, -+ }, { -+ .name = "RTL8226 2.5Gbps PHY", -+ .match_phy_device = rtl8226_match_phy_device, -+ .get_features = rtl822x_get_features, -+ .config_aneg = rtl822x_config_aneg, -+ .read_status = rtl822x_read_status, -+ .suspend = genphy_suspend, -+ .resume = rtlgen_resume, -+ .read_page = rtl821x_read_page, -+ .write_page = rtl821x_write_page, -+ }, { -+ .match_phy_device = rtl8221b_match_phy_device, -+ .name = "RTL8226B_RTL8221B 2.5Gbps PHY", -+ .get_features = rtl822x_get_features, -+ .config_aneg = rtl822x_config_aneg, -+ .config_init = rtl822xb_config_init, -+ .get_rate_matching = rtl822xb_get_rate_matching, -+ .read_status = rtl822xb_read_status, -+ .suspend = genphy_suspend, -+ .resume = rtlgen_resume, -+ .read_page = rtl821x_read_page, -+ .write_page = rtl821x_write_page, -+ }, { -+ PHY_ID_MATCH_EXACT(0x001cc838), -+ .name = "RTL8226-CG 2.5Gbps PHY", -+ .get_features = rtl822x_get_features, -+ .config_aneg = rtl822x_config_aneg, -+ .read_status = rtl822x_read_status, -+ .suspend = genphy_suspend, -+ .resume = rtlgen_resume, -+ .read_page = rtl821x_read_page, -+ .write_page = rtl821x_write_page, -+ }, { -+ PHY_ID_MATCH_EXACT(0x001cc848), -+ .name = "RTL8226B-CG_RTL8221B-CG 2.5Gbps PHY", -+ .get_features = rtl822x_get_features, -+ .config_aneg = rtl822x_config_aneg, -+ .config_init = rtl822xb_config_init, -+ .get_rate_matching = rtl822xb_get_rate_matching, -+ .read_status = rtl822xb_read_status, -+ .suspend = genphy_suspend, -+ .resume = rtlgen_resume, -+ .read_page = rtl821x_read_page, -+ .write_page = rtl821x_write_page, -+ }, { -+ .match_phy_device = rtl8221b_vb_cg_c22_match_phy_device, -+ .name = "RTL8221B-VB-CG 2.5Gbps PHY (C22)", -+ .get_features = rtl822x_get_features, -+ .config_aneg = rtl822x_config_aneg, -+ .config_init = rtl822xb_config_init, -+ .get_rate_matching = rtl822xb_get_rate_matching, -+ .read_status = rtl822xb_read_status, -+ .suspend = genphy_suspend, -+ .resume = rtlgen_resume, -+ .read_page = rtl821x_read_page, -+ .write_page = rtl821x_write_page, -+ }, { -+ .match_phy_device = rtl8221b_vb_cg_c45_match_phy_device, -+ .name = "RTL8221B-VB-CG 2.5Gbps PHY (C45)", -+ .config_init = rtl822xb_config_init, -+ .get_rate_matching = rtl822xb_get_rate_matching, -+ .get_features = rtl822x_c45_get_features, -+ .config_aneg = rtl822x_c45_config_aneg, -+ .read_status = rtl822xb_c45_read_status, -+ .suspend = genphy_c45_pma_suspend, -+ .resume = rtlgen_c45_resume, -+ }, { -+ .match_phy_device = rtl8221b_vn_cg_c22_match_phy_device, -+ .name = "RTL8221B-VM-CG 2.5Gbps PHY (C22)", -+ .get_features = rtl822x_get_features, -+ .config_aneg = rtl822x_config_aneg, -+ .config_init = rtl822xb_config_init, -+ .get_rate_matching = rtl822xb_get_rate_matching, -+ .read_status = rtl822xb_read_status, -+ .suspend = genphy_suspend, -+ .resume = rtlgen_resume, -+ .read_page = rtl821x_read_page, -+ .write_page = rtl821x_write_page, -+ }, { -+ .match_phy_device = rtl8221b_vn_cg_c45_match_phy_device, -+ .name = "RTL8221B-VN-CG 2.5Gbps PHY (C45)", -+ .config_init = rtl822xb_config_init, -+ .get_rate_matching = rtl822xb_get_rate_matching, -+ .get_features = rtl822x_c45_get_features, -+ .config_aneg = rtl822x_c45_config_aneg, -+ .read_status = rtl822xb_c45_read_status, -+ .suspend = genphy_c45_pma_suspend, -+ .resume = rtlgen_c45_resume, -+ }, { -+ .match_phy_device = rtl8251b_c45_match_phy_device, -+ .name = "RTL8251B 5Gbps PHY", -+ .get_features = rtl822x_get_features, -+ .config_aneg = rtl822x_config_aneg, -+ .read_status = rtl822x_read_status, -+ .suspend = genphy_suspend, -+ .resume = rtlgen_resume, -+ .read_page = rtl821x_read_page, -+ .write_page = rtl821x_write_page, -+ }, { -+ .match_phy_device = rtl_internal_nbaset_match_phy_device, -+ .name = "Realtek Internal NBASE-T PHY", -+ .flags = PHY_IS_INTERNAL, -+ .get_features = rtl822x_get_features, -+ .config_aneg = rtl822x_config_aneg, -+ .read_status = rtl822x_read_status, -+ .suspend = genphy_suspend, -+ .resume = rtlgen_resume, -+ .read_page = rtl821x_read_page, -+ .write_page = rtl821x_write_page, -+ .read_mmd = rtl822x_read_mmd, -+ .write_mmd = rtl822x_write_mmd, -+ }, { -+ PHY_ID_MATCH_EXACT(0x001ccad0), -+ .name = "RTL8224 2.5Gbps PHY", -+ .get_features = rtl822x_c45_get_features, -+ .config_aneg = rtl822x_c45_config_aneg, -+ .read_status = rtl822x_c45_read_status, -+ .suspend = genphy_c45_pma_suspend, -+ .resume = rtlgen_c45_resume, -+ }, { -+ PHY_ID_MATCH_EXACT(0x001cc961), -+ .name = "RTL8366RB Gigabit Ethernet", -+ .config_init = &rtl8366rb_config_init, -+ /* These interrupts are handled by the irq controller -+ * embedded inside the RTL8366RB, they get unmasked when the -+ * irq is requested and ACKed by reading the status register, -+ * which is done by the irqchip code. -+ */ -+ .config_intr = genphy_no_config_intr, -+ .handle_interrupt = genphy_handle_interrupt_no_ack, -+ .suspend = genphy_suspend, -+ .resume = genphy_resume, -+ }, { -+ PHY_ID_MATCH_EXACT(0x001ccb00), -+ .name = "RTL9000AA_RTL9000AN Ethernet", -+ .features = PHY_BASIC_T1_FEATURES, -+ .config_init = rtl9000a_config_init, -+ .config_aneg = rtl9000a_config_aneg, -+ .read_status = rtl9000a_read_status, -+ .config_intr = rtl9000a_config_intr, -+ .handle_interrupt = rtl9000a_handle_interrupt, -+ .suspend = genphy_suspend, -+ .resume = genphy_resume, -+ .read_page = rtl821x_read_page, -+ .write_page = rtl821x_write_page, -+ }, { -+ PHY_ID_MATCH_EXACT(0x001cc942), -+ .name = "RTL8365MB-VC Gigabit Ethernet", -+ /* Interrupt handling analogous to RTL8366RB */ -+ .config_intr = genphy_no_config_intr, -+ .handle_interrupt = genphy_handle_interrupt_no_ack, -+ .suspend = genphy_suspend, -+ .resume = genphy_resume, -+ }, { -+ PHY_ID_MATCH_EXACT(0x001cc960), -+ .name = "RTL8366S Gigabit Ethernet", -+ .suspend = genphy_suspend, -+ .resume = genphy_resume, -+ .read_mmd = genphy_read_mmd_unsupported, -+ .write_mmd = genphy_write_mmd_unsupported, -+ }, -+}; -+ -+module_phy_driver(realtek_drvs); -+ -+static const struct mdio_device_id __maybe_unused realtek_tbl[] = { -+ { PHY_ID_MATCH_VENDOR(0x001cc800) }, -+ { } -+}; -+ -+MODULE_DEVICE_TABLE(mdio, realtek_tbl); diff --git a/target/linux/generic/backport-6.18/781-11-v6.14-net-phy-realtek-add-hwmon-support-for-temp-sensor-on.patch b/target/linux/generic/backport-6.18/781-11-v6.14-net-phy-realtek-add-hwmon-support-for-temp-sensor-on.patch deleted file mode 100644 index 2dec701028..0000000000 --- a/target/linux/generic/backport-6.18/781-11-v6.14-net-phy-realtek-add-hwmon-support-for-temp-sensor-on.patch +++ /dev/null @@ -1,173 +0,0 @@ -From 33700ca45b7d2e1655d4cad95e25671e8a94e2f0 Mon Sep 17 00:00:00 2001 -From: Heiner Kallweit -Date: Sat, 11 Jan 2025 21:51:24 +0100 -Subject: [PATCH] net: phy: realtek: add hwmon support for temp sensor on - RTL822x - -This adds hwmon support for the temperature sensor on RTL822x. -It's available on the standalone versions of the PHY's, and on -the integrated PHY's in RTL8125B/RTL8125D/RTL8126. - -Signed-off-by: Heiner Kallweit -Reviewed-by: Andrew Lunn -Link: https://patch.msgid.link/ad6bfe9f-6375-4a00-84b4-bfb38a21bd71@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/realtek/Kconfig | 6 ++ - drivers/net/phy/realtek/Makefile | 1 + - drivers/net/phy/realtek/realtek.h | 10 ++++ - drivers/net/phy/realtek/realtek_hwmon.c | 79 +++++++++++++++++++++++++ - drivers/net/phy/realtek/realtek_main.c | 12 ++++ - 5 files changed, 108 insertions(+) - create mode 100644 drivers/net/phy/realtek/realtek.h - create mode 100644 drivers/net/phy/realtek/realtek_hwmon.c - ---- a/drivers/net/phy/realtek/Kconfig -+++ b/drivers/net/phy/realtek/Kconfig -@@ -3,3 +3,9 @@ config REALTEK_PHY - tristate "Realtek PHYs" - help - Currently supports RTL821x/RTL822x and fast ethernet PHYs -+ -+config REALTEK_PHY_HWMON -+ def_bool REALTEK_PHY && HWMON -+ depends on !(REALTEK_PHY=y && HWMON=m) -+ help -+ Optional hwmon support for the temperature sensor ---- a/drivers/net/phy/realtek/Makefile -+++ b/drivers/net/phy/realtek/Makefile -@@ -1,3 +1,4 @@ - # SPDX-License-Identifier: GPL-2.0 - realtek-y += realtek_main.o -+realtek-$(CONFIG_REALTEK_PHY_HWMON) += realtek_hwmon.o - obj-$(CONFIG_REALTEK_PHY) += realtek.o ---- /dev/null -+++ b/drivers/net/phy/realtek/realtek.h -@@ -0,0 +1,10 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+ -+#ifndef REALTEK_H -+#define REALTEK_H -+ -+#include -+ -+int rtl822x_hwmon_init(struct phy_device *phydev); -+ -+#endif /* REALTEK_H */ ---- /dev/null -+++ b/drivers/net/phy/realtek/realtek_hwmon.c -@@ -0,0 +1,79 @@ -+// SPDX-License-Identifier: GPL-2.0+ -+/* -+ * HWMON support for Realtek PHY's -+ * -+ * Author: Heiner Kallweit -+ */ -+ -+#include -+#include -+ -+#include "realtek.h" -+ -+#define RTL822X_VND2_TSALRM 0xa662 -+#define RTL822X_VND2_TSRR 0xbd84 -+#define RTL822X_VND2_TSSR 0xb54c -+ -+static int rtl822x_hwmon_get_temp(int raw) -+{ -+ if (raw >= 512) -+ raw -= 1024; -+ -+ return 1000 * raw / 2; -+} -+ -+static int rtl822x_hwmon_read(struct device *dev, enum hwmon_sensor_types type, -+ u32 attr, int channel, long *val) -+{ -+ struct phy_device *phydev = dev_get_drvdata(dev); -+ int raw; -+ -+ switch (attr) { -+ case hwmon_temp_input: -+ raw = phy_read_mmd(phydev, MDIO_MMD_VEND2, RTL822X_VND2_TSRR) & 0x3ff; -+ *val = rtl822x_hwmon_get_temp(raw); -+ break; -+ case hwmon_temp_max: -+ /* Chip reduces speed to 1G if threshold is exceeded */ -+ raw = phy_read_mmd(phydev, MDIO_MMD_VEND2, RTL822X_VND2_TSSR) >> 6; -+ *val = rtl822x_hwmon_get_temp(raw); -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+static const struct hwmon_ops rtl822x_hwmon_ops = { -+ .visible = 0444, -+ .read = rtl822x_hwmon_read, -+}; -+ -+static const struct hwmon_channel_info * const rtl822x_hwmon_info[] = { -+ HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT | HWMON_T_MAX), -+ NULL -+}; -+ -+static const struct hwmon_chip_info rtl822x_hwmon_chip_info = { -+ .ops = &rtl822x_hwmon_ops, -+ .info = rtl822x_hwmon_info, -+}; -+ -+int rtl822x_hwmon_init(struct phy_device *phydev) -+{ -+ struct device *hwdev, *dev = &phydev->mdio.dev; -+ const char *name; -+ -+ /* Ensure over-temp alarm is reset. */ -+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2, RTL822X_VND2_TSALRM, 3); -+ -+ name = devm_hwmon_sanitize_name(dev, dev_name(dev)); -+ if (IS_ERR(name)) -+ return PTR_ERR(name); -+ -+ hwdev = devm_hwmon_device_register_with_info(dev, name, phydev, -+ &rtl822x_hwmon_chip_info, -+ NULL); -+ return PTR_ERR_OR_ZERO(hwdev); -+} ---- a/drivers/net/phy/realtek/realtek_main.c -+++ b/drivers/net/phy/realtek/realtek_main.c -@@ -14,6 +14,8 @@ - #include - #include - -+#include "realtek.h" -+ - #define RTL821x_PHYSR 0x11 - #define RTL821x_PHYSR_DUPLEX BIT(13) - #define RTL821x_PHYSR_SPEED GENMASK(15, 14) -@@ -820,6 +822,15 @@ static int rtl822x_write_mmd(struct phy_ - return ret; - } - -+static int rtl822x_probe(struct phy_device *phydev) -+{ -+ if (IS_ENABLED(CONFIG_REALTEK_PHY_HWMON) && -+ phydev->phy_id != RTL_GENERIC_PHYID) -+ return rtl822x_hwmon_init(phydev); -+ -+ return 0; -+} -+ - static int rtl822xb_config_init(struct phy_device *phydev) - { - bool has_2500, has_sgmii; -@@ -1518,6 +1529,7 @@ static struct phy_driver realtek_drvs[] - .match_phy_device = rtl_internal_nbaset_match_phy_device, - .name = "Realtek Internal NBASE-T PHY", - .flags = PHY_IS_INTERNAL, -+ .probe = rtl822x_probe, - .get_features = rtl822x_get_features, - .config_aneg = rtl822x_config_aneg, - .read_status = rtl822x_read_status, diff --git a/target/linux/generic/backport-6.18/781-12-v6.14-net-phy-realtek-HWMON-support-for-standalone-version.patch b/target/linux/generic/backport-6.18/781-12-v6.14-net-phy-realtek-HWMON-support-for-standalone-version.patch deleted file mode 100644 index 8b8c97c54f..0000000000 --- a/target/linux/generic/backport-6.18/781-12-v6.14-net-phy-realtek-HWMON-support-for-standalone-version.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 64ff63aeefb03139ae27454bd4208244579ae88e Mon Sep 17 00:00:00 2001 -From: Aleksander Jan Bajkowski -Date: Fri, 17 Jan 2025 23:24:21 +0100 -Subject: [PATCH] net: phy: realtek: HWMON support for standalone versions of - RTL8221B and RTL8251 - -HWMON support has been added for the RTL8221/8251 PHYs integrated together -with the MAC inside the RTL8125/8126 chips. This patch extends temperature -reading support for standalone variants of the mentioned PHYs. - -I don't know whether the earlier revisions of the RTL8226 also have a -built-in temperature sensor, so they have been skipped for now. - -Tested on RTL8221B-VB-CG. - -Signed-off-by: Aleksander Jan Bajkowski -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - drivers/net/phy/realtek/realtek_main.c | 5 +++++ - 1 file changed, 5 insertions(+) - ---- a/drivers/net/phy/realtek/realtek_main.c -+++ b/drivers/net/phy/realtek/realtek_main.c -@@ -1474,6 +1474,7 @@ static struct phy_driver realtek_drvs[] - }, { - .match_phy_device = rtl8221b_vb_cg_c22_match_phy_device, - .name = "RTL8221B-VB-CG 2.5Gbps PHY (C22)", -+ .probe = rtl822x_probe, - .get_features = rtl822x_get_features, - .config_aneg = rtl822x_config_aneg, - .config_init = rtl822xb_config_init, -@@ -1486,6 +1487,7 @@ static struct phy_driver realtek_drvs[] - }, { - .match_phy_device = rtl8221b_vb_cg_c45_match_phy_device, - .name = "RTL8221B-VB-CG 2.5Gbps PHY (C45)", -+ .probe = rtl822x_probe, - .config_init = rtl822xb_config_init, - .get_rate_matching = rtl822xb_get_rate_matching, - .get_features = rtl822x_c45_get_features, -@@ -1496,6 +1498,7 @@ static struct phy_driver realtek_drvs[] - }, { - .match_phy_device = rtl8221b_vn_cg_c22_match_phy_device, - .name = "RTL8221B-VM-CG 2.5Gbps PHY (C22)", -+ .probe = rtl822x_probe, - .get_features = rtl822x_get_features, - .config_aneg = rtl822x_config_aneg, - .config_init = rtl822xb_config_init, -@@ -1508,6 +1511,7 @@ static struct phy_driver realtek_drvs[] - }, { - .match_phy_device = rtl8221b_vn_cg_c45_match_phy_device, - .name = "RTL8221B-VN-CG 2.5Gbps PHY (C45)", -+ .probe = rtl822x_probe, - .config_init = rtl822xb_config_init, - .get_rate_matching = rtl822xb_get_rate_matching, - .get_features = rtl822x_c45_get_features, -@@ -1518,6 +1522,7 @@ static struct phy_driver realtek_drvs[] - }, { - .match_phy_device = rtl8251b_c45_match_phy_device, - .name = "RTL8251B 5Gbps PHY", -+ .probe = rtl822x_probe, - .get_features = rtl822x_get_features, - .config_aneg = rtl822x_config_aneg, - .read_status = rtl822x_read_status, diff --git a/target/linux/generic/backport-6.18/781-13-v6.15-net-phy-realtek-make-HWMON-support-a-user-visible-Kc.patch b/target/linux/generic/backport-6.18/781-13-v6.15-net-phy-realtek-make-HWMON-support-a-user-visible-Kc.patch deleted file mode 100644 index 821d7ee879..0000000000 --- a/target/linux/generic/backport-6.18/781-13-v6.15-net-phy-realtek-make-HWMON-support-a-user-visible-Kc.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 51773846fab24a353bed4ebb660997ced4bc32d7 Mon Sep 17 00:00:00 2001 -From: Heiner Kallweit -Date: Mon, 3 Feb 2025 21:33:39 +0100 -Subject: [PATCH] net: phy: realtek: make HWMON support a user-visible Kconfig - symbol - -Make config symbol REALTEK_PHY_HWMON user-visible, so that users can -remove support if not needed. - -Suggested-by: Geert Uytterhoeven -Signed-off-by: Heiner Kallweit -Reviewed-by: Simon Horman -Link: https://patch.msgid.link/3466ee92-166a-4b0f-9ae7-42b9e046f333@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/realtek/Kconfig | 8 ++++++-- - 1 file changed, 6 insertions(+), 2 deletions(-) - ---- a/drivers/net/phy/realtek/Kconfig -+++ b/drivers/net/phy/realtek/Kconfig -@@ -4,8 +4,12 @@ config REALTEK_PHY - help - Currently supports RTL821x/RTL822x and fast ethernet PHYs - -+if REALTEK_PHY -+ - config REALTEK_PHY_HWMON -- def_bool REALTEK_PHY && HWMON -- depends on !(REALTEK_PHY=y && HWMON=m) -+ bool "HWMON support for Realtek PHYs" -+ depends on HWMON && !(REALTEK_PHY=y && HWMON=m) - help - Optional hwmon support for the temperature sensor -+ -+endif # REALTEK_PHY diff --git a/target/linux/generic/backport-6.18/781-14-v6.15-net-phy-realtek-use-string-choices-helpers.patch b/target/linux/generic/backport-6.18/781-14-v6.15-net-phy-realtek-use-string-choices-helpers.patch deleted file mode 100644 index d3e09bc7cd..0000000000 --- a/target/linux/generic/backport-6.18/781-14-v6.15-net-phy-realtek-use-string-choices-helpers.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 0bea93fdbaf8675b7e8124bdcaf51497dcc8bcfa Mon Sep 17 00:00:00 2001 -From: Heiner Kallweit -Date: Mon, 3 Feb 2025 21:41:36 +0100 -Subject: [PATCH] net: phy: realtek: use string choices helpers - -Use string choices helpers to simplify the code. - -Reported-by: kernel test robot -Closes: https://lore.kernel.org/oe-kbuild-all/202501190707.qQS8PGHW-lkp@intel.com/ -Signed-off-by: Heiner Kallweit -Reviewed-by: Simon Horman -Signed-off-by: David S. Miller ---- - drivers/net/phy/realtek/realtek_main.c | 9 +++++---- - 1 file changed, 5 insertions(+), 4 deletions(-) - ---- a/drivers/net/phy/realtek/realtek_main.c -+++ b/drivers/net/phy/realtek/realtek_main.c -@@ -13,6 +13,7 @@ - #include - #include - #include -+#include - - #include "realtek.h" - -@@ -422,11 +423,11 @@ static int rtl8211f_config_init(struct p - } else if (ret) { - dev_dbg(dev, - "%s 2ns TX delay (and changing the value from pin-strapping RXD1 or the bootloader)\n", -- val_txdly ? "Enabling" : "Disabling"); -+ str_enable_disable(val_txdly)); - } else { - dev_dbg(dev, - "2ns TX delay was already %s (by pin-strapping RXD1 or bootloader configuration)\n", -- val_txdly ? "enabled" : "disabled"); -+ str_enabled_disabled(val_txdly)); - } - - ret = phy_modify_paged_changed(phydev, 0xd08, 0x15, RTL8211F_RX_DELAY, -@@ -437,11 +438,11 @@ static int rtl8211f_config_init(struct p - } else if (ret) { - dev_dbg(dev, - "%s 2ns RX delay (and changing the value from pin-strapping RXD0 or the bootloader)\n", -- val_rxdly ? "Enabling" : "Disabling"); -+ str_enable_disable(val_rxdly)); - } else { - dev_dbg(dev, - "2ns RX delay was already %s (by pin-strapping RXD0 or bootloader configuration)\n", -- val_rxdly ? "enabled" : "disabled"); -+ str_enabled_disabled(val_rxdly)); - } - - if (priv->has_phycr2) { diff --git a/target/linux/generic/backport-6.18/781-15-v6.15-net-phy-realtek-improve-mmd-register-access-for-inte.patch b/target/linux/generic/backport-6.18/781-15-v6.15-net-phy-realtek-improve-mmd-register-access-for-inte.patch deleted file mode 100644 index 3a3a20d58b..0000000000 --- a/target/linux/generic/backport-6.18/781-15-v6.15-net-phy-realtek-improve-mmd-register-access-for-inte.patch +++ /dev/null @@ -1,134 +0,0 @@ -From da681ed73fb980286fc29de707b35d76bb33e123 Mon Sep 17 00:00:00 2001 -From: Heiner Kallweit -Date: Thu, 13 Feb 2025 20:18:17 +0100 -Subject: [PATCH] net: phy: realtek: improve mmd register access for internal - PHY's - -r8169 provides the MDIO bus for the internal PHY's. It has been extended -with c45 access functions for addressing MDIO_MMD_VEND2 registers. -So we can switch from paged access to directly addressing the -MDIO_MMD_VEND2 registers. - -Signed-off-by: Heiner Kallweit -Reviewed-by: Andrew Lunn -Link: https://patch.msgid.link/a5f2333c-dda9-48ad-9801-77049766e632@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/realtek/realtek_main.c | 79 +++++++++++--------------- - 1 file changed, 33 insertions(+), 46 deletions(-) - ---- a/drivers/net/phy/realtek/realtek_main.c -+++ b/drivers/net/phy/realtek/realtek_main.c -@@ -735,29 +735,31 @@ static int rtlgen_read_status(struct phy - return 0; - } - -+static int rtlgen_read_vend2(struct phy_device *phydev, int regnum) -+{ -+ return __mdiobus_c45_read(phydev->mdio.bus, 0, MDIO_MMD_VEND2, regnum); -+} -+ -+static int rtlgen_write_vend2(struct phy_device *phydev, int regnum, u16 val) -+{ -+ return __mdiobus_c45_write(phydev->mdio.bus, 0, MDIO_MMD_VEND2, regnum, -+ val); -+} -+ - static int rtlgen_read_mmd(struct phy_device *phydev, int devnum, u16 regnum) - { - int ret; - -- if (devnum == MDIO_MMD_VEND2) { -- rtl821x_write_page(phydev, regnum >> 4); -- ret = __phy_read(phydev, 0x10 + ((regnum & 0xf) >> 1)); -- rtl821x_write_page(phydev, 0); -- } else if (devnum == MDIO_MMD_PCS && regnum == MDIO_PCS_EEE_ABLE) { -- rtl821x_write_page(phydev, 0xa5c); -- ret = __phy_read(phydev, 0x12); -- rtl821x_write_page(phydev, 0); -- } else if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_ADV) { -- rtl821x_write_page(phydev, 0xa5d); -- ret = __phy_read(phydev, 0x10); -- rtl821x_write_page(phydev, 0); -- } else if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_LPABLE) { -- rtl821x_write_page(phydev, 0xa5d); -- ret = __phy_read(phydev, 0x11); -- rtl821x_write_page(phydev, 0); -- } else { -+ if (devnum == MDIO_MMD_VEND2) -+ ret = rtlgen_read_vend2(phydev, regnum); -+ else if (devnum == MDIO_MMD_PCS && regnum == MDIO_PCS_EEE_ABLE) -+ ret = rtlgen_read_vend2(phydev, 0xa5c4); -+ else if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_ADV) -+ ret = rtlgen_read_vend2(phydev, 0xa5d0); -+ else if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_LPABLE) -+ ret = rtlgen_read_vend2(phydev, 0xa5d2); -+ else - ret = -EOPNOTSUPP; -- } - - return ret; - } -@@ -767,17 +769,12 @@ static int rtlgen_write_mmd(struct phy_d - { - int ret; - -- if (devnum == MDIO_MMD_VEND2) { -- rtl821x_write_page(phydev, regnum >> 4); -- ret = __phy_write(phydev, 0x10 + ((regnum & 0xf) >> 1), val); -- rtl821x_write_page(phydev, 0); -- } else if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_ADV) { -- rtl821x_write_page(phydev, 0xa5d); -- ret = __phy_write(phydev, 0x10, val); -- rtl821x_write_page(phydev, 0); -- } else { -+ if (devnum == MDIO_MMD_VEND2) -+ ret = rtlgen_write_vend2(phydev, regnum, val); -+ else if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_ADV) -+ ret = rtlgen_write_vend2(phydev, regnum, 0xa5d0); -+ else - ret = -EOPNOTSUPP; -- } - - return ret; - } -@@ -789,19 +786,12 @@ static int rtl822x_read_mmd(struct phy_d - if (ret != -EOPNOTSUPP) - return ret; - -- if (devnum == MDIO_MMD_PCS && regnum == MDIO_PCS_EEE_ABLE2) { -- rtl821x_write_page(phydev, 0xa6e); -- ret = __phy_read(phydev, 0x16); -- rtl821x_write_page(phydev, 0); -- } else if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_ADV2) { -- rtl821x_write_page(phydev, 0xa6d); -- ret = __phy_read(phydev, 0x12); -- rtl821x_write_page(phydev, 0); -- } else if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_LPABLE2) { -- rtl821x_write_page(phydev, 0xa6d); -- ret = __phy_read(phydev, 0x10); -- rtl821x_write_page(phydev, 0); -- } -+ if (devnum == MDIO_MMD_PCS && regnum == MDIO_PCS_EEE_ABLE2) -+ ret = rtlgen_read_vend2(phydev, 0xa6ec); -+ else if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_ADV2) -+ ret = rtlgen_read_vend2(phydev, 0xa6d4); -+ else if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_LPABLE2) -+ ret = rtlgen_read_vend2(phydev, 0xa6d0); - - return ret; - } -@@ -814,11 +804,8 @@ static int rtl822x_write_mmd(struct phy_ - if (ret != -EOPNOTSUPP) - return ret; - -- if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_ADV2) { -- rtl821x_write_page(phydev, 0xa6d); -- ret = __phy_write(phydev, 0x12, val); -- rtl821x_write_page(phydev, 0); -- } -+ if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_ADV2) -+ ret = rtlgen_write_vend2(phydev, 0xa6d4, val); - - return ret; - } diff --git a/target/linux/generic/backport-6.18/781-16-v6.15-net-phy-realtek-switch-from-paged-to-MMD-ops-in-rtl8.patch b/target/linux/generic/backport-6.18/781-16-v6.15-net-phy-realtek-switch-from-paged-to-MMD-ops-in-rtl8.patch deleted file mode 100644 index 5e3c3ce70a..0000000000 --- a/target/linux/generic/backport-6.18/781-16-v6.15-net-phy-realtek-switch-from-paged-to-MMD-ops-in-rtl8.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 02d3b306ac2f0b174753d1c5b9e4e5fb8ec5057e Mon Sep 17 00:00:00 2001 -From: Heiner Kallweit -Date: Thu, 13 Feb 2025 20:19:14 +0100 -Subject: [PATCH] net: phy: realtek: switch from paged to MMD ops in rtl822x - functions - -The MDIO bus provided by r8169 for the internal PHY's now supports -c45 ops for the MDIO_MMD_VEND2 device. So we can switch to standard -MMD ops here. - -Signed-off-by: Heiner Kallweit -Reviewed-by: Andrew Lunn -Link: https://patch.msgid.link/81416f95-0fac-4225-87b4-828e3738b8ed@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/realtek/realtek_main.c | 11 +++++------ - 1 file changed, 5 insertions(+), 6 deletions(-) - ---- a/drivers/net/phy/realtek/realtek_main.c -+++ b/drivers/net/phy/realtek/realtek_main.c -@@ -901,7 +901,7 @@ static int rtl822x_get_features(struct p - { - int val; - -- val = phy_read_paged(phydev, 0xa61, 0x13); -+ val = phy_read_mmd(phydev, MDIO_MMD_VEND2, 0xa616); - if (val < 0) - return val; - -@@ -922,10 +922,9 @@ static int rtl822x_config_aneg(struct ph - if (phydev->autoneg == AUTONEG_ENABLE) { - u16 adv = linkmode_adv_to_mii_10gbt_adv_t(phydev->advertising); - -- ret = phy_modify_paged_changed(phydev, 0xa5d, 0x12, -- MDIO_AN_10GBT_CTRL_ADV2_5G | -- MDIO_AN_10GBT_CTRL_ADV5G, -- adv); -+ ret = phy_modify_mmd_changed(phydev, MDIO_MMD_VEND2, 0xa5d4, -+ MDIO_AN_10GBT_CTRL_ADV2_5G | -+ MDIO_AN_10GBT_CTRL_ADV5G, adv); - if (ret < 0) - return ret; - } -@@ -969,7 +968,7 @@ static int rtl822x_read_status(struct ph - !phydev->autoneg_complete) - return 0; - -- lpadv = phy_read_paged(phydev, 0xa5d, 0x13); -+ lpadv = phy_read_mmd(phydev, MDIO_MMD_VEND2, 0xa5d6); - if (lpadv < 0) - return lpadv; - diff --git a/target/linux/generic/backport-6.18/781-17-v6.15-net-phy-realtek-add-helper-RTL822X_VND2_C22_REG.patch b/target/linux/generic/backport-6.18/781-17-v6.15-net-phy-realtek-add-helper-RTL822X_VND2_C22_REG.patch deleted file mode 100644 index 5134d08b1c..0000000000 --- a/target/linux/generic/backport-6.18/781-17-v6.15-net-phy-realtek-add-helper-RTL822X_VND2_C22_REG.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 8af2136e77989a64fae0284bf76fd584e32edd3a Mon Sep 17 00:00:00 2001 -From: Heiner Kallweit -Date: Fri, 14 Feb 2025 21:31:14 +0100 -Subject: [PATCH] net: phy: realtek: add helper RTL822X_VND2_C22_REG - -C22 register space is mapped to 0xa400 in MMD VEND2 register space. -Add a helper to access mapped C22 registers. - -Signed-off-by: Heiner Kallweit -Reviewed-by: Andrew Lunn -Link: https://patch.msgid.link/6344277b-c5c7-449b-ac89-d5425306ca76@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/realtek/realtek_main.c | 9 ++++----- - 1 file changed, 4 insertions(+), 5 deletions(-) - ---- a/drivers/net/phy/realtek/realtek_main.c -+++ b/drivers/net/phy/realtek/realtek_main.c -@@ -79,9 +79,7 @@ - /* RTL822X_VND2_XXXXX registers are only accessible when phydev->is_c45 - * is set, they cannot be accessed by C45-over-C22. - */ --#define RTL822X_VND2_GBCR 0xa412 -- --#define RTL822X_VND2_GANLPAR 0xa414 -+#define RTL822X_VND2_C22_REG(reg) (0xa400 + 2 * (reg)) - - #define RTL8366RB_POWER_SAVE 0x15 - #define RTL8366RB_POWER_SAVE_ON BIT(12) -@@ -1015,7 +1013,8 @@ static int rtl822x_c45_config_aneg(struc - val = linkmode_adv_to_mii_ctrl1000_t(phydev->advertising); - - /* Vendor register as C45 has no standardized support for 1000BaseT */ -- ret = phy_modify_mmd_changed(phydev, MDIO_MMD_VEND2, RTL822X_VND2_GBCR, -+ ret = phy_modify_mmd_changed(phydev, MDIO_MMD_VEND2, -+ RTL822X_VND2_C22_REG(MII_CTRL1000), - ADVERTISE_1000FULL, val); - if (ret < 0) - return ret; -@@ -1032,7 +1031,7 @@ static int rtl822x_c45_read_status(struc - /* Vendor register as C45 has no standardized support for 1000BaseT */ - if (phydev->autoneg == AUTONEG_ENABLE && genphy_c45_aneg_done(phydev)) { - val = phy_read_mmd(phydev, MDIO_MMD_VEND2, -- RTL822X_VND2_GANLPAR); -+ RTL822X_VND2_C22_REG(MII_STAT1000)); - if (val < 0) - return val; - } else { diff --git a/target/linux/generic/backport-6.18/781-18-v6.15-net-phy-realtek-add-defines-for-shadowed-c45-standar.patch b/target/linux/generic/backport-6.18/781-18-v6.15-net-phy-realtek-add-defines-for-shadowed-c45-standar.patch deleted file mode 100644 index ff7d5b1fb6..0000000000 --- a/target/linux/generic/backport-6.18/781-18-v6.15-net-phy-realtek-add-defines-for-shadowed-c45-standar.patch +++ /dev/null @@ -1,113 +0,0 @@ -From fabcfd6d10999024a721ae1b965b57eb8a305ace Mon Sep 17 00:00:00 2001 -From: Heiner Kallweit -Date: Sat, 15 Feb 2025 14:29:15 +0100 -Subject: [PATCH] net: phy: realtek: add defines for shadowed c45 standard - registers - -Realtek shadows standard c45 registers in VEND2 device register space. -Add defines for these VEND2 registers, based on the names of the -standard c45 registers. - -Signed-off-by: Heiner Kallweit -Reviewed-by: Andrew Lunn -Link: https://patch.msgid.link/c90bdf76-f8b8-4d06-9656-7a52d5658ee6@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/realtek/realtek_main.c | 33 +++++++++++++++++--------- - 1 file changed, 22 insertions(+), 11 deletions(-) - ---- a/drivers/net/phy/realtek/realtek_main.c -+++ b/drivers/net/phy/realtek/realtek_main.c -@@ -94,6 +94,16 @@ - #define RTL_VND2_PHYSR_MASTER BIT(11) - #define RTL_VND2_PHYSR_SPEED_MASK (RTL_VND2_PHYSR_SPEEDL | RTL_VND2_PHYSR_SPEEDH) - -+#define RTL_MDIO_PCS_EEE_ABLE 0xa5c4 -+#define RTL_MDIO_AN_EEE_ADV 0xa5d0 -+#define RTL_MDIO_AN_EEE_LPABLE 0xa5d2 -+#define RTL_MDIO_AN_10GBT_CTRL 0xa5d4 -+#define RTL_MDIO_AN_10GBT_STAT 0xa5d6 -+#define RTL_MDIO_PMA_SPEED 0xa616 -+#define RTL_MDIO_AN_EEE_LPABLE2 0xa6d0 -+#define RTL_MDIO_AN_EEE_ADV2 0xa6d4 -+#define RTL_MDIO_PCS_EEE_ABLE2 0xa6ec -+ - #define RTL_GENERIC_PHYID 0x001cc800 - #define RTL_8211FVD_PHYID 0x001cc878 - #define RTL_8221B 0x001cc840 -@@ -751,11 +761,11 @@ static int rtlgen_read_mmd(struct phy_de - if (devnum == MDIO_MMD_VEND2) - ret = rtlgen_read_vend2(phydev, regnum); - else if (devnum == MDIO_MMD_PCS && regnum == MDIO_PCS_EEE_ABLE) -- ret = rtlgen_read_vend2(phydev, 0xa5c4); -+ ret = rtlgen_read_vend2(phydev, RTL_MDIO_PCS_EEE_ABLE); - else if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_ADV) -- ret = rtlgen_read_vend2(phydev, 0xa5d0); -+ ret = rtlgen_read_vend2(phydev, RTL_MDIO_AN_EEE_ADV); - else if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_LPABLE) -- ret = rtlgen_read_vend2(phydev, 0xa5d2); -+ ret = rtlgen_read_vend2(phydev, RTL_MDIO_AN_EEE_LPABLE); - else - ret = -EOPNOTSUPP; - -@@ -770,7 +780,7 @@ static int rtlgen_write_mmd(struct phy_d - if (devnum == MDIO_MMD_VEND2) - ret = rtlgen_write_vend2(phydev, regnum, val); - else if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_ADV) -- ret = rtlgen_write_vend2(phydev, regnum, 0xa5d0); -+ ret = rtlgen_write_vend2(phydev, regnum, RTL_MDIO_AN_EEE_ADV); - else - ret = -EOPNOTSUPP; - -@@ -785,11 +795,11 @@ static int rtl822x_read_mmd(struct phy_d - return ret; - - if (devnum == MDIO_MMD_PCS && regnum == MDIO_PCS_EEE_ABLE2) -- ret = rtlgen_read_vend2(phydev, 0xa6ec); -+ ret = rtlgen_read_vend2(phydev, RTL_MDIO_PCS_EEE_ABLE2); - else if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_ADV2) -- ret = rtlgen_read_vend2(phydev, 0xa6d4); -+ ret = rtlgen_read_vend2(phydev, RTL_MDIO_AN_EEE_ADV2); - else if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_LPABLE2) -- ret = rtlgen_read_vend2(phydev, 0xa6d0); -+ ret = rtlgen_read_vend2(phydev, RTL_MDIO_AN_EEE_LPABLE2); - - return ret; - } -@@ -803,7 +813,7 @@ static int rtl822x_write_mmd(struct phy_ - return ret; - - if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_ADV2) -- ret = rtlgen_write_vend2(phydev, 0xa6d4, val); -+ ret = rtlgen_write_vend2(phydev, RTL_MDIO_AN_EEE_ADV2, val); - - return ret; - } -@@ -899,7 +909,7 @@ static int rtl822x_get_features(struct p - { - int val; - -- val = phy_read_mmd(phydev, MDIO_MMD_VEND2, 0xa616); -+ val = phy_read_mmd(phydev, MDIO_MMD_VEND2, RTL_MDIO_PMA_SPEED); - if (val < 0) - return val; - -@@ -920,7 +930,8 @@ static int rtl822x_config_aneg(struct ph - if (phydev->autoneg == AUTONEG_ENABLE) { - u16 adv = linkmode_adv_to_mii_10gbt_adv_t(phydev->advertising); - -- ret = phy_modify_mmd_changed(phydev, MDIO_MMD_VEND2, 0xa5d4, -+ ret = phy_modify_mmd_changed(phydev, MDIO_MMD_VEND2, -+ RTL_MDIO_AN_10GBT_CTRL, - MDIO_AN_10GBT_CTRL_ADV2_5G | - MDIO_AN_10GBT_CTRL_ADV5G, adv); - if (ret < 0) -@@ -966,7 +977,7 @@ static int rtl822x_read_status(struct ph - !phydev->autoneg_complete) - return 0; - -- lpadv = phy_read_mmd(phydev, MDIO_MMD_VEND2, 0xa5d6); -+ lpadv = phy_read_mmd(phydev, MDIO_MMD_VEND2, RTL_MDIO_AN_10GBT_STAT); - if (lpadv < 0) - return lpadv; - diff --git a/target/linux/generic/backport-6.18/781-19-v6.15-net-phy-realtek-disable-PHY-mode-EEE.patch b/target/linux/generic/backport-6.18/781-19-v6.15-net-phy-realtek-disable-PHY-mode-EEE.patch deleted file mode 100644 index 4d755d4e22..0000000000 --- a/target/linux/generic/backport-6.18/781-19-v6.15-net-phy-realtek-disable-PHY-mode-EEE.patch +++ /dev/null @@ -1,54 +0,0 @@ -From bfc17c1658353f22843c7c13e27c2d31950f1887 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Sun, 16 Mar 2025 12:39:54 +0000 -Subject: [PATCH] net: phy: realtek: disable PHY-mode EEE - -Realtek RTL8211F has a "PHY-mode" EEE support which interferes with an -IEEE 802.3 compliant implementation. This mode defaults to enabled, and -results in the MAC receive path not seeing the link transition to LPI -state. - -Fix this by disabling PHY-mode EEE. - -Signed-off-by: Russell King (Oracle) -Reviewed-by: Andrew Lunn -Link: https://patch.msgid.link/E1ttnHW-00785s-Uq@rmk-PC.armlinux.org.uk -Signed-off-by: Paolo Abeni ---- - drivers/net/phy/realtek/realtek_main.c | 11 +++++++++-- - 1 file changed, 9 insertions(+), 2 deletions(-) - ---- a/drivers/net/phy/realtek/realtek_main.c -+++ b/drivers/net/phy/realtek/realtek_main.c -@@ -33,6 +33,9 @@ - - #define RTL8211F_PHYCR1 0x18 - #define RTL8211F_PHYCR2 0x19 -+#define RTL8211F_CLKOUT_EN BIT(0) -+#define RTL8211F_PHYCR2_PHY_EEE_ENABLE BIT(5) -+ - #define RTL8211F_INSR 0x1d - - #define RTL8211F_LEDCR 0x10 -@@ -55,8 +58,6 @@ - #define RTL8211E_TX_DELAY BIT(12) - #define RTL8211E_RX_DELAY BIT(11) - --#define RTL8211F_CLKOUT_EN BIT(0) -- - #define RTL8201F_ISR 0x1e - #define RTL8201F_ISR_ANERR BIT(15) - #define RTL8201F_ISR_DUPLEX BIT(13) -@@ -453,6 +454,12 @@ static int rtl8211f_config_init(struct p - str_enabled_disabled(val_rxdly)); - } - -+ /* Disable PHY-mode EEE so LPI is passed to the MAC */ -+ ret = phy_modify_paged(phydev, 0xa43, RTL8211F_PHYCR2, -+ RTL8211F_PHYCR2_PHY_EEE_ENABLE, 0); -+ if (ret) -+ return ret; -+ - if (priv->has_phycr2) { - ret = phy_modify_paged(phydev, 0xa43, RTL8211F_PHYCR2, - RTL8211F_CLKOUT_EN, priv->phycr2); diff --git a/target/linux/generic/backport-6.18/781-20-v6.16-net-phy-realtek-Add-support-for-WOL-magic-packet-on.patch b/target/linux/generic/backport-6.18/781-20-v6.16-net-phy-realtek-Add-support-for-WOL-magic-packet-on.patch deleted file mode 100644 index 4ba06cc3dd..0000000000 --- a/target/linux/generic/backport-6.18/781-20-v6.16-net-phy-realtek-Add-support-for-WOL-magic-packet-on.patch +++ /dev/null @@ -1,126 +0,0 @@ -From 7840e4d6f48a75413470935ebdc4bab4fc0c035e Mon Sep 17 00:00:00 2001 -From: Daniel Braunwarth -Date: Tue, 29 Apr 2025 13:33:37 +0200 -Subject: [PATCH] net: phy: realtek: Add support for WOL magic packet on - RTL8211F - -The RTL8211F supports multiple WOL modes. This patch adds support for -magic packets. - -The PHY notifies the system via the INTB/PMEB pin when a WOL event -occurs. - -Signed-off-by: Daniel Braunwarth -Reviewed-by: Andrew Lunn -Link: https://patch.msgid.link/20250429-realtek_wol-v2-1-8f84def1ef2c@kuka.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/realtek/realtek_main.c | 69 ++++++++++++++++++++++++++ - 1 file changed, 69 insertions(+) - ---- a/drivers/net/phy/realtek/realtek_main.c -+++ b/drivers/net/phy/realtek/realtek_main.c -@@ -10,6 +10,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -38,6 +39,24 @@ - - #define RTL8211F_INSR 0x1d - -+/* RTL8211F WOL interrupt configuration */ -+#define RTL8211F_INTBCR_PAGE 0xd40 -+#define RTL8211F_INTBCR 0x16 -+#define RTL8211F_INTBCR_INTB_PMEB BIT(5) -+ -+/* RTL8211F WOL settings */ -+#define RTL8211F_WOL_SETTINGS_PAGE 0xd8a -+#define RTL8211F_WOL_SETTINGS_EVENTS 16 -+#define RTL8211F_WOL_EVENT_MAGIC BIT(12) -+#define RTL8211F_WOL_SETTINGS_STATUS 17 -+#define RTL8211F_WOL_STATUS_RESET (BIT(15) | 0x1fff) -+ -+/* RTL8211F Unique phyiscal and multicast address (WOL) */ -+#define RTL8211F_PHYSICAL_ADDR_PAGE 0xd8c -+#define RTL8211F_PHYSICAL_ADDR_WORD0 16 -+#define RTL8211F_PHYSICAL_ADDR_WORD1 17 -+#define RTL8211F_PHYSICAL_ADDR_WORD2 18 -+ - #define RTL8211F_LEDCR 0x10 - #define RTL8211F_LEDCR_MODE BIT(15) - #define RTL8211F_LEDCR_ACT_TXRX BIT(4) -@@ -123,6 +142,7 @@ struct rtl821x_priv { - u16 phycr2; - bool has_phycr2; - struct clk *clk; -+ u32 saved_wolopts; - }; - - static int rtl821x_read_page(struct phy_device *phydev) -@@ -354,6 +374,53 @@ static irqreturn_t rtl8211f_handle_inter - return IRQ_HANDLED; - } - -+static void rtl8211f_get_wol(struct phy_device *dev, struct ethtool_wolinfo *wol) -+{ -+ wol->supported = WAKE_MAGIC; -+ if (phy_read_paged(dev, RTL8211F_WOL_SETTINGS_PAGE, RTL8211F_WOL_SETTINGS_EVENTS) -+ & RTL8211F_WOL_EVENT_MAGIC) -+ wol->wolopts = WAKE_MAGIC; -+} -+ -+static int rtl8211f_set_wol(struct phy_device *dev, struct ethtool_wolinfo *wol) -+{ -+ const u8 *mac_addr = dev->attached_dev->dev_addr; -+ int oldpage; -+ -+ oldpage = phy_save_page(dev); -+ if (oldpage < 0) -+ goto err; -+ -+ if (wol->wolopts & WAKE_MAGIC) { -+ /* Store the device address for the magic packet */ -+ rtl821x_write_page(dev, RTL8211F_PHYSICAL_ADDR_PAGE); -+ __phy_write(dev, RTL8211F_PHYSICAL_ADDR_WORD0, mac_addr[1] << 8 | (mac_addr[0])); -+ __phy_write(dev, RTL8211F_PHYSICAL_ADDR_WORD1, mac_addr[3] << 8 | (mac_addr[2])); -+ __phy_write(dev, RTL8211F_PHYSICAL_ADDR_WORD2, mac_addr[5] << 8 | (mac_addr[4])); -+ -+ /* Enable magic packet matching and reset WOL status */ -+ rtl821x_write_page(dev, RTL8211F_WOL_SETTINGS_PAGE); -+ __phy_write(dev, RTL8211F_WOL_SETTINGS_EVENTS, RTL8211F_WOL_EVENT_MAGIC); -+ __phy_write(dev, RTL8211F_WOL_SETTINGS_STATUS, RTL8211F_WOL_STATUS_RESET); -+ -+ /* Enable the WOL interrupt */ -+ rtl821x_write_page(dev, RTL8211F_INTBCR_PAGE); -+ __phy_set_bits(dev, RTL8211F_INTBCR, RTL8211F_INTBCR_INTB_PMEB); -+ } else { -+ /* Disable the WOL interrupt */ -+ rtl821x_write_page(dev, RTL8211F_INTBCR_PAGE); -+ __phy_clear_bits(dev, RTL8211F_INTBCR, RTL8211F_INTBCR_INTB_PMEB); -+ -+ /* Disable magic packet matching and reset WOL status */ -+ rtl821x_write_page(dev, RTL8211F_WOL_SETTINGS_PAGE); -+ __phy_write(dev, RTL8211F_WOL_SETTINGS_EVENTS, 0); -+ __phy_write(dev, RTL8211F_WOL_SETTINGS_STATUS, RTL8211F_WOL_STATUS_RESET); -+ } -+ -+err: -+ return phy_restore_page(dev, oldpage, 0); -+} -+ - static int rtl8211_config_aneg(struct phy_device *phydev) - { - int ret; -@@ -1400,6 +1467,8 @@ static struct phy_driver realtek_drvs[] - .read_status = rtlgen_read_status, - .config_intr = &rtl8211f_config_intr, - .handle_interrupt = rtl8211f_handle_interrupt, -+ .set_wol = rtl8211f_set_wol, -+ .get_wol = rtl8211f_get_wol, - .suspend = rtl821x_suspend, - .resume = rtl821x_resume, - .read_page = rtl821x_read_page, diff --git a/target/linux/generic/backport-6.18/781-21-v6.16-net-phy-realtek-remove-unsed-RTL821x_PHYSR-macros.patch b/target/linux/generic/backport-6.18/781-21-v6.16-net-phy-realtek-remove-unsed-RTL821x_PHYSR-macros.patch deleted file mode 100644 index e054937fdd..0000000000 --- a/target/linux/generic/backport-6.18/781-21-v6.16-net-phy-realtek-remove-unsed-RTL821x_PHYSR-macros.patch +++ /dev/null @@ -1,28 +0,0 @@ -From f3b265358b911fe9e495619bdfa7797749474f95 Mon Sep 17 00:00:00 2001 -From: Michael Klein -Date: Sun, 4 May 2025 19:29:11 +0200 -Subject: [PATCH] net: phy: realtek: remove unsed RTL821x_PHYSR* macros - -These macros have there since the first revision but were never used, so -let's just remove them. - -Signed-off-by: Michael Klein -Link: https://patch.msgid.link/20250504172916.243185-2-michael@fossekall.de -Signed-off-by: Paolo Abeni ---- - drivers/net/phy/realtek/realtek_main.c | 4 ---- - 1 file changed, 4 deletions(-) - ---- a/drivers/net/phy/realtek/realtek_main.c -+++ b/drivers/net/phy/realtek/realtek_main.c -@@ -18,10 +18,6 @@ - - #include "realtek.h" - --#define RTL821x_PHYSR 0x11 --#define RTL821x_PHYSR_DUPLEX BIT(13) --#define RTL821x_PHYSR_SPEED GENMASK(15, 14) -- - #define RTL821x_INER 0x12 - #define RTL8211B_INER_INIT 0x6400 - #define RTL8211E_INER_LINK_STATUS BIT(10) diff --git a/target/linux/generic/backport-6.18/781-22-v6.16-net-phy-realtek-Clean-up-RTL821x-ExtPage-access.patch b/target/linux/generic/backport-6.18/781-22-v6.16-net-phy-realtek-Clean-up-RTL821x-ExtPage-access.patch deleted file mode 100644 index 62bbf32f1a..0000000000 --- a/target/linux/generic/backport-6.18/781-22-v6.16-net-phy-realtek-Clean-up-RTL821x-ExtPage-access.patch +++ /dev/null @@ -1,95 +0,0 @@ -From 7c6fa3ffd2650347b1d37f028e232e53d617c1af Mon Sep 17 00:00:00 2001 -From: Michael Klein -Date: Sun, 4 May 2025 19:29:12 +0200 -Subject: [PATCH] net: phy: realtek: Clean up RTL821x ExtPage access - -Factor out RTL8211E extension page access code to -rtl821x_modify_ext_page() and clean up rtl8211e_config_init() - -Signed-off-by: Michael Klein -Reviewed-by: Andrew Lunn -Link: https://patch.msgid.link/20250504172916.243185-3-michael@fossekall.de -Signed-off-by: Paolo Abeni ---- - drivers/net/phy/realtek/realtek_main.c | 38 ++++++++++++++++---------- - 1 file changed, 23 insertions(+), 15 deletions(-) - ---- a/drivers/net/phy/realtek/realtek_main.c -+++ b/drivers/net/phy/realtek/realtek_main.c -@@ -26,7 +26,9 @@ - #define RTL821x_INSR 0x13 - - #define RTL821x_EXT_PAGE_SELECT 0x1e -+ - #define RTL821x_PAGE_SELECT 0x1f -+#define RTL821x_SET_EXT_PAGE 0x07 - - #define RTL8211F_PHYCR1 0x18 - #define RTL8211F_PHYCR2 0x19 -@@ -69,9 +71,12 @@ - #define RTL8211F_ALDPS_ENABLE BIT(2) - #define RTL8211F_ALDPS_XTAL_OFF BIT(12) - -+#define RTL8211E_RGMII_EXT_PAGE 0xa4 -+#define RTL8211E_RGMII_DELAY 0x1c - #define RTL8211E_CTRL_DELAY BIT(13) - #define RTL8211E_TX_DELAY BIT(12) - #define RTL8211E_RX_DELAY BIT(11) -+#define RTL8211E_DELAY_MASK GENMASK(13, 11) - - #define RTL8201F_ISR 0x1e - #define RTL8201F_ISR_ANERR BIT(15) -@@ -151,6 +156,21 @@ static int rtl821x_write_page(struct phy - return __phy_write(phydev, RTL821x_PAGE_SELECT, page); - } - -+static int rtl821x_modify_ext_page(struct phy_device *phydev, u16 ext_page, -+ u32 regnum, u16 mask, u16 set) -+{ -+ int oldpage, ret = 0; -+ -+ oldpage = phy_select_page(phydev, RTL821x_SET_EXT_PAGE); -+ if (oldpage >= 0) { -+ ret = __phy_write(phydev, RTL821x_EXT_PAGE_SELECT, ext_page); -+ if (ret == 0) -+ ret = __phy_modify(phydev, regnum, mask, set); -+ } -+ -+ return phy_restore_page(phydev, oldpage, ret); -+} -+ - static int rtl821x_probe(struct phy_device *phydev) - { - struct device *dev = &phydev->mdio.dev; -@@ -670,7 +690,6 @@ static int rtl8211f_led_hw_control_set(s - - static int rtl8211e_config_init(struct phy_device *phydev) - { -- int ret = 0, oldpage; - u16 val; - - /* enable TX/RX delay for rgmii-* modes, and disable them for rgmii. */ -@@ -700,20 +719,9 @@ static int rtl8211e_config_init(struct p - * 12 = RX Delay, 11 = TX Delay - * 10:0 = Test && debug settings reserved by realtek - */ -- oldpage = phy_select_page(phydev, 0x7); -- if (oldpage < 0) -- goto err_restore_page; -- -- ret = __phy_write(phydev, RTL821x_EXT_PAGE_SELECT, 0xa4); -- if (ret) -- goto err_restore_page; -- -- ret = __phy_modify(phydev, 0x1c, RTL8211E_CTRL_DELAY -- | RTL8211E_TX_DELAY | RTL8211E_RX_DELAY, -- val); -- --err_restore_page: -- return phy_restore_page(phydev, oldpage, ret); -+ return rtl821x_modify_ext_page(phydev, RTL8211E_RGMII_EXT_PAGE, -+ RTL8211E_RGMII_DELAY, -+ RTL8211E_DELAY_MASK, val); - } - - static int rtl8211b_suspend(struct phy_device *phydev) diff --git a/target/linux/generic/backport-6.18/781-23-v6.16-net-phy-realtek-add-RTL8211F-register-defines.patch b/target/linux/generic/backport-6.18/781-23-v6.16-net-phy-realtek-add-RTL8211F-register-defines.patch deleted file mode 100644 index 9116992832..0000000000 --- a/target/linux/generic/backport-6.18/781-23-v6.16-net-phy-realtek-add-RTL8211F-register-defines.patch +++ /dev/null @@ -1,139 +0,0 @@ -From 12d40df259e38851a0d973535e6023b33e2ea4f9 Mon Sep 17 00:00:00 2001 -From: Michael Klein -Date: Sun, 4 May 2025 19:29:13 +0200 -Subject: [PATCH] net: phy: realtek: add RTL8211F register defines - -Add some more defines for RTL8211F page and register numbers. - -Signed-off-by: Michael Klein -Reviewed-by: Andrew Lunn -Link: https://patch.msgid.link/20250504172916.243185-4-michael@fossekall.de -Signed-off-by: Paolo Abeni ---- - drivers/net/phy/realtek/realtek_main.c | 34 ++++++++++++++++++-------- - 1 file changed, 24 insertions(+), 10 deletions(-) - ---- a/drivers/net/phy/realtek/realtek_main.c -+++ b/drivers/net/phy/realtek/realtek_main.c -@@ -30,11 +30,14 @@ - #define RTL821x_PAGE_SELECT 0x1f - #define RTL821x_SET_EXT_PAGE 0x07 - -+/* RTL8211F PHY configuration */ -+#define RTL8211F_PHYCR_PAGE 0xa43 - #define RTL8211F_PHYCR1 0x18 - #define RTL8211F_PHYCR2 0x19 - #define RTL8211F_CLKOUT_EN BIT(0) - #define RTL8211F_PHYCR2_PHY_EEE_ENABLE BIT(5) - -+#define RTL8211F_INSR_PAGE 0xa43 - #define RTL8211F_INSR 0x1d - - /* RTL8211F WOL interrupt configuration */ -@@ -55,6 +58,8 @@ - #define RTL8211F_PHYSICAL_ADDR_WORD1 17 - #define RTL8211F_PHYSICAL_ADDR_WORD2 18 - -+/* RTL8211F LED configuration */ -+#define RTL8211F_LEDCR_PAGE 0xd04 - #define RTL8211F_LEDCR 0x10 - #define RTL8211F_LEDCR_MODE BIT(15) - #define RTL8211F_LEDCR_ACT_TXRX BIT(4) -@@ -64,7 +69,13 @@ - #define RTL8211F_LEDCR_MASK GENMASK(4, 0) - #define RTL8211F_LEDCR_SHIFT 5 - -+/* RTL8211F RGMII configuration */ -+#define RTL8211F_RGMII_PAGE 0xd08 -+ -+#define RTL8211F_TXCR 0x11 - #define RTL8211F_TX_DELAY BIT(8) -+ -+#define RTL8211F_RXCR 0x15 - #define RTL8211F_RX_DELAY BIT(3) - - #define RTL8211F_ALDPS_PLL_OFF BIT(1) -@@ -187,7 +198,7 @@ static int rtl821x_probe(struct phy_devi - return dev_err_probe(dev, PTR_ERR(priv->clk), - "failed to get phy clock\n"); - -- ret = phy_read_paged(phydev, 0xa43, RTL8211F_PHYCR1); -+ ret = phy_read_paged(phydev, RTL8211F_PHYCR_PAGE, RTL8211F_PHYCR1); - if (ret < 0) - return ret; - -@@ -197,7 +208,7 @@ static int rtl821x_probe(struct phy_devi - - priv->has_phycr2 = !(phy_id == RTL_8211FVD_PHYID); - if (priv->has_phycr2) { -- ret = phy_read_paged(phydev, 0xa43, RTL8211F_PHYCR2); -+ ret = phy_read_paged(phydev, RTL8211F_PHYCR_PAGE, RTL8211F_PHYCR2); - if (ret < 0) - return ret; - -@@ -233,7 +244,7 @@ static int rtl8211f_ack_interrupt(struct - { - int err; - -- err = phy_read_paged(phydev, 0xa43, RTL8211F_INSR); -+ err = phy_read_paged(phydev, RTL8211F_INSR_PAGE, RTL8211F_INSR); - - return (err < 0) ? err : 0; - } -@@ -376,7 +387,7 @@ static irqreturn_t rtl8211f_handle_inter - { - int irq_status; - -- irq_status = phy_read_paged(phydev, 0xa43, RTL8211F_INSR); -+ irq_status = phy_read_paged(phydev, RTL8211F_INSR_PAGE, RTL8211F_INSR); - if (irq_status < 0) { - phy_error(phydev); - return IRQ_NONE; -@@ -473,7 +484,7 @@ static int rtl8211f_config_init(struct p - u16 val_txdly, val_rxdly; - int ret; - -- ret = phy_modify_paged_changed(phydev, 0xa43, RTL8211F_PHYCR1, -+ ret = phy_modify_paged_changed(phydev, RTL8211F_PHYCR_PAGE, RTL8211F_PHYCR1, - RTL8211F_ALDPS_PLL_OFF | RTL8211F_ALDPS_ENABLE | RTL8211F_ALDPS_XTAL_OFF, - priv->phycr1); - if (ret < 0) { -@@ -507,7 +518,8 @@ static int rtl8211f_config_init(struct p - return 0; - } - -- ret = phy_modify_paged_changed(phydev, 0xd08, 0x11, RTL8211F_TX_DELAY, -+ ret = phy_modify_paged_changed(phydev, RTL8211F_RGMII_PAGE, -+ RTL8211F_TXCR, RTL8211F_TX_DELAY, - val_txdly); - if (ret < 0) { - dev_err(dev, "Failed to update the TX delay register\n"); -@@ -522,7 +534,8 @@ static int rtl8211f_config_init(struct p - str_enabled_disabled(val_txdly)); - } - -- ret = phy_modify_paged_changed(phydev, 0xd08, 0x15, RTL8211F_RX_DELAY, -+ ret = phy_modify_paged_changed(phydev, RTL8211F_RGMII_PAGE, -+ RTL8211F_RXCR, RTL8211F_RX_DELAY, - val_rxdly); - if (ret < 0) { - dev_err(dev, "Failed to update the RX delay register\n"); -@@ -538,14 +551,15 @@ static int rtl8211f_config_init(struct p - } - - /* Disable PHY-mode EEE so LPI is passed to the MAC */ -- ret = phy_modify_paged(phydev, 0xa43, RTL8211F_PHYCR2, -+ ret = phy_modify_paged(phydev, RTL8211F_PHYCR_PAGE, RTL8211F_PHYCR2, - RTL8211F_PHYCR2_PHY_EEE_ENABLE, 0); - if (ret) - return ret; - - if (priv->has_phycr2) { -- ret = phy_modify_paged(phydev, 0xa43, RTL8211F_PHYCR2, -- RTL8211F_CLKOUT_EN, priv->phycr2); -+ ret = phy_modify_paged(phydev, RTL8211F_PHYCR_PAGE, -+ RTL8211F_PHYCR2, RTL8211F_CLKOUT_EN, -+ priv->phycr2); - if (ret < 0) { - dev_err(dev, "clkout configuration failed: %pe\n", - ERR_PTR(ret)); diff --git a/target/linux/generic/backport-6.18/781-24-v6.16-net-phy-realtek-Group-RTL82-macro-definitions.patch b/target/linux/generic/backport-6.18/781-24-v6.16-net-phy-realtek-Group-RTL82-macro-definitions.patch deleted file mode 100644 index 0319a2b109..0000000000 --- a/target/linux/generic/backport-6.18/781-24-v6.16-net-phy-realtek-Group-RTL82-macro-definitions.patch +++ /dev/null @@ -1,123 +0,0 @@ -From 8c4d0172657c1f2d86b9c19172150abcd0e35c39 Mon Sep 17 00:00:00 2001 -From: Michael Klein -Date: Sun, 4 May 2025 19:29:14 +0200 -Subject: [PATCH] net: phy: realtek: Group RTL82* macro definitions - -Group macro definitions by PHY in lexicographic order. Within each PHY -block, definitions are order by page number and then register number. - -Signed-off-by: Michael Klein -Reviewed-by: Andrew Lunn -Link: https://patch.msgid.link/20250504172916.243185-5-michael@fossekall.de -Signed-off-by: Paolo Abeni ---- - drivers/net/phy/realtek/realtek_main.c | 72 +++++++++++++------------- - 1 file changed, 37 insertions(+), 35 deletions(-) - ---- a/drivers/net/phy/realtek/realtek_main.c -+++ b/drivers/net/phy/realtek/realtek_main.c -@@ -18,6 +18,16 @@ - - #include "realtek.h" - -+#define RTL8201F_IER 0x13 -+ -+#define RTL8201F_ISR 0x1e -+#define RTL8201F_ISR_ANERR BIT(15) -+#define RTL8201F_ISR_DUPLEX BIT(13) -+#define RTL8201F_ISR_LINK BIT(11) -+#define RTL8201F_ISR_MASK (RTL8201F_ISR_ANERR | \ -+ RTL8201F_ISR_DUPLEX | \ -+ RTL8201F_ISR_LINK) -+ - #define RTL821x_INER 0x12 - #define RTL8211B_INER_INIT 0x6400 - #define RTL8211E_INER_LINK_STATUS BIT(10) -@@ -30,9 +40,21 @@ - #define RTL821x_PAGE_SELECT 0x1f - #define RTL821x_SET_EXT_PAGE 0x07 - -+/* RTL8211E extension page 164/0xa4 */ -+#define RTL8211E_RGMII_EXT_PAGE 0xa4 -+#define RTL8211E_RGMII_DELAY 0x1c -+#define RTL8211E_CTRL_DELAY BIT(13) -+#define RTL8211E_TX_DELAY BIT(12) -+#define RTL8211E_RX_DELAY BIT(11) -+#define RTL8211E_DELAY_MASK GENMASK(13, 11) -+ - /* RTL8211F PHY configuration */ - #define RTL8211F_PHYCR_PAGE 0xa43 - #define RTL8211F_PHYCR1 0x18 -+#define RTL8211F_ALDPS_PLL_OFF BIT(1) -+#define RTL8211F_ALDPS_ENABLE BIT(2) -+#define RTL8211F_ALDPS_XTAL_OFF BIT(12) -+ - #define RTL8211F_PHYCR2 0x19 - #define RTL8211F_CLKOUT_EN BIT(0) - #define RTL8211F_PHYCR2_PHY_EEE_ENABLE BIT(5) -@@ -40,24 +62,6 @@ - #define RTL8211F_INSR_PAGE 0xa43 - #define RTL8211F_INSR 0x1d - --/* RTL8211F WOL interrupt configuration */ --#define RTL8211F_INTBCR_PAGE 0xd40 --#define RTL8211F_INTBCR 0x16 --#define RTL8211F_INTBCR_INTB_PMEB BIT(5) -- --/* RTL8211F WOL settings */ --#define RTL8211F_WOL_SETTINGS_PAGE 0xd8a --#define RTL8211F_WOL_SETTINGS_EVENTS 16 --#define RTL8211F_WOL_EVENT_MAGIC BIT(12) --#define RTL8211F_WOL_SETTINGS_STATUS 17 --#define RTL8211F_WOL_STATUS_RESET (BIT(15) | 0x1fff) -- --/* RTL8211F Unique phyiscal and multicast address (WOL) */ --#define RTL8211F_PHYSICAL_ADDR_PAGE 0xd8c --#define RTL8211F_PHYSICAL_ADDR_WORD0 16 --#define RTL8211F_PHYSICAL_ADDR_WORD1 17 --#define RTL8211F_PHYSICAL_ADDR_WORD2 18 -- - /* RTL8211F LED configuration */ - #define RTL8211F_LEDCR_PAGE 0xd04 - #define RTL8211F_LEDCR 0x10 -@@ -78,25 +82,23 @@ - #define RTL8211F_RXCR 0x15 - #define RTL8211F_RX_DELAY BIT(3) - --#define RTL8211F_ALDPS_PLL_OFF BIT(1) --#define RTL8211F_ALDPS_ENABLE BIT(2) --#define RTL8211F_ALDPS_XTAL_OFF BIT(12) -+/* RTL8211F WOL interrupt configuration */ -+#define RTL8211F_INTBCR_PAGE 0xd40 -+#define RTL8211F_INTBCR 0x16 -+#define RTL8211F_INTBCR_INTB_PMEB BIT(5) - --#define RTL8211E_RGMII_EXT_PAGE 0xa4 --#define RTL8211E_RGMII_DELAY 0x1c --#define RTL8211E_CTRL_DELAY BIT(13) --#define RTL8211E_TX_DELAY BIT(12) --#define RTL8211E_RX_DELAY BIT(11) --#define RTL8211E_DELAY_MASK GENMASK(13, 11) -+/* RTL8211F WOL settings */ -+#define RTL8211F_WOL_SETTINGS_PAGE 0xd8a -+#define RTL8211F_WOL_SETTINGS_EVENTS 16 -+#define RTL8211F_WOL_EVENT_MAGIC BIT(12) -+#define RTL8211F_WOL_SETTINGS_STATUS 17 -+#define RTL8211F_WOL_STATUS_RESET (BIT(15) | 0x1fff) - --#define RTL8201F_ISR 0x1e --#define RTL8201F_ISR_ANERR BIT(15) --#define RTL8201F_ISR_DUPLEX BIT(13) --#define RTL8201F_ISR_LINK BIT(11) --#define RTL8201F_ISR_MASK (RTL8201F_ISR_ANERR | \ -- RTL8201F_ISR_DUPLEX | \ -- RTL8201F_ISR_LINK) --#define RTL8201F_IER 0x13 -+/* RTL8211F Unique phyiscal and multicast address (WOL) */ -+#define RTL8211F_PHYSICAL_ADDR_PAGE 0xd8c -+#define RTL8211F_PHYSICAL_ADDR_WORD0 16 -+#define RTL8211F_PHYSICAL_ADDR_WORD1 17 -+#define RTL8211F_PHYSICAL_ADDR_WORD2 18 - - #define RTL822X_VND1_SERDES_OPTION 0x697a - #define RTL822X_VND1_SERDES_OPTION_MODE_MASK GENMASK(5, 0) diff --git a/target/linux/generic/backport-6.18/781-25-v6.16-net-phy-realtek-use-__set_bit-in-rtl8211f_led_hw_con.patch b/target/linux/generic/backport-6.18/781-25-v6.16-net-phy-realtek-use-__set_bit-in-rtl8211f_led_hw_con.patch deleted file mode 100644 index a9e3f9037d..0000000000 --- a/target/linux/generic/backport-6.18/781-25-v6.16-net-phy-realtek-use-__set_bit-in-rtl8211f_led_hw_con.patch +++ /dev/null @@ -1,42 +0,0 @@ -From be1cc96ddf82bb0c0a159751f73239d6d3e9594a Mon Sep 17 00:00:00 2001 -From: Michael Klein -Date: Sun, 4 May 2025 19:29:15 +0200 -Subject: [PATCH] net: phy: realtek: use __set_bit() in - rtl8211f_led_hw_control_get() - -rtl8211f_led_hw_control_get() does not need atomic bit operations, -replace set_bit() by __set_bit(). - -Signed-off-by: Michael Klein -Reviewed-by: Andrew Lunn -Link: https://patch.msgid.link/20250504172916.243185-6-michael@fossekall.de -Signed-off-by: Paolo Abeni ---- - drivers/net/phy/realtek/realtek_main.c | 10 +++++----- - 1 file changed, 5 insertions(+), 5 deletions(-) - ---- a/drivers/net/phy/realtek/realtek_main.c -+++ b/drivers/net/phy/realtek/realtek_main.c -@@ -659,17 +659,17 @@ static int rtl8211f_led_hw_control_get(s - val &= RTL8211F_LEDCR_MASK; - - if (val & RTL8211F_LEDCR_LINK_10) -- set_bit(TRIGGER_NETDEV_LINK_10, rules); -+ __set_bit(TRIGGER_NETDEV_LINK_10, rules); - - if (val & RTL8211F_LEDCR_LINK_100) -- set_bit(TRIGGER_NETDEV_LINK_100, rules); -+ __set_bit(TRIGGER_NETDEV_LINK_100, rules); - - if (val & RTL8211F_LEDCR_LINK_1000) -- set_bit(TRIGGER_NETDEV_LINK_1000, rules); -+ __set_bit(TRIGGER_NETDEV_LINK_1000, rules); - - if (val & RTL8211F_LEDCR_ACT_TXRX) { -- set_bit(TRIGGER_NETDEV_RX, rules); -- set_bit(TRIGGER_NETDEV_TX, rules); -+ __set_bit(TRIGGER_NETDEV_RX, rules); -+ __set_bit(TRIGGER_NETDEV_TX, rules); - } - - return 0; diff --git a/target/linux/generic/backport-6.18/781-26-v6.16-net-phy-realtek-Add-support-for-PHY-LEDs-on-RTL8211E.patch b/target/linux/generic/backport-6.18/781-26-v6.16-net-phy-realtek-Add-support-for-PHY-LEDs-on-RTL8211E.patch deleted file mode 100644 index a4b6450e92..0000000000 --- a/target/linux/generic/backport-6.18/781-26-v6.16-net-phy-realtek-Add-support-for-PHY-LEDs-on-RTL8211E.patch +++ /dev/null @@ -1,215 +0,0 @@ -From 708686132ba02659267c0cebcc414348ece389a5 Mon Sep 17 00:00:00 2001 -From: Michael Klein -Date: Sun, 4 May 2025 19:29:16 +0200 -Subject: [PATCH] net: phy: realtek: Add support for PHY LEDs on RTL8211E - -Like the RTL8211F, the RTL8211E PHY supports up to three LEDs. -Add netdev trigger support for them, too. - -Signed-off-by: Michael Klein -Reviewed-by: Andrew Lunn -Link: https://patch.msgid.link/20250504172916.243185-7-michael@fossekall.de -Signed-off-by: Paolo Abeni ---- - drivers/net/phy/realtek/realtek_main.c | 125 +++++++++++++++++++++++-- - 1 file changed, 119 insertions(+), 6 deletions(-) - ---- a/drivers/net/phy/realtek/realtek_main.c -+++ b/drivers/net/phy/realtek/realtek_main.c -@@ -40,6 +40,20 @@ - #define RTL821x_PAGE_SELECT 0x1f - #define RTL821x_SET_EXT_PAGE 0x07 - -+/* RTL8211E extension page 44/0x2c */ -+#define RTL8211E_LEDCR_EXT_PAGE 0x2c -+#define RTL8211E_LEDCR1 0x1a -+#define RTL8211E_LEDCR1_ACT_TXRX BIT(4) -+#define RTL8211E_LEDCR1_MASK BIT(4) -+#define RTL8211E_LEDCR1_SHIFT 1 -+ -+#define RTL8211E_LEDCR2 0x1c -+#define RTL8211E_LEDCR2_LINK_1000 BIT(2) -+#define RTL8211E_LEDCR2_LINK_100 BIT(1) -+#define RTL8211E_LEDCR2_LINK_10 BIT(0) -+#define RTL8211E_LEDCR2_MASK GENMASK(2, 0) -+#define RTL8211E_LEDCR2_SHIFT 4 -+ - /* RTL8211E extension page 164/0xa4 */ - #define RTL8211E_RGMII_EXT_PAGE 0xa4 - #define RTL8211E_RGMII_DELAY 0x1c -@@ -145,7 +159,8 @@ - #define RTL_8221B_VN_CG 0x001cc84a - #define RTL_8251B 0x001cc862 - --#define RTL8211F_LED_COUNT 3 -+/* RTL8211E and RTL8211F support up to three LEDs */ -+#define RTL8211x_LED_COUNT 3 - - MODULE_DESCRIPTION("Realtek PHY driver"); - MODULE_AUTHOR("Johnson Leung"); -@@ -169,6 +184,21 @@ static int rtl821x_write_page(struct phy - return __phy_write(phydev, RTL821x_PAGE_SELECT, page); - } - -+static int rtl821x_read_ext_page(struct phy_device *phydev, u16 ext_page, -+ u32 regnum) -+{ -+ int oldpage, ret = 0; -+ -+ oldpage = phy_select_page(phydev, RTL821x_SET_EXT_PAGE); -+ if (oldpage >= 0) { -+ ret = __phy_write(phydev, RTL821x_EXT_PAGE_SELECT, ext_page); -+ if (ret == 0) -+ ret = __phy_read(phydev, regnum); -+ } -+ -+ return phy_restore_page(phydev, oldpage, ret); -+} -+ - static int rtl821x_modify_ext_page(struct phy_device *phydev, u16 ext_page, - u32 regnum, u16 mask, u16 set) - { -@@ -608,7 +638,7 @@ static int rtl821x_resume(struct phy_dev - return 0; - } - --static int rtl8211f_led_hw_is_supported(struct phy_device *phydev, u8 index, -+static int rtl8211x_led_hw_is_supported(struct phy_device *phydev, u8 index, - unsigned long rules) - { - const unsigned long mask = BIT(TRIGGER_NETDEV_LINK_10) | -@@ -627,9 +657,11 @@ static int rtl8211f_led_hw_is_supported( - * rates and Active indication always at all three 10+100+1000 - * link rates. - * This code currently uses mode B only. -+ * -+ * RTL8211E PHY LED has one mode, which works like RTL8211F mode B. - */ - -- if (index >= RTL8211F_LED_COUNT) -+ if (index >= RTL8211x_LED_COUNT) - return -EINVAL; - - /* Filter out any other unsupported triggers. */ -@@ -648,7 +680,7 @@ static int rtl8211f_led_hw_control_get(s - { - int val; - -- if (index >= RTL8211F_LED_COUNT) -+ if (index >= RTL8211x_LED_COUNT) - return -EINVAL; - - val = phy_read_paged(phydev, 0xd04, RTL8211F_LEDCR); -@@ -681,7 +713,7 @@ static int rtl8211f_led_hw_control_set(s - const u16 mask = RTL8211F_LEDCR_MASK << (RTL8211F_LEDCR_SHIFT * index); - u16 reg = 0; - -- if (index >= RTL8211F_LED_COUNT) -+ if (index >= RTL8211x_LED_COUNT) - return -EINVAL; - - if (test_bit(TRIGGER_NETDEV_LINK_10, &rules)) -@@ -704,6 +736,84 @@ static int rtl8211f_led_hw_control_set(s - return phy_modify_paged(phydev, 0xd04, RTL8211F_LEDCR, mask, reg); - } - -+static int rtl8211e_led_hw_control_get(struct phy_device *phydev, u8 index, -+ unsigned long *rules) -+{ -+ int ret; -+ u16 cr1, cr2; -+ -+ if (index >= RTL8211x_LED_COUNT) -+ return -EINVAL; -+ -+ ret = rtl821x_read_ext_page(phydev, RTL8211E_LEDCR_EXT_PAGE, -+ RTL8211E_LEDCR1); -+ if (ret < 0) -+ return ret; -+ -+ cr1 = ret >> RTL8211E_LEDCR1_SHIFT * index; -+ if (cr1 & RTL8211E_LEDCR1_ACT_TXRX) { -+ __set_bit(TRIGGER_NETDEV_RX, rules); -+ __set_bit(TRIGGER_NETDEV_TX, rules); -+ } -+ -+ ret = rtl821x_read_ext_page(phydev, RTL8211E_LEDCR_EXT_PAGE, -+ RTL8211E_LEDCR2); -+ if (ret < 0) -+ return ret; -+ -+ cr2 = ret >> RTL8211E_LEDCR2_SHIFT * index; -+ if (cr2 & RTL8211E_LEDCR2_LINK_10) -+ __set_bit(TRIGGER_NETDEV_LINK_10, rules); -+ -+ if (cr2 & RTL8211E_LEDCR2_LINK_100) -+ __set_bit(TRIGGER_NETDEV_LINK_100, rules); -+ -+ if (cr2 & RTL8211E_LEDCR2_LINK_1000) -+ __set_bit(TRIGGER_NETDEV_LINK_1000, rules); -+ -+ return ret; -+} -+ -+static int rtl8211e_led_hw_control_set(struct phy_device *phydev, u8 index, -+ unsigned long rules) -+{ -+ const u16 cr1mask = -+ RTL8211E_LEDCR1_MASK << (RTL8211E_LEDCR1_SHIFT * index); -+ const u16 cr2mask = -+ RTL8211E_LEDCR2_MASK << (RTL8211E_LEDCR2_SHIFT * index); -+ u16 cr1 = 0, cr2 = 0; -+ int ret; -+ -+ if (index >= RTL8211x_LED_COUNT) -+ return -EINVAL; -+ -+ if (test_bit(TRIGGER_NETDEV_RX, &rules) || -+ test_bit(TRIGGER_NETDEV_TX, &rules)) { -+ cr1 |= RTL8211E_LEDCR1_ACT_TXRX; -+ } -+ -+ cr1 <<= RTL8211E_LEDCR1_SHIFT * index; -+ ret = rtl821x_modify_ext_page(phydev, RTL8211E_LEDCR_EXT_PAGE, -+ RTL8211E_LEDCR1, cr1mask, cr1); -+ if (ret < 0) -+ return ret; -+ -+ if (test_bit(TRIGGER_NETDEV_LINK_10, &rules)) -+ cr2 |= RTL8211E_LEDCR2_LINK_10; -+ -+ if (test_bit(TRIGGER_NETDEV_LINK_100, &rules)) -+ cr2 |= RTL8211E_LEDCR2_LINK_100; -+ -+ if (test_bit(TRIGGER_NETDEV_LINK_1000, &rules)) -+ cr2 |= RTL8211E_LEDCR2_LINK_1000; -+ -+ cr2 <<= RTL8211E_LEDCR2_SHIFT * index; -+ ret = rtl821x_modify_ext_page(phydev, RTL8211E_LEDCR_EXT_PAGE, -+ RTL8211E_LEDCR2, cr2mask, cr2); -+ -+ return ret; -+} -+ - static int rtl8211e_config_init(struct phy_device *phydev) - { - u16 val; -@@ -1479,6 +1589,9 @@ static struct phy_driver realtek_drvs[] - .resume = genphy_resume, - .read_page = rtl821x_read_page, - .write_page = rtl821x_write_page, -+ .led_hw_is_supported = rtl8211x_led_hw_is_supported, -+ .led_hw_control_get = rtl8211e_led_hw_control_get, -+ .led_hw_control_set = rtl8211e_led_hw_control_set, - }, { - PHY_ID_MATCH_EXACT(0x001cc916), - .name = "RTL8211F Gigabit Ethernet", -@@ -1494,7 +1607,7 @@ static struct phy_driver realtek_drvs[] - .read_page = rtl821x_read_page, - .write_page = rtl821x_write_page, - .flags = PHY_ALWAYS_CALL_SUSPEND, -- .led_hw_is_supported = rtl8211f_led_hw_is_supported, -+ .led_hw_is_supported = rtl8211x_led_hw_is_supported, - .led_hw_control_get = rtl8211f_led_hw_control_get, - .led_hw_control_set = rtl8211f_led_hw_control_set, - }, { diff --git a/target/linux/generic/backport-6.18/781-27-v6.16-net-phy-realtek-add-RTL8127-internal-PHY.patch b/target/linux/generic/backport-6.18/781-27-v6.16-net-phy-realtek-add-RTL8127-internal-PHY.patch deleted file mode 100644 index 04c631dfe5..0000000000 --- a/target/linux/generic/backport-6.18/781-27-v6.16-net-phy-realtek-add-RTL8127-internal-PHY.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 83d9623161283f5f6883ee3fdb88ef2177b8a5f1 Mon Sep 17 00:00:00 2001 -From: ChunHao Lin -Date: Fri, 16 May 2025 13:56:22 +0800 -Subject: [PATCH] net: phy: realtek: add RTL8127-internal PHY - -RTL8127-internal PHY is RTL8261C which is a integrated 10Gbps PHY with ID -0x001cc890. It follows the code path of RTL8125/RTL8126 internal NBase-T -PHY. - -Signed-off-by: ChunHao Lin -Reviewed-by: Andrew Lunn -Link: https://patch.msgid.link/20250516055622.3772-1-hau@realtek.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/realtek/realtek_main.c | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/drivers/net/phy/realtek/realtek_main.c -+++ b/drivers/net/phy/realtek/realtek_main.c -@@ -158,6 +158,7 @@ - #define RTL_8221B_VB_CG 0x001cc849 - #define RTL_8221B_VN_CG 0x001cc84a - #define RTL_8251B 0x001cc862 -+#define RTL_8261C 0x001cc890 - - /* RTL8211E and RTL8211F support up to three LEDs */ - #define RTL8211x_LED_COUNT 3 -@@ -1370,6 +1371,7 @@ static int rtl_internal_nbaset_match_phy - case RTL_GENERIC_PHYID: - case RTL_8221B: - case RTL_8251B: -+ case RTL_8261C: - case 0x001cc841: - break; - default: diff --git a/target/linux/generic/backport-6.18/781-28-v6.18-net-phy-realtek-convert-RTL8226-CG-to-c45-only.patch b/target/linux/generic/backport-6.18/781-28-v6.18-net-phy-realtek-convert-RTL8226-CG-to-c45-only.patch deleted file mode 100644 index 43f2c7b82c..0000000000 --- a/target/linux/generic/backport-6.18/781-28-v6.18-net-phy-realtek-convert-RTL8226-CG-to-c45-only.patch +++ /dev/null @@ -1,169 +0,0 @@ -From 34167f1a024d2c5abae0b0325a6d0b8257160f86 Mon Sep 17 00:00:00 2001 -From: Markus Stockhausen -Date: Wed, 13 Aug 2025 01:44:07 -0400 -Subject: net: phy: realtek: convert RTL8226-CG to c45 only - -Short: Convert the RTL8226-CG to c45 so it can be used in its -Realtek based ecosystems. - -Long: The RTL8226-CG can be mainly found on devices of the -Realtek Otto switch platform. Devices like the Zyxel XGS1210-12 -are based on it. These implement a hardware based phy polling -in the background to update SoC status registers. - -The hardware provides 4 smi busses where phys are attached to. -For each bus one can decide if it is polled in c45 or c22 mode. -See https://svanheule.net/realtek/longan/register/smi_glb_ctrl -With this setting the register access will be limited by the -hardware. This is very complex (including caching and special -c45-over-c22 handling). But basically it boils down to "enable -protocol x and SoC will disable register access via protocol y". - -Mainline already gained support for the rtl9300 mdio driver -in commit 24e31e474769 ("net: mdio: Add RTL9300 MDIO driver"). - -It covers the basic features, but a lot effort is still needed -to understand hardware properly. So it runs a simple setup by -selecting the proper bus mode during startup. - - /* Put the interfaces into C45 mode if required */ - glb_ctrl_mask = GENMASK(19, 16); - for (i = 0; i < MAX_SMI_BUSSES; i++) - if (priv->smi_bus_is_c45[i]) - glb_ctrl_val |= GLB_CTRL_INTF_SEL(i); - ... - err = regmap_update_bits(regmap, SMI_GLB_CTRL, - glb_ctrl_mask, glb_ctrl_val); - -To avoid complex coding later on, it limits access by only -providing either c22 or c45: - - bus->name = "Realtek Switch MDIO Bus"; - if (priv->smi_bus_is_c45[mdio_bus]) { - bus->read_c45 = rtl9300_mdio_read_c45; - bus->write_c45 = rtl9300_mdio_write_c45; - } else { - bus->read = rtl9300_mdio_read_c22; - bus->write = rtl9300_mdio_write_c22; - } - -Because of these limitations the existing RTL8226 phy driver -is not working at all on Realtek switches. Convert the driver -to c45-only. - -Luckily the RTL8226 seems to support proper MDIO_PMA_EXTABLE -flags. So standard function genphy_c45_pma_read_abilities() can -call genphy_c45_pma_read_ext_abilities() and 10/100/1000 is -populated right. Thus conversion is straight forward. - -Outputs before - REMARK: For this a "hacked" bus was used that -toggles the mode for each c22/c45 access. But that is slow and -produces unstable data in the SoC status registers). - -Settings for lan9: - Supported ports: [ TP MII ] - Supported link modes: 10baseT/Half 10baseT/Full - 100baseT/Half 100baseT/Full - 1000baseT/Full - 2500baseT/Full - Supported pause frame use: Symmetric Receive-only - Supports auto-negotiation: Yes - Supported FEC modes: Not reported - Advertised link modes: 10baseT/Half 10baseT/Full - 100baseT/Half 100baseT/Full - 1000baseT/Full - 2500baseT/Full - Advertised pause frame use: Symmetric Receive-only - Advertised auto-negotiation: Yes - Advertised FEC modes: Not reported - Speed: Unknown! - Duplex: Unknown! (255) - Port: Twisted Pair - PHYAD: 24 - Transceiver: external - Auto-negotiation: on - MDI-X: Unknown - Supports Wake-on: d - Wake-on: d - Link detected: no - -Outputs with this commit: - -Settings for lan9: - Supported ports: [ TP ] - Supported link modes: 10baseT/Half 10baseT/Full - 100baseT/Half 100baseT/Full - 1000baseT/Full - 2500baseT/Full - Supported pause frame use: Symmetric Receive-only - Supports auto-negotiation: Yes - Supported FEC modes: Not reported - Advertised link modes: 10baseT/Half 10baseT/Full - 100baseT/Half 100baseT/Full - 1000baseT/Full - 2500baseT/Full - Advertised pause frame use: Symmetric Receive-only - Advertised auto-negotiation: Yes - Advertised FEC modes: Not reported - Speed: Unknown! - Duplex: Unknown! (255) - Port: Twisted Pair - PHYAD: 24 - Transceiver: external - Auto-negotiation: on - MDI-X: Unknown - Supports Wake-on: d - Wake-on: d - Link detected: no - -Signed-off-by: Markus Stockhausen -Link: https://patch.msgid.link/20250813054407.1108285-1-markus.stockhausen@gmx.de -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/realtek/realtek_main.c | 28 +++++++++++++++++++++------- - 1 file changed, 21 insertions(+), 7 deletions(-) - ---- a/drivers/net/phy/realtek/realtek_main.c -+++ b/drivers/net/phy/realtek/realtek_main.c -@@ -1274,6 +1274,21 @@ static int rtl822x_c45_read_status(struc - return 0; - } - -+static int rtl822x_c45_soft_reset(struct phy_device *phydev) -+{ -+ int ret, val; -+ -+ ret = phy_modify_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_CTRL1, -+ MDIO_CTRL1_RESET, MDIO_CTRL1_RESET); -+ if (ret < 0) -+ return ret; -+ -+ return phy_read_mmd_poll_timeout(phydev, MDIO_MMD_PMAPMD, -+ MDIO_CTRL1, val, -+ !(val & MDIO_CTRL1_RESET), -+ 5000, 100000, true); -+} -+ - static int rtl822xb_c45_read_status(struct phy_device *phydev) - { - int ret; -@@ -1660,13 +1675,12 @@ static struct phy_driver realtek_drvs[] - }, { - PHY_ID_MATCH_EXACT(0x001cc838), - .name = "RTL8226-CG 2.5Gbps PHY", -- .get_features = rtl822x_get_features, -- .config_aneg = rtl822x_config_aneg, -- .read_status = rtl822x_read_status, -- .suspend = genphy_suspend, -- .resume = rtlgen_resume, -- .read_page = rtl821x_read_page, -- .write_page = rtl821x_write_page, -+ .soft_reset = rtl822x_c45_soft_reset, -+ .get_features = rtl822x_c45_get_features, -+ .config_aneg = rtl822x_c45_config_aneg, -+ .read_status = rtl822x_c45_read_status, -+ .suspend = genphy_c45_pma_suspend, -+ .resume = rtlgen_c45_resume, - }, { - PHY_ID_MATCH_EXACT(0x001cc848), - .name = "RTL8226B-CG_RTL8221B-CG 2.5Gbps PHY", diff --git a/target/linux/generic/backport-6.18/781-29-v6.18-net-phy-realtek-enable-serdes-option-mode-for-RTL8226-CG.patch b/target/linux/generic/backport-6.18/781-29-v6.18-net-phy-realtek-enable-serdes-option-mode-for-RTL8226-CG.patch deleted file mode 100644 index 9ffb260df1..0000000000 --- a/target/linux/generic/backport-6.18/781-29-v6.18-net-phy-realtek-enable-serdes-option-mode-for-RTL8226-CG.patch +++ /dev/null @@ -1,92 +0,0 @@ -From 3a752e67800106a5c42d802d67e06c60aa71d07b Mon Sep 17 00:00:00 2001 -From: Markus Stockhausen -Date: Fri, 15 Aug 2025 04:20:09 -0400 -Subject: net: phy: realtek: enable serdes option mode for RTL8226-CG - -The RTL8226-CG can make use of the serdes option mode feature to -dynamically switch between SGMII and 2500base-X. From what is -known the setup sequence is much simpler with no magic values. - -Convert the exiting config_init() into a helper that configures -the PHY depending on generation 1 or 2. Call the helper from two -separated new config_init() functions. - -Finally convert the phy_driver specs of the RTL8226-CG to make -use of the new configuration and switch over to the extended -read_status() function to dynamically change the interface -according to the serdes mode. - -Remark! The logic could be simpler if the serdes mode could be -set before all other generation 2 magic values. Due to missing -RTL8221B test hardware the mmd command order was kept. - -Tested on Zyxel XGS1210-12. - -Signed-off-by: Markus Stockhausen -Link: https://patch.msgid.link/20250815082009.3678865-1-markus.stockhausen@gmx.de -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/realtek/realtek_main.c | 26 ++++++++++++++++++++------ - 1 file changed, 20 insertions(+), 6 deletions(-) - ---- a/drivers/net/phy/realtek/realtek_main.c -+++ b/drivers/net/phy/realtek/realtek_main.c -@@ -1032,7 +1032,7 @@ static int rtl822x_probe(struct phy_devi - return 0; - } - --static int rtl822xb_config_init(struct phy_device *phydev) -+static int rtl822x_set_serdes_option_mode(struct phy_device *phydev, bool gen1) - { - bool has_2500, has_sgmii; - u16 mode; -@@ -1067,15 +1067,18 @@ static int rtl822xb_config_init(struct p - /* the following sequence with magic numbers sets up the SerDes - * option mode - */ -- ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x75f3, 0); -- if (ret < 0) -- return ret; -+ -+ if (!gen1) { -+ ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x75f3, 0); -+ if (ret < 0) -+ return ret; -+ } - - ret = phy_modify_mmd_changed(phydev, MDIO_MMD_VEND1, - RTL822X_VND1_SERDES_OPTION, - RTL822X_VND1_SERDES_OPTION_MODE_MASK, - mode); -- if (ret < 0) -+ if (gen1 || ret < 0) - return ret; - - ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x6a04, 0x0503); -@@ -1089,6 +1092,16 @@ static int rtl822xb_config_init(struct p - return phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x6f11, 0x8020); - } - -+static int rtl822x_config_init(struct phy_device *phydev) -+{ -+ return rtl822x_set_serdes_option_mode(phydev, true); -+} -+ -+static int rtl822xb_config_init(struct phy_device *phydev) -+{ -+ return rtl822x_set_serdes_option_mode(phydev, false); -+} -+ - static int rtl822xb_get_rate_matching(struct phy_device *phydev, - phy_interface_t iface) - { -@@ -1678,7 +1691,8 @@ static struct phy_driver realtek_drvs[] - .soft_reset = rtl822x_c45_soft_reset, - .get_features = rtl822x_c45_get_features, - .config_aneg = rtl822x_c45_config_aneg, -- .read_status = rtl822x_c45_read_status, -+ .config_init = rtl822x_config_init, -+ .read_status = rtl822xb_c45_read_status, - .suspend = genphy_c45_pma_suspend, - .resume = rtlgen_c45_resume, - }, { diff --git a/target/linux/generic/backport-6.18/782-01-v6.16-net-phy-pass-PHY-driver-to-.match_phy_device-OP.patch b/target/linux/generic/backport-6.18/782-01-v6.16-net-phy-pass-PHY-driver-to-.match_phy_device-OP.patch deleted file mode 100644 index c22231ea66..0000000000 --- a/target/linux/generic/backport-6.18/782-01-v6.16-net-phy-pass-PHY-driver-to-.match_phy_device-OP.patch +++ /dev/null @@ -1,303 +0,0 @@ -From 31afd6bc55cc0093c3e5b0a368319e423d4de8ea Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Sat, 17 May 2025 22:13:45 +0200 -Subject: [PATCH] net: phy: pass PHY driver to .match_phy_device OP - -Pass PHY driver pointer to .match_phy_device OP in addition to phydev. -Having access to the PHY driver struct might be useful to check the -PHY ID of the driver is being matched for in case the PHY ID scanned in -the phydev is not consistent. - -A scenario for this is a PHY that change PHY ID after a firmware is -loaded, in such case, the PHY ID stored in PHY device struct is not -valid anymore and PHY will manually scan the ID in the match_phy_device -function. - -Having the PHY driver info is also useful for those PHY driver that -implement multiple simple .match_phy_device OP to match specific MMD PHY -ID. With this extra info if the parsing logic is the same, the matching -function can be generalized by using the phy_id in the PHY driver -instead of hardcoding. - -Rust wrapper callback is updated to align to the new match_phy_device -arguments. - -Suggested-by: Russell King (Oracle) -Reviewed-by: Russell King (Oracle) -Signed-off-by: Christian Marangi -Reviewed-by: Benno Lossin # for Rust -Reviewed-by: FUJITA Tomonori -Link: https://patch.msgid.link/20250517201353.5137-2-ansuelsmth@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/bcm87xx.c | 6 ++++-- - drivers/net/phy/icplus.c | 6 ++++-- - drivers/net/phy/marvell10g.c | 12 ++++++++---- - drivers/net/phy/micrel.c | 6 ++++-- - drivers/net/phy/nxp-c45-tja11xx.c | 12 ++++++++---- - drivers/net/phy/nxp-tja11xx.c | 6 ++++-- - drivers/net/phy/phy_device.c | 2 +- - drivers/net/phy/realtek/realtek_main.c | 27 +++++++++++++++++--------- - drivers/net/phy/teranetics.c | 3 ++- - include/linux/phy.h | 3 ++- - rust/kernel/net/phy.rs | 1 + - 11 files changed, 56 insertions(+), 28 deletions(-) - ---- a/drivers/net/phy/bcm87xx.c -+++ b/drivers/net/phy/bcm87xx.c -@@ -185,12 +185,14 @@ static irqreturn_t bcm87xx_handle_interr - return IRQ_HANDLED; - } - --static int bcm8706_match_phy_device(struct phy_device *phydev) -+static int bcm8706_match_phy_device(struct phy_device *phydev, -+ const struct phy_driver *phydrv) - { - return phydev->c45_ids.device_ids[4] == PHY_ID_BCM8706; - } - --static int bcm8727_match_phy_device(struct phy_device *phydev) -+static int bcm8727_match_phy_device(struct phy_device *phydev, -+ const struct phy_driver *phydrv) - { - return phydev->c45_ids.device_ids[4] == PHY_ID_BCM8727; - } ---- a/drivers/net/phy/icplus.c -+++ b/drivers/net/phy/icplus.c -@@ -520,12 +520,14 @@ static int ip101a_g_match_phy_device(str - return ip101a == !ret; - } - --static int ip101a_match_phy_device(struct phy_device *phydev) -+static int ip101a_match_phy_device(struct phy_device *phydev, -+ const struct phy_driver *phydrv) - { - return ip101a_g_match_phy_device(phydev, true); - } - --static int ip101g_match_phy_device(struct phy_device *phydev) -+static int ip101g_match_phy_device(struct phy_device *phydev, -+ const struct phy_driver *phydrv) - { - return ip101a_g_match_phy_device(phydev, false); - } ---- a/drivers/net/phy/marvell10g.c -+++ b/drivers/net/phy/marvell10g.c -@@ -1284,7 +1284,8 @@ static int mv3310_get_number_of_ports(st - return ret + 1; - } - --static int mv3310_match_phy_device(struct phy_device *phydev) -+static int mv3310_match_phy_device(struct phy_device *phydev, -+ const struct phy_driver *phydrv) - { - if ((phydev->c45_ids.device_ids[MDIO_MMD_PMAPMD] & - MARVELL_PHY_ID_MASK) != MARVELL_PHY_ID_88X3310) -@@ -1293,7 +1294,8 @@ static int mv3310_match_phy_device(struc - return mv3310_get_number_of_ports(phydev) == 1; - } - --static int mv3340_match_phy_device(struct phy_device *phydev) -+static int mv3340_match_phy_device(struct phy_device *phydev, -+ const struct phy_driver *phydrv) - { - if ((phydev->c45_ids.device_ids[MDIO_MMD_PMAPMD] & - MARVELL_PHY_ID_MASK) != MARVELL_PHY_ID_88X3310) -@@ -1317,12 +1319,14 @@ static int mv211x_match_phy_device(struc - return !!(val & MDIO_PCS_SPEED_5G) == has_5g; - } - --static int mv2110_match_phy_device(struct phy_device *phydev) -+static int mv2110_match_phy_device(struct phy_device *phydev, -+ const struct phy_driver *phydrv) - { - return mv211x_match_phy_device(phydev, true); - } - --static int mv2111_match_phy_device(struct phy_device *phydev) -+static int mv2111_match_phy_device(struct phy_device *phydev, -+ const struct phy_driver *phydrv) - { - return mv211x_match_phy_device(phydev, false); - } ---- a/drivers/net/phy/micrel.c -+++ b/drivers/net/phy/micrel.c -@@ -768,7 +768,8 @@ static int ksz8051_ksz8795_match_phy_dev - return !ret; - } - --static int ksz8051_match_phy_device(struct phy_device *phydev) -+static int ksz8051_match_phy_device(struct phy_device *phydev, -+ const struct phy_driver *phydrv) - { - return ksz8051_ksz8795_match_phy_device(phydev, true); - } -@@ -888,7 +889,8 @@ static int ksz8061_config_init(struct ph - return kszphy_config_init(phydev); - } - --static int ksz8795_match_phy_device(struct phy_device *phydev) -+static int ksz8795_match_phy_device(struct phy_device *phydev, -+ const struct phy_driver *phydrv) - { - return ksz8051_ksz8795_match_phy_device(phydev, false); - } ---- a/drivers/net/phy/nxp-c45-tja11xx.c -+++ b/drivers/net/phy/nxp-c45-tja11xx.c -@@ -1944,13 +1944,15 @@ static int nxp_c45_macsec_ability(struct - return macsec_ability; - } - --static int tja1103_match_phy_device(struct phy_device *phydev) -+static int tja1103_match_phy_device(struct phy_device *phydev, -+ const struct phy_driver *phydrv) - { - return phy_id_compare(phydev->phy_id, PHY_ID_TJA_1103, PHY_ID_MASK) && - !nxp_c45_macsec_ability(phydev); - } - --static int tja1104_match_phy_device(struct phy_device *phydev) -+static int tja1104_match_phy_device(struct phy_device *phydev, -+ const struct phy_driver *phydrv) - { - return phy_id_compare(phydev->phy_id, PHY_ID_TJA_1103, PHY_ID_MASK) && - nxp_c45_macsec_ability(phydev); ---- a/drivers/net/phy/nxp-tja11xx.c -+++ b/drivers/net/phy/nxp-tja11xx.c -@@ -646,12 +646,14 @@ static int tja1102_match_phy_device(stru - return !ret; - } - --static int tja1102_p0_match_phy_device(struct phy_device *phydev) -+static int tja1102_p0_match_phy_device(struct phy_device *phydev, -+ const struct phy_driver *phydrv) - { - return tja1102_match_phy_device(phydev, true); - } - --static int tja1102_p1_match_phy_device(struct phy_device *phydev) -+static int tja1102_p1_match_phy_device(struct phy_device *phydev, -+ const struct phy_driver *phydrv) - { - return tja1102_match_phy_device(phydev, false); - } ---- a/drivers/net/phy/phy_device.c -+++ b/drivers/net/phy/phy_device.c -@@ -600,7 +600,7 @@ static int phy_bus_match(struct device * - return 0; - - if (phydrv->match_phy_device) -- return phydrv->match_phy_device(phydev); -+ return phydrv->match_phy_device(phydev, phydrv); - - if (phydev->is_c45) { - for (i = 1; i < num_ids; i++) { ---- a/drivers/net/phy/realtek/realtek_main.c -+++ b/drivers/net/phy/realtek/realtek_main.c -@@ -1343,13 +1343,15 @@ static bool rtlgen_supports_mmd(struct p - return val > 0; - } - --static int rtlgen_match_phy_device(struct phy_device *phydev) -+static int rtlgen_match_phy_device(struct phy_device *phydev, -+ const struct phy_driver *phydrv) - { - return phydev->phy_id == RTL_GENERIC_PHYID && - !rtlgen_supports_2_5gbps(phydev); - } - --static int rtl8226_match_phy_device(struct phy_device *phydev) -+static int rtl8226_match_phy_device(struct phy_device *phydev, -+ const struct phy_driver *phydrv) - { - return phydev->phy_id == RTL_GENERIC_PHYID && - rtlgen_supports_2_5gbps(phydev) && -@@ -1365,32 +1367,38 @@ static int rtlgen_is_c45_match(struct ph - return !is_c45 && (id == phydev->phy_id); - } - --static int rtl8221b_match_phy_device(struct phy_device *phydev) -+static int rtl8221b_match_phy_device(struct phy_device *phydev, -+ const struct phy_driver *phydrv) - { - return phydev->phy_id == RTL_8221B && rtlgen_supports_mmd(phydev); - } - --static int rtl8221b_vb_cg_c22_match_phy_device(struct phy_device *phydev) -+static int rtl8221b_vb_cg_c22_match_phy_device(struct phy_device *phydev, -+ const struct phy_driver *phydrv) - { - return rtlgen_is_c45_match(phydev, RTL_8221B_VB_CG, false); - } - --static int rtl8221b_vb_cg_c45_match_phy_device(struct phy_device *phydev) -+static int rtl8221b_vb_cg_c45_match_phy_device(struct phy_device *phydev, -+ const struct phy_driver *phydrv) - { - return rtlgen_is_c45_match(phydev, RTL_8221B_VB_CG, true); - } - --static int rtl8221b_vn_cg_c22_match_phy_device(struct phy_device *phydev) -+static int rtl8221b_vn_cg_c22_match_phy_device(struct phy_device *phydev, -+ const struct phy_driver *phydrv) - { - return rtlgen_is_c45_match(phydev, RTL_8221B_VN_CG, false); - } - --static int rtl8221b_vn_cg_c45_match_phy_device(struct phy_device *phydev) -+static int rtl8221b_vn_cg_c45_match_phy_device(struct phy_device *phydev, -+ const struct phy_driver *phydrv) - { - return rtlgen_is_c45_match(phydev, RTL_8221B_VN_CG, true); - } - --static int rtl_internal_nbaset_match_phy_device(struct phy_device *phydev) -+static int rtl_internal_nbaset_match_phy_device(struct phy_device *phydev, -+ const struct phy_driver *phydrv) - { - if (phydev->is_c45) - return false; -@@ -1409,7 +1417,8 @@ static int rtl_internal_nbaset_match_phy - return rtlgen_supports_2_5gbps(phydev) && !rtlgen_supports_mmd(phydev); - } - --static int rtl8251b_c45_match_phy_device(struct phy_device *phydev) -+static int rtl8251b_c45_match_phy_device(struct phy_device *phydev, -+ const struct phy_driver *phydrv) - { - return rtlgen_is_c45_match(phydev, RTL_8251B, true); - } ---- a/drivers/net/phy/teranetics.c -+++ b/drivers/net/phy/teranetics.c -@@ -67,7 +67,8 @@ static int teranetics_read_status(struct - return 0; - } - --static int teranetics_match_phy_device(struct phy_device *phydev) -+static int teranetics_match_phy_device(struct phy_device *phydev, -+ const struct phy_driver *phydrv) - { - return phydev->c45_ids.device_ids[3] == PHY_ID_TN2020; - } ---- a/include/linux/phy.h -+++ b/include/linux/phy.h -@@ -1045,7 +1045,8 @@ struct phy_driver { - * driver for the given phydev. If NULL, matching is based on - * phy_id and phy_id_mask. - */ -- int (*match_phy_device)(struct phy_device *phydev); -+ int (*match_phy_device)(struct phy_device *phydev, -+ const struct phy_driver *phydrv); - - /** - * @set_wol: Some devices (e.g. qnap TS-119P II) require PHY ---- a/rust/kernel/net/phy.rs -+++ b/rust/kernel/net/phy.rs -@@ -421,6 +421,7 @@ impl Adapter { - /// `phydev` must be passed by the corresponding callback in `phy_driver`. - unsafe extern "C" fn match_phy_device_callback( - phydev: *mut bindings::phy_device, -+ _phydrv: *const bindings::phy_driver, - ) -> crate::ffi::c_int { - // SAFETY: This callback is called only in contexts - // where we hold `phy_device->lock`, so the accessors on diff --git a/target/linux/generic/backport-6.18/782-04-v6.16-net-phy-introduce-genphy_match_phy_device.patch b/target/linux/generic/backport-6.18/782-04-v6.16-net-phy-introduce-genphy_match_phy_device.patch deleted file mode 100644 index fed9d3c11f..0000000000 --- a/target/linux/generic/backport-6.18/782-04-v6.16-net-phy-introduce-genphy_match_phy_device.patch +++ /dev/null @@ -1,109 +0,0 @@ -From d6c45707ac84c2d9f274ece1cea4dddb97996bde Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Sat, 17 May 2025 22:13:48 +0200 -Subject: [PATCH 4/5] net: phy: introduce genphy_match_phy_device() - -Introduce new API, genphy_match_phy_device(), to provide a way to check -to match a PHY driver for a PHY device based on the info stored in the -PHY device struct. - -The function generalize the logic used in phy_bus_match() to check the -PHY ID whether if C45 or C22 ID should be used for matching. - -This is useful for custom .match_phy_device function that wants to use -the generic logic under some condition. (example a PHY is already setup -and provide the correct PHY ID) - -Reviewed-by: Russell King (Oracle) -Signed-off-by: Christian Marangi -Link: https://patch.msgid.link/20250517201353.5137-5-ansuelsmth@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/phy_device.c | 52 +++++++++++++++++++++++++----------- - include/linux/phy.h | 3 +++ - 2 files changed, 40 insertions(+), 15 deletions(-) - ---- a/drivers/net/phy/phy_device.c -+++ b/drivers/net/phy/phy_device.c -@@ -589,20 +589,26 @@ static int phy_scan_fixups(struct phy_de - return 0; - } - --static int phy_bus_match(struct device *dev, const struct device_driver *drv) -+/** -+ * genphy_match_phy_device - match a PHY device with a PHY driver -+ * @phydev: target phy_device struct -+ * @phydrv: target phy_driver struct -+ * -+ * Description: Checks whether the given PHY device matches the specified -+ * PHY driver. For Clause 45 PHYs, iterates over the available device -+ * identifiers and compares them against the driver's expected PHY ID, -+ * applying the provided mask. For Clause 22 PHYs, a direct ID comparison -+ * is performed. -+ * -+ * Return: 1 if the PHY device matches the driver, 0 otherwise. -+ */ -+int genphy_match_phy_device(struct phy_device *phydev, -+ const struct phy_driver *phydrv) - { -- struct phy_device *phydev = to_phy_device(dev); -- const struct phy_driver *phydrv = to_phy_driver(drv); -- const int num_ids = ARRAY_SIZE(phydev->c45_ids.device_ids); -- int i; -- -- if (!(phydrv->mdiodrv.flags & MDIO_DEVICE_IS_PHY)) -- return 0; -- -- if (phydrv->match_phy_device) -- return phydrv->match_phy_device(phydev, phydrv); -- - if (phydev->is_c45) { -+ const int num_ids = ARRAY_SIZE(phydev->c45_ids.device_ids); -+ int i; -+ - for (i = 1; i < num_ids; i++) { - if (phydev->c45_ids.device_ids[i] == 0xffffffff) - continue; -@@ -611,11 +617,27 @@ static int phy_bus_match(struct device * - phydrv->phy_id, phydrv->phy_id_mask)) - return 1; - } -+ - return 0; -- } else { -- return phy_id_compare(phydev->phy_id, phydrv->phy_id, -- phydrv->phy_id_mask); - } -+ -+ return phy_id_compare(phydev->phy_id, phydrv->phy_id, -+ phydrv->phy_id_mask); -+} -+EXPORT_SYMBOL_GPL(genphy_match_phy_device); -+ -+static int phy_bus_match(struct device *dev, const struct device_driver *drv) -+{ -+ struct phy_device *phydev = to_phy_device(dev); -+ const struct phy_driver *phydrv = to_phy_driver(drv); -+ -+ if (!(phydrv->mdiodrv.flags & MDIO_DEVICE_IS_PHY)) -+ return 0; -+ -+ if (phydrv->match_phy_device) -+ return phydrv->match_phy_device(phydev, phydrv); -+ -+ return genphy_match_phy_device(phydev, phydrv); - } - - static ssize_t ---- a/include/linux/phy.h -+++ b/include/linux/phy.h -@@ -1963,6 +1963,9 @@ char *phy_attached_info_irq(struct phy_d - __malloc; - void phy_attached_info(struct phy_device *phydev); - -+int genphy_match_phy_device(struct phy_device *phydev, -+ const struct phy_driver *phydrv); -+ - /* Clause 22 PHY */ - int genphy_read_abilities(struct phy_device *phydev); - int genphy_setup_forced(struct phy_device *phydev); diff --git a/target/linux/generic/backport-6.18/782-05-v6.16-net-phy-Add-support-for-Aeonsemi-AS21xxx-PHYs.patch b/target/linux/generic/backport-6.18/782-05-v6.16-net-phy-Add-support-for-Aeonsemi-AS21xxx-PHYs.patch deleted file mode 100644 index f1bcb35e66..0000000000 --- a/target/linux/generic/backport-6.18/782-05-v6.16-net-phy-Add-support-for-Aeonsemi-AS21xxx-PHYs.patch +++ /dev/null @@ -1,1180 +0,0 @@ -From 830877d89edcd834e4b4d0fcc021ff619d89505e Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Sat, 17 May 2025 22:13:49 +0200 -Subject: [PATCH 5/5] net: phy: Add support for Aeonsemi AS21xxx PHYs - -Add support for Aeonsemi AS21xxx 10G C45 PHYs. These PHYs integrate -an IPC to setup some configuration and require special handling to -sync with the parity bit. The parity bit is a way the IPC use to -follow correct order of command sent. - -Supported PHYs AS21011JB1, AS21011PB1, AS21010JB1, AS21010PB1, -AS21511JB1, AS21511PB1, AS21510JB1, AS21510PB1, AS21210JB1, -AS21210PB1 that all register with the PHY ID 0x7500 0x7510 -before the firmware is loaded. - -They all support up to 5 LEDs with various HW mode supported. - -While implementing it was found some strange coincidence with using the -same logic for implementing C22 in MMD regs in Broadcom PHYs. - -For reference here the AS21xxx PHY name logic: - -AS21x1xxB1 - ^ ^^ - | |J: Supports SyncE/PTP - | |P: No SyncE/PTP support - | 1: Supports 2nd Serdes - | 2: Not 2nd Serdes support - 0: 10G, 5G, 2.5G - 5: 5G, 2.5G - 2: 2.5G - -Reviewed-by: Andrew Lunn -Signed-off-by: Christian Marangi -Link: https://patch.msgid.link/20250517201353.5137-6-ansuelsmth@gmail.com -Signed-off-by: Jakub Kicinski ---- - MAINTAINERS | 6 + - drivers/net/phy/Kconfig | 12 + - drivers/net/phy/Makefile | 1 + - drivers/net/phy/as21xxx.c | 1087 +++++++++++++++++++++++++++++++++++++ - 4 files changed, 1106 insertions(+) - create mode 100644 drivers/net/phy/as21xxx.c - ---- a/MAINTAINERS -+++ b/MAINTAINERS -@@ -637,6 +637,12 @@ F: drivers/iio/accel/adxl380.h - F: drivers/iio/accel/adxl380_i2c.c - F: drivers/iio/accel/adxl380_spi.c - -+AEONSEMI PHY DRIVER -+M: Christian Marangi -+L: netdev@vger.kernel.org -+S: Maintained -+F: drivers/net/phy/as21xxx.c -+ - AF8133J THREE-AXIS MAGNETOMETER DRIVER - M: Ondřej Jirman - S: Maintained ---- a/drivers/net/phy/Kconfig -+++ b/drivers/net/phy/Kconfig -@@ -79,6 +79,18 @@ config SFP - - comment "MII PHY device drivers" - -+config AS21XXX_PHY -+ tristate "Aeonsemi AS21xxx PHYs" -+ help -+ Currently supports the Aeonsemi AS21xxx PHY. -+ -+ These are C45 PHYs 10G that require all a generic firmware. -+ -+ Supported PHYs AS21011JB1, AS21011PB1, AS21010JB1, AS21010PB1, -+ AS21511JB1, AS21511PB1, AS21510JB1, AS21510PB1, AS21210JB1, -+ AS21210PB1 that all register with the PHY ID 0x7500 0x7500 -+ before the firmware is loaded. -+ - config AIR_EN8811H_PHY - tristate "Airoha EN8811H 2.5 Gigabit PHY" - help ---- a/drivers/net/phy/Makefile -+++ b/drivers/net/phy/Makefile -@@ -39,6 +39,7 @@ obj-$(CONFIG_AIR_EN8811H_PHY) += air_e - obj-$(CONFIG_AMD_PHY) += amd.o - obj-$(CONFIG_AMCC_QT2025_PHY) += qt2025.o - obj-$(CONFIG_AQUANTIA_PHY) += aquantia/ -+obj-$(CONFIG_AS21XXX_PHY) += as21xxx.o - ifdef CONFIG_AX88796B_RUST_PHY - obj-$(CONFIG_AX88796B_PHY) += ax88796b_rust.o - else ---- /dev/null -+++ b/drivers/net/phy/as21xxx.c -@@ -0,0 +1,1087 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Aeonsemi AS21XXxX PHY Driver -+ * -+ * Author: Christian Marangi -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#define VEND1_GLB_REG_CPU_RESET_ADDR_LO_BASEADDR 0x3 -+#define VEND1_GLB_REG_CPU_RESET_ADDR_HI_BASEADDR 0x4 -+ -+#define VEND1_GLB_REG_CPU_CTRL 0xe -+#define VEND1_GLB_CPU_CTRL_MASK GENMASK(4, 0) -+#define VEND1_GLB_CPU_CTRL_LED_POLARITY_MASK GENMASK(12, 8) -+#define VEND1_GLB_CPU_CTRL_LED_POLARITY(_n) FIELD_PREP(VEND1_GLB_CPU_CTRL_LED_POLARITY_MASK, \ -+ BIT(_n)) -+ -+#define VEND1_FW_START_ADDR 0x100 -+ -+#define VEND1_GLB_REG_MDIO_INDIRECT_ADDRCMD 0x101 -+#define VEND1_GLB_REG_MDIO_INDIRECT_LOAD 0x102 -+ -+#define VEND1_GLB_REG_MDIO_INDIRECT_STATUS 0x103 -+ -+#define VEND1_PTP_CLK 0x142 -+#define VEND1_PTP_CLK_EN BIT(6) -+ -+/* 5 LED at step of 0x20 -+ * FE: Fast-Ethernet (10/100) -+ * GE: Gigabit-Ethernet (1000) -+ * NG: New-Generation (2500/5000/10000) -+ */ -+#define VEND1_LED_REG(_n) (0x1800 + ((_n) * 0x10)) -+#define VEND1_LED_REG_A_EVENT GENMASK(15, 11) -+#define VEND1_LED_CONF 0x1881 -+#define VEND1_LED_CONFG_BLINK GENMASK(7, 0) -+ -+#define VEND1_SPEED_STATUS 0x4002 -+#define VEND1_SPEED_MASK GENMASK(7, 0) -+#define VEND1_SPEED_10000 FIELD_PREP_CONST(VEND1_SPEED_MASK, 0x3) -+#define VEND1_SPEED_5000 FIELD_PREP_CONST(VEND1_SPEED_MASK, 0x5) -+#define VEND1_SPEED_2500 FIELD_PREP_CONST(VEND1_SPEED_MASK, 0x9) -+#define VEND1_SPEED_1000 FIELD_PREP_CONST(VEND1_SPEED_MASK, 0x10) -+#define VEND1_SPEED_100 FIELD_PREP_CONST(VEND1_SPEED_MASK, 0x20) -+#define VEND1_SPEED_10 FIELD_PREP_CONST(VEND1_SPEED_MASK, 0x0) -+ -+#define VEND1_IPC_CMD 0x5801 -+#define AEON_IPC_CMD_PARITY BIT(15) -+#define AEON_IPC_CMD_SIZE GENMASK(10, 6) -+#define AEON_IPC_CMD_OPCODE GENMASK(5, 0) -+ -+#define IPC_CMD_NOOP 0x0 /* Do nothing */ -+#define IPC_CMD_INFO 0x1 /* Get Firmware Version */ -+#define IPC_CMD_SYS_CPU 0x2 /* SYS_CPU */ -+#define IPC_CMD_BULK_DATA 0xa /* Pass bulk data in ipc registers. */ -+#define IPC_CMD_BULK_WRITE 0xc /* Write bulk data to memory */ -+#define IPC_CMD_CFG_PARAM 0x1a /* Write config parameters to memory */ -+#define IPC_CMD_NG_TESTMODE 0x1b /* Set NG test mode and tone */ -+#define IPC_CMD_TEMP_MON 0x15 /* Temperature monitoring function */ -+#define IPC_CMD_SET_LED 0x23 /* Set led */ -+ -+#define VEND1_IPC_STS 0x5802 -+#define AEON_IPC_STS_PARITY BIT(15) -+#define AEON_IPC_STS_SIZE GENMASK(14, 10) -+#define AEON_IPC_STS_OPCODE GENMASK(9, 4) -+#define AEON_IPC_STS_STATUS GENMASK(3, 0) -+#define AEON_IPC_STS_STATUS_RCVD FIELD_PREP_CONST(AEON_IPC_STS_STATUS, 0x1) -+#define AEON_IPC_STS_STATUS_PROCESS FIELD_PREP_CONST(AEON_IPC_STS_STATUS, 0x2) -+#define AEON_IPC_STS_STATUS_SUCCESS FIELD_PREP_CONST(AEON_IPC_STS_STATUS, 0x4) -+#define AEON_IPC_STS_STATUS_ERROR FIELD_PREP_CONST(AEON_IPC_STS_STATUS, 0x8) -+#define AEON_IPC_STS_STATUS_BUSY FIELD_PREP_CONST(AEON_IPC_STS_STATUS, 0xe) -+#define AEON_IPC_STS_STATUS_READY FIELD_PREP_CONST(AEON_IPC_STS_STATUS, 0xf) -+ -+#define VEND1_IPC_DATA0 0x5808 -+#define VEND1_IPC_DATA1 0x5809 -+#define VEND1_IPC_DATA2 0x580a -+#define VEND1_IPC_DATA3 0x580b -+#define VEND1_IPC_DATA4 0x580c -+#define VEND1_IPC_DATA5 0x580d -+#define VEND1_IPC_DATA6 0x580e -+#define VEND1_IPC_DATA7 0x580f -+#define VEND1_IPC_DATA(_n) (VEND1_IPC_DATA0 + (_n)) -+ -+/* Sub command of CMD_INFO */ -+#define IPC_INFO_VERSION 0x1 -+ -+/* Sub command of CMD_SYS_CPU */ -+#define IPC_SYS_CPU_REBOOT 0x3 -+#define IPC_SYS_CPU_IMAGE_OFST 0x4 -+#define IPC_SYS_CPU_IMAGE_CHECK 0x5 -+#define IPC_SYS_CPU_PHY_ENABLE 0x6 -+ -+/* Sub command of CMD_CFG_PARAM */ -+#define IPC_CFG_PARAM_DIRECT 0x4 -+ -+/* CFG DIRECT sub command */ -+#define IPC_CFG_PARAM_DIRECT_NG_PHYCTRL 0x1 -+#define IPC_CFG_PARAM_DIRECT_CU_AN 0x2 -+#define IPC_CFG_PARAM_DIRECT_SDS_PCS 0x3 -+#define IPC_CFG_PARAM_DIRECT_AUTO_EEE 0x4 -+#define IPC_CFG_PARAM_DIRECT_SDS_PMA 0x5 -+#define IPC_CFG_PARAM_DIRECT_DPC_RA 0x6 -+#define IPC_CFG_PARAM_DIRECT_DPC_PKT_CHK 0x7 -+#define IPC_CFG_PARAM_DIRECT_DPC_SDS_WAIT_ETH 0x8 -+#define IPC_CFG_PARAM_DIRECT_WDT 0x9 -+#define IPC_CFG_PARAM_DIRECT_SDS_RESTART_AN 0x10 -+#define IPC_CFG_PARAM_DIRECT_TEMP_MON 0x11 -+#define IPC_CFG_PARAM_DIRECT_WOL 0x12 -+ -+/* Sub command of CMD_TEMP_MON */ -+#define IPC_CMD_TEMP_MON_GET 0x4 -+ -+#define AS21XXX_MDIO_AN_C22 0xffe0 -+ -+#define PHY_ID_AS21XXX 0x75009410 -+/* AS21xxx ID Legend -+ * AS21x1xxB1 -+ * ^ ^^ -+ * | |J: Supports SyncE/PTP -+ * | |P: No SyncE/PTP support -+ * | 1: Supports 2nd Serdes -+ * | 2: Not 2nd Serdes support -+ * 0: 10G, 5G, 2.5G -+ * 5: 5G, 2.5G -+ * 2: 2.5G -+ */ -+#define PHY_ID_AS21011JB1 0x75009402 -+#define PHY_ID_AS21011PB1 0x75009412 -+#define PHY_ID_AS21010JB1 0x75009422 -+#define PHY_ID_AS21010PB1 0x75009432 -+#define PHY_ID_AS21511JB1 0x75009442 -+#define PHY_ID_AS21511PB1 0x75009452 -+#define PHY_ID_AS21510JB1 0x75009462 -+#define PHY_ID_AS21510PB1 0x75009472 -+#define PHY_ID_AS21210JB1 0x75009482 -+#define PHY_ID_AS21210PB1 0x75009492 -+#define PHY_VENDOR_AEONSEMI 0x75009400 -+ -+#define AEON_MAX_LEDS 5 -+#define AEON_IPC_DELAY 10000 -+#define AEON_IPC_TIMEOUT (AEON_IPC_DELAY * 100) -+#define AEON_IPC_DATA_NUM_REGISTERS 8 -+#define AEON_IPC_DATA_MAX (AEON_IPC_DATA_NUM_REGISTERS * sizeof(u16)) -+ -+#define AEON_BOOT_ADDR 0x1000 -+#define AEON_CPU_BOOT_ADDR 0x2000 -+#define AEON_CPU_CTRL_FW_LOAD (BIT(4) | BIT(2) | BIT(1) | BIT(0)) -+#define AEON_CPU_CTRL_FW_START BIT(0) -+ -+enum as21xxx_led_event { -+ VEND1_LED_REG_A_EVENT_ON_10 = 0x0, -+ VEND1_LED_REG_A_EVENT_ON_100, -+ VEND1_LED_REG_A_EVENT_ON_1000, -+ VEND1_LED_REG_A_EVENT_ON_2500, -+ VEND1_LED_REG_A_EVENT_ON_5000, -+ VEND1_LED_REG_A_EVENT_ON_10000, -+ VEND1_LED_REG_A_EVENT_ON_FE_GE, -+ VEND1_LED_REG_A_EVENT_ON_NG, -+ VEND1_LED_REG_A_EVENT_ON_FULL_DUPLEX, -+ VEND1_LED_REG_A_EVENT_ON_COLLISION, -+ VEND1_LED_REG_A_EVENT_BLINK_TX, -+ VEND1_LED_REG_A_EVENT_BLINK_RX, -+ VEND1_LED_REG_A_EVENT_BLINK_ACT, -+ VEND1_LED_REG_A_EVENT_ON_LINK, -+ VEND1_LED_REG_A_EVENT_ON_LINK_BLINK_ACT, -+ VEND1_LED_REG_A_EVENT_ON_LINK_BLINK_RX, -+ VEND1_LED_REG_A_EVENT_ON_FE_GE_BLINK_ACT, -+ VEND1_LED_REG_A_EVENT_ON_NG_BLINK_ACT, -+ VEND1_LED_REG_A_EVENT_ON_NG_BLINK_FE_GE, -+ VEND1_LED_REG_A_EVENT_ON_FD_BLINK_COLLISION, -+ VEND1_LED_REG_A_EVENT_ON, -+ VEND1_LED_REG_A_EVENT_OFF, -+}; -+ -+struct as21xxx_led_pattern_info { -+ unsigned int pattern; -+ u16 val; -+}; -+ -+struct as21xxx_priv { -+ bool parity_status; -+ /* Protect concurrent IPC access */ -+ struct mutex ipc_lock; -+}; -+ -+static struct as21xxx_led_pattern_info as21xxx_led_supported_pattern[] = { -+ { -+ .pattern = BIT(TRIGGER_NETDEV_LINK_10), -+ .val = VEND1_LED_REG_A_EVENT_ON_10 -+ }, -+ { -+ .pattern = BIT(TRIGGER_NETDEV_LINK_100), -+ .val = VEND1_LED_REG_A_EVENT_ON_100 -+ }, -+ { -+ .pattern = BIT(TRIGGER_NETDEV_LINK_1000), -+ .val = VEND1_LED_REG_A_EVENT_ON_1000 -+ }, -+ { -+ .pattern = BIT(TRIGGER_NETDEV_LINK_2500), -+ .val = VEND1_LED_REG_A_EVENT_ON_2500 -+ }, -+ { -+ .pattern = BIT(TRIGGER_NETDEV_LINK_5000), -+ .val = VEND1_LED_REG_A_EVENT_ON_5000 -+ }, -+ { -+ .pattern = BIT(TRIGGER_NETDEV_LINK_10000), -+ .val = VEND1_LED_REG_A_EVENT_ON_10000 -+ }, -+ { -+ .pattern = BIT(TRIGGER_NETDEV_LINK), -+ .val = VEND1_LED_REG_A_EVENT_ON_LINK -+ }, -+ { -+ .pattern = BIT(TRIGGER_NETDEV_LINK_10) | -+ BIT(TRIGGER_NETDEV_LINK_100) | -+ BIT(TRIGGER_NETDEV_LINK_1000), -+ .val = VEND1_LED_REG_A_EVENT_ON_FE_GE -+ }, -+ { -+ .pattern = BIT(TRIGGER_NETDEV_LINK_2500) | -+ BIT(TRIGGER_NETDEV_LINK_5000) | -+ BIT(TRIGGER_NETDEV_LINK_10000), -+ .val = VEND1_LED_REG_A_EVENT_ON_NG -+ }, -+ { -+ .pattern = BIT(TRIGGER_NETDEV_FULL_DUPLEX), -+ .val = VEND1_LED_REG_A_EVENT_ON_FULL_DUPLEX -+ }, -+ { -+ .pattern = BIT(TRIGGER_NETDEV_TX), -+ .val = VEND1_LED_REG_A_EVENT_BLINK_TX -+ }, -+ { -+ .pattern = BIT(TRIGGER_NETDEV_RX), -+ .val = VEND1_LED_REG_A_EVENT_BLINK_RX -+ }, -+ { -+ .pattern = BIT(TRIGGER_NETDEV_TX) | -+ BIT(TRIGGER_NETDEV_RX), -+ .val = VEND1_LED_REG_A_EVENT_BLINK_ACT -+ }, -+ { -+ .pattern = BIT(TRIGGER_NETDEV_LINK_10) | -+ BIT(TRIGGER_NETDEV_LINK_100) | -+ BIT(TRIGGER_NETDEV_LINK_1000) | -+ BIT(TRIGGER_NETDEV_LINK_2500) | -+ BIT(TRIGGER_NETDEV_LINK_5000) | -+ BIT(TRIGGER_NETDEV_LINK_10000), -+ .val = VEND1_LED_REG_A_EVENT_ON_LINK -+ }, -+ { -+ .pattern = BIT(TRIGGER_NETDEV_LINK_10) | -+ BIT(TRIGGER_NETDEV_LINK_100) | -+ BIT(TRIGGER_NETDEV_LINK_1000) | -+ BIT(TRIGGER_NETDEV_LINK_2500) | -+ BIT(TRIGGER_NETDEV_LINK_5000) | -+ BIT(TRIGGER_NETDEV_LINK_10000) | -+ BIT(TRIGGER_NETDEV_TX) | -+ BIT(TRIGGER_NETDEV_RX), -+ .val = VEND1_LED_REG_A_EVENT_ON_LINK_BLINK_ACT -+ }, -+ { -+ .pattern = BIT(TRIGGER_NETDEV_LINK_10) | -+ BIT(TRIGGER_NETDEV_LINK_100) | -+ BIT(TRIGGER_NETDEV_LINK_1000) | -+ BIT(TRIGGER_NETDEV_LINK_2500) | -+ BIT(TRIGGER_NETDEV_LINK_5000) | -+ BIT(TRIGGER_NETDEV_LINK_10000) | -+ BIT(TRIGGER_NETDEV_RX), -+ .val = VEND1_LED_REG_A_EVENT_ON_LINK_BLINK_RX -+ }, -+ { -+ .pattern = BIT(TRIGGER_NETDEV_LINK_10) | -+ BIT(TRIGGER_NETDEV_LINK_100) | -+ BIT(TRIGGER_NETDEV_LINK_1000) | -+ BIT(TRIGGER_NETDEV_TX) | -+ BIT(TRIGGER_NETDEV_RX), -+ .val = VEND1_LED_REG_A_EVENT_ON_FE_GE_BLINK_ACT -+ }, -+ { -+ .pattern = BIT(TRIGGER_NETDEV_LINK_2500) | -+ BIT(TRIGGER_NETDEV_LINK_5000) | -+ BIT(TRIGGER_NETDEV_LINK_10000) | -+ BIT(TRIGGER_NETDEV_TX) | -+ BIT(TRIGGER_NETDEV_RX), -+ .val = VEND1_LED_REG_A_EVENT_ON_NG_BLINK_ACT -+ } -+}; -+ -+static int aeon_firmware_boot(struct phy_device *phydev, const u8 *data, -+ size_t size) -+{ -+ int i, ret; -+ u16 val; -+ -+ ret = phy_modify_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLB_REG_CPU_CTRL, -+ VEND1_GLB_CPU_CTRL_MASK, AEON_CPU_CTRL_FW_LOAD); -+ if (ret) -+ return ret; -+ -+ ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_FW_START_ADDR, -+ AEON_BOOT_ADDR); -+ if (ret) -+ return ret; -+ -+ ret = phy_modify_mmd(phydev, MDIO_MMD_VEND1, -+ VEND1_GLB_REG_MDIO_INDIRECT_ADDRCMD, -+ 0x3ffc, 0xc000); -+ if (ret) -+ return ret; -+ -+ val = phy_read_mmd(phydev, MDIO_MMD_VEND1, -+ VEND1_GLB_REG_MDIO_INDIRECT_STATUS); -+ if (val > 1) { -+ phydev_err(phydev, "wrong origin mdio_indirect_status: %x\n", val); -+ return -EINVAL; -+ } -+ -+ /* Firmware is always aligned to u16 */ -+ for (i = 0; i < size; i += 2) { -+ val = data[i + 1] << 8 | data[i]; -+ -+ ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, -+ VEND1_GLB_REG_MDIO_INDIRECT_LOAD, val); -+ if (ret) -+ return ret; -+ } -+ -+ ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, -+ VEND1_GLB_REG_CPU_RESET_ADDR_LO_BASEADDR, -+ lower_16_bits(AEON_CPU_BOOT_ADDR)); -+ if (ret) -+ return ret; -+ -+ ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, -+ VEND1_GLB_REG_CPU_RESET_ADDR_HI_BASEADDR, -+ upper_16_bits(AEON_CPU_BOOT_ADDR)); -+ if (ret) -+ return ret; -+ -+ return phy_modify_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLB_REG_CPU_CTRL, -+ VEND1_GLB_CPU_CTRL_MASK, AEON_CPU_CTRL_FW_START); -+} -+ -+static int aeon_firmware_load(struct phy_device *phydev) -+{ -+ struct device *dev = &phydev->mdio.dev; -+ const struct firmware *fw; -+ const char *fw_name; -+ int ret; -+ -+ ret = of_property_read_string(dev->of_node, "firmware-name", -+ &fw_name); -+ if (ret) -+ return ret; -+ -+ ret = request_firmware(&fw, fw_name, dev); -+ if (ret) { -+ phydev_err(phydev, "failed to find FW file %s (%d)\n", -+ fw_name, ret); -+ return ret; -+ } -+ -+ ret = aeon_firmware_boot(phydev, fw->data, fw->size); -+ -+ release_firmware(fw); -+ -+ return ret; -+} -+ -+static bool aeon_ipc_ready(u16 val, bool parity_status) -+{ -+ u16 status; -+ -+ if (FIELD_GET(AEON_IPC_STS_PARITY, val) != parity_status) -+ return false; -+ -+ status = val & AEON_IPC_STS_STATUS; -+ -+ return status != AEON_IPC_STS_STATUS_RCVD && -+ status != AEON_IPC_STS_STATUS_PROCESS && -+ status != AEON_IPC_STS_STATUS_BUSY; -+} -+ -+static int aeon_ipc_wait_cmd(struct phy_device *phydev, bool parity_status) -+{ -+ u16 val; -+ -+ /* Exit condition logic: -+ * - Wait for parity bit equal -+ * - Wait for status success, error OR ready -+ */ -+ return phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1, VEND1_IPC_STS, val, -+ aeon_ipc_ready(val, parity_status), -+ AEON_IPC_DELAY, AEON_IPC_TIMEOUT, false); -+} -+ -+static int aeon_ipc_send_cmd(struct phy_device *phydev, -+ struct as21xxx_priv *priv, -+ u16 cmd, u16 *ret_sts) -+{ -+ bool curr_parity; -+ int ret; -+ -+ /* The IPC sync by using a single parity bit. -+ * Each CMD have alternately this bit set or clear -+ * to understand correct flow and packet order. -+ */ -+ curr_parity = priv->parity_status; -+ if (priv->parity_status) -+ cmd |= AEON_IPC_CMD_PARITY; -+ -+ /* Always update parity for next packet */ -+ priv->parity_status = !priv->parity_status; -+ -+ ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_IPC_CMD, cmd); -+ if (ret) -+ return ret; -+ -+ /* Wait for packet to be processed */ -+ usleep_range(AEON_IPC_DELAY, AEON_IPC_DELAY + 5000); -+ -+ /* With no ret_sts, ignore waiting for packet completion -+ * (ipc parity bit sync) -+ */ -+ if (!ret_sts) -+ return 0; -+ -+ ret = aeon_ipc_wait_cmd(phydev, curr_parity); -+ if (ret) -+ return ret; -+ -+ ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_IPC_STS); -+ if (ret < 0) -+ return ret; -+ -+ *ret_sts = ret; -+ if ((*ret_sts & AEON_IPC_STS_STATUS) != AEON_IPC_STS_STATUS_SUCCESS) -+ return -EINVAL; -+ -+ return 0; -+} -+ -+/* If data is NULL, return 0 or negative error. -+ * If data not NULL, return number of Bytes received from IPC or -+ * a negative error. -+ */ -+static int aeon_ipc_send_msg(struct phy_device *phydev, -+ u16 opcode, u16 *data, unsigned int data_len, -+ u16 *ret_data) -+{ -+ struct as21xxx_priv *priv = phydev->priv; -+ unsigned int ret_size; -+ u16 cmd, ret_sts; -+ int ret; -+ int i; -+ -+ /* IPC have a max of 8 register to transfer data, -+ * make sure we never exceed this. -+ */ -+ if (data_len > AEON_IPC_DATA_MAX) -+ return -EINVAL; -+ -+ for (i = 0; i < data_len / sizeof(u16); i++) -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_IPC_DATA(i), -+ data[i]); -+ -+ cmd = FIELD_PREP(AEON_IPC_CMD_SIZE, data_len) | -+ FIELD_PREP(AEON_IPC_CMD_OPCODE, opcode); -+ -+ mutex_lock(&priv->ipc_lock); -+ -+ ret = aeon_ipc_send_cmd(phydev, priv, cmd, &ret_sts); -+ if (ret) { -+ phydev_err(phydev, "failed to send ipc msg for %x: %d\n", -+ opcode, ret); -+ goto out; -+ } -+ -+ if (!data) -+ goto out; -+ -+ if ((ret_sts & AEON_IPC_STS_STATUS) == AEON_IPC_STS_STATUS_ERROR) { -+ ret = -EINVAL; -+ goto out; -+ } -+ -+ /* Prevent IPC from stack smashing the kernel. -+ * We can't trust IPC to return a good value and we always -+ * preallocate space for 16 Bytes. -+ */ -+ ret_size = FIELD_GET(AEON_IPC_STS_SIZE, ret_sts); -+ if (ret_size > AEON_IPC_DATA_MAX) { -+ ret = -EINVAL; -+ goto out; -+ } -+ -+ /* Read data from IPC data register for ret_size value from IPC */ -+ for (i = 0; i < DIV_ROUND_UP(ret_size, sizeof(u16)); i++) { -+ ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_IPC_DATA(i)); -+ if (ret < 0) -+ goto out; -+ -+ ret_data[i] = ret; -+ } -+ -+ ret = ret_size; -+ -+out: -+ mutex_unlock(&priv->ipc_lock); -+ -+ return ret; -+} -+ -+static int aeon_ipc_noop(struct phy_device *phydev, -+ struct as21xxx_priv *priv, u16 *ret_sts) -+{ -+ u16 cmd; -+ -+ cmd = FIELD_PREP(AEON_IPC_CMD_SIZE, 0) | -+ FIELD_PREP(AEON_IPC_CMD_OPCODE, IPC_CMD_NOOP); -+ -+ return aeon_ipc_send_cmd(phydev, priv, cmd, ret_sts); -+} -+ -+/* Logic to sync parity bit with IPC. -+ * We send 2 NOP cmd with same partity and we wait for IPC -+ * to handle the packet only for the second one. This way -+ * we make sure we are sync for every next cmd. -+ */ -+static int aeon_ipc_sync_parity(struct phy_device *phydev, -+ struct as21xxx_priv *priv) -+{ -+ u16 ret_sts; -+ int ret; -+ -+ mutex_lock(&priv->ipc_lock); -+ -+ /* Send NOP with no parity */ -+ aeon_ipc_noop(phydev, priv, NULL); -+ -+ /* Reset packet parity */ -+ priv->parity_status = false; -+ -+ /* Send second NOP with no parity */ -+ ret = aeon_ipc_noop(phydev, priv, &ret_sts); -+ -+ mutex_unlock(&priv->ipc_lock); -+ -+ /* We expect to return -EINVAL */ -+ if (ret != -EINVAL) -+ return ret; -+ -+ if ((ret_sts & AEON_IPC_STS_STATUS) != AEON_IPC_STS_STATUS_READY) { -+ phydev_err(phydev, "Invalid IPC status on sync parity: %x\n", -+ ret_sts); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+static int aeon_ipc_get_fw_version(struct phy_device *phydev) -+{ -+ u16 ret_data[AEON_IPC_DATA_NUM_REGISTERS], data[1]; -+ char fw_version[AEON_IPC_DATA_MAX + 1]; -+ int ret; -+ -+ data[0] = IPC_INFO_VERSION; -+ -+ ret = aeon_ipc_send_msg(phydev, IPC_CMD_INFO, data, -+ sizeof(data), ret_data); -+ if (ret < 0) -+ return ret; -+ -+ /* Make sure FW version is NULL terminated */ -+ memcpy(fw_version, ret_data, ret); -+ fw_version[ret] = '\0'; -+ -+ phydev_info(phydev, "Firmware Version: %s\n", fw_version); -+ -+ return 0; -+} -+ -+static int aeon_dpc_ra_enable(struct phy_device *phydev) -+{ -+ u16 data[2]; -+ -+ data[0] = IPC_CFG_PARAM_DIRECT; -+ data[1] = IPC_CFG_PARAM_DIRECT_DPC_RA; -+ -+ return aeon_ipc_send_msg(phydev, IPC_CMD_CFG_PARAM, data, -+ sizeof(data), NULL); -+} -+ -+static int as21xxx_probe(struct phy_device *phydev) -+{ -+ struct as21xxx_priv *priv; -+ int ret; -+ -+ priv = devm_kzalloc(&phydev->mdio.dev, -+ sizeof(*priv), GFP_KERNEL); -+ if (!priv) -+ return -ENOMEM; -+ phydev->priv = priv; -+ -+ ret = devm_mutex_init(&phydev->mdio.dev, -+ &priv->ipc_lock); -+ if (ret) -+ return ret; -+ -+ ret = aeon_ipc_sync_parity(phydev, priv); -+ if (ret) -+ return ret; -+ -+ ret = aeon_ipc_get_fw_version(phydev); -+ if (ret) -+ return ret; -+ -+ /* Enable PTP clk if not already Enabled */ -+ ret = phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_PTP_CLK, -+ VEND1_PTP_CLK_EN); -+ if (ret) -+ return ret; -+ -+ return aeon_dpc_ra_enable(phydev); -+} -+ -+static int as21xxx_read_link(struct phy_device *phydev, int *bmcr) -+{ -+ int status; -+ -+ /* Normal C22 BMCR report inconsistent data, use -+ * the mapped C22 in C45 to have more consistent link info. -+ */ -+ *bmcr = phy_read_mmd(phydev, MDIO_MMD_AN, -+ AS21XXX_MDIO_AN_C22 + MII_BMCR); -+ if (*bmcr < 0) -+ return *bmcr; -+ -+ /* Autoneg is being started, therefore disregard current -+ * link status and report link as down. -+ */ -+ if (*bmcr & BMCR_ANRESTART) { -+ phydev->link = 0; -+ return 0; -+ } -+ -+ status = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_STAT1); -+ if (status < 0) -+ return status; -+ -+ phydev->link = !!(status & MDIO_STAT1_LSTATUS); -+ -+ return 0; -+} -+ -+static int as21xxx_read_c22_lpa(struct phy_device *phydev) -+{ -+ int lpagb; -+ -+ /* MII_STAT1000 are only filled in the mapped C22 -+ * in C45, use that to fill lpagb values and check. -+ */ -+ lpagb = phy_read_mmd(phydev, MDIO_MMD_AN, -+ AS21XXX_MDIO_AN_C22 + MII_STAT1000); -+ if (lpagb < 0) -+ return lpagb; -+ -+ if (lpagb & LPA_1000MSFAIL) { -+ int adv = phy_read_mmd(phydev, MDIO_MMD_AN, -+ AS21XXX_MDIO_AN_C22 + MII_CTRL1000); -+ -+ if (adv < 0) -+ return adv; -+ -+ if (adv & CTL1000_ENABLE_MASTER) -+ phydev_err(phydev, "Master/Slave resolution failed, maybe conflicting manual settings?\n"); -+ else -+ phydev_err(phydev, "Master/Slave resolution failed\n"); -+ return -ENOLINK; -+ } -+ -+ mii_stat1000_mod_linkmode_lpa_t(phydev->lp_advertising, -+ lpagb); -+ -+ return 0; -+} -+ -+static int as21xxx_read_status(struct phy_device *phydev) -+{ -+ int bmcr, old_link = phydev->link; -+ int ret; -+ -+ ret = as21xxx_read_link(phydev, &bmcr); -+ if (ret) -+ return ret; -+ -+ /* why bother the PHY if nothing can have changed */ -+ if (phydev->autoneg == AUTONEG_ENABLE && old_link && phydev->link) -+ return 0; -+ -+ phydev->speed = SPEED_UNKNOWN; -+ phydev->duplex = DUPLEX_UNKNOWN; -+ phydev->pause = 0; -+ phydev->asym_pause = 0; -+ -+ if (phydev->autoneg == AUTONEG_ENABLE) { -+ ret = genphy_c45_read_lpa(phydev); -+ if (ret) -+ return ret; -+ -+ ret = as21xxx_read_c22_lpa(phydev); -+ if (ret) -+ return ret; -+ -+ phy_resolve_aneg_linkmode(phydev); -+ } else { -+ int speed; -+ -+ linkmode_zero(phydev->lp_advertising); -+ -+ speed = phy_read_mmd(phydev, MDIO_MMD_VEND1, -+ VEND1_SPEED_STATUS); -+ if (speed < 0) -+ return speed; -+ -+ switch (speed & VEND1_SPEED_STATUS) { -+ case VEND1_SPEED_10000: -+ phydev->speed = SPEED_10000; -+ phydev->duplex = DUPLEX_FULL; -+ break; -+ case VEND1_SPEED_5000: -+ phydev->speed = SPEED_5000; -+ phydev->duplex = DUPLEX_FULL; -+ break; -+ case VEND1_SPEED_2500: -+ phydev->speed = SPEED_2500; -+ phydev->duplex = DUPLEX_FULL; -+ break; -+ case VEND1_SPEED_1000: -+ phydev->speed = SPEED_1000; -+ if (bmcr & BMCR_FULLDPLX) -+ phydev->duplex = DUPLEX_FULL; -+ else -+ phydev->duplex = DUPLEX_HALF; -+ break; -+ case VEND1_SPEED_100: -+ phydev->speed = SPEED_100; -+ phydev->duplex = DUPLEX_FULL; -+ break; -+ case VEND1_SPEED_10: -+ phydev->speed = SPEED_10; -+ phydev->duplex = DUPLEX_FULL; -+ break; -+ default: -+ return -EINVAL; -+ } -+ } -+ -+ return 0; -+} -+ -+static int as21xxx_led_brightness_set(struct phy_device *phydev, -+ u8 index, enum led_brightness value) -+{ -+ u16 val = VEND1_LED_REG_A_EVENT_OFF; -+ -+ if (index > AEON_MAX_LEDS) -+ return -EINVAL; -+ -+ if (value) -+ val = VEND1_LED_REG_A_EVENT_ON; -+ -+ return phy_modify_mmd(phydev, MDIO_MMD_VEND1, -+ VEND1_LED_REG(index), -+ VEND1_LED_REG_A_EVENT, -+ FIELD_PREP(VEND1_LED_REG_A_EVENT, val)); -+} -+ -+static int as21xxx_led_hw_is_supported(struct phy_device *phydev, u8 index, -+ unsigned long rules) -+{ -+ int i; -+ -+ if (index > AEON_MAX_LEDS) -+ return -EINVAL; -+ -+ for (i = 0; i < ARRAY_SIZE(as21xxx_led_supported_pattern); i++) -+ if (rules == as21xxx_led_supported_pattern[i].pattern) -+ return 0; -+ -+ return -EOPNOTSUPP; -+} -+ -+static int as21xxx_led_hw_control_get(struct phy_device *phydev, u8 index, -+ unsigned long *rules) -+{ -+ int i, val; -+ -+ if (index > AEON_MAX_LEDS) -+ return -EINVAL; -+ -+ val = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_LED_REG(index)); -+ if (val < 0) -+ return val; -+ -+ val = FIELD_GET(VEND1_LED_REG_A_EVENT, val); -+ for (i = 0; i < ARRAY_SIZE(as21xxx_led_supported_pattern); i++) -+ if (val == as21xxx_led_supported_pattern[i].val) { -+ *rules = as21xxx_led_supported_pattern[i].pattern; -+ return 0; -+ } -+ -+ /* Should be impossible */ -+ return -EINVAL; -+} -+ -+static int as21xxx_led_hw_control_set(struct phy_device *phydev, u8 index, -+ unsigned long rules) -+{ -+ u16 val = 0; -+ int i; -+ -+ if (index > AEON_MAX_LEDS) -+ return -EINVAL; -+ -+ for (i = 0; i < ARRAY_SIZE(as21xxx_led_supported_pattern); i++) -+ if (rules == as21xxx_led_supported_pattern[i].pattern) { -+ val = as21xxx_led_supported_pattern[i].val; -+ break; -+ } -+ -+ return phy_modify_mmd(phydev, MDIO_MMD_VEND1, -+ VEND1_LED_REG(index), -+ VEND1_LED_REG_A_EVENT, -+ FIELD_PREP(VEND1_LED_REG_A_EVENT, val)); -+} -+ -+static int as21xxx_led_polarity_set(struct phy_device *phydev, int index, -+ unsigned long modes) -+{ -+ bool led_active_low = false; -+ u16 mask, val = 0; -+ u32 mode; -+ -+ if (index > AEON_MAX_LEDS) -+ return -EINVAL; -+ -+ for_each_set_bit(mode, &modes, __PHY_LED_MODES_NUM) { -+ switch (mode) { -+ case PHY_LED_ACTIVE_LOW: -+ led_active_low = true; -+ break; -+ case PHY_LED_ACTIVE_HIGH: /* default mode */ -+ led_active_low = false; -+ break; -+ default: -+ return -EINVAL; -+ } -+ } -+ -+ mask = VEND1_GLB_CPU_CTRL_LED_POLARITY(index); -+ if (led_active_low) -+ val = VEND1_GLB_CPU_CTRL_LED_POLARITY(index); -+ -+ return phy_modify_mmd(phydev, MDIO_MMD_VEND1, -+ VEND1_GLB_REG_CPU_CTRL, -+ mask, val); -+} -+ -+static int as21xxx_match_phy_device(struct phy_device *phydev, -+ const struct phy_driver *phydrv) -+{ -+ struct as21xxx_priv *priv; -+ u16 ret_sts; -+ u32 phy_id; -+ int ret; -+ -+ /* Skip PHY that are not AS21xxx or already have firmware loaded */ -+ if (phydev->c45_ids.device_ids[MDIO_MMD_PCS] != PHY_ID_AS21XXX) -+ return genphy_match_phy_device(phydev, phydrv); -+ -+ /* Read PHY ID to handle firmware just loaded */ -+ ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MII_PHYSID1); -+ if (ret < 0) -+ return ret; -+ phy_id = ret << 16; -+ -+ ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MII_PHYSID2); -+ if (ret < 0) -+ return ret; -+ phy_id |= ret; -+ -+ /* With PHY ID not the generic AS21xxx one assume -+ * the firmware just loaded -+ */ -+ if (phy_id != PHY_ID_AS21XXX) -+ return phy_id == phydrv->phy_id; -+ -+ /* Allocate temp priv and load the firmware */ -+ priv = kzalloc(sizeof(*priv), GFP_KERNEL); -+ if (!priv) -+ return -ENOMEM; -+ -+ mutex_init(&priv->ipc_lock); -+ -+ ret = aeon_firmware_load(phydev); -+ if (ret) -+ goto out; -+ -+ /* Sync parity... */ -+ ret = aeon_ipc_sync_parity(phydev, priv); -+ if (ret) -+ goto out; -+ -+ /* ...and send a third NOOP cmd to wait for firmware finish loading */ -+ ret = aeon_ipc_noop(phydev, priv, &ret_sts); -+ if (ret) -+ goto out; -+ -+out: -+ mutex_destroy(&priv->ipc_lock); -+ kfree(priv); -+ -+ /* Return can either be 0 or a negative error code. -+ * Returning 0 here means THIS is NOT a suitable PHY. -+ * -+ * For the specific case of the generic Aeonsemi PHY ID that -+ * needs the firmware the be loaded first to have a correct PHY ID, -+ * this is OK as a matching PHY ID will be found right after. -+ * This relies on the driver probe order where the first PHY driver -+ * probed is the generic one. -+ */ -+ return ret; -+} -+ -+static struct phy_driver as21xxx_drivers[] = { -+ { -+ /* PHY expose in C45 as 0x7500 0x9410 -+ * before firmware is loaded. -+ * This driver entry must be attempted first to load -+ * the firmware and thus update the ID registers. -+ */ -+ PHY_ID_MATCH_EXACT(PHY_ID_AS21XXX), -+ .name = "Aeonsemi AS21xxx", -+ .match_phy_device = as21xxx_match_phy_device, -+ }, -+ { -+ PHY_ID_MATCH_EXACT(PHY_ID_AS21011JB1), -+ .name = "Aeonsemi AS21011JB1", -+ .probe = as21xxx_probe, -+ .match_phy_device = as21xxx_match_phy_device, -+ .read_status = as21xxx_read_status, -+ .led_brightness_set = as21xxx_led_brightness_set, -+ .led_hw_is_supported = as21xxx_led_hw_is_supported, -+ .led_hw_control_set = as21xxx_led_hw_control_set, -+ .led_hw_control_get = as21xxx_led_hw_control_get, -+ .led_polarity_set = as21xxx_led_polarity_set, -+ }, -+ { -+ PHY_ID_MATCH_EXACT(PHY_ID_AS21011PB1), -+ .name = "Aeonsemi AS21011PB1", -+ .probe = as21xxx_probe, -+ .match_phy_device = as21xxx_match_phy_device, -+ .read_status = as21xxx_read_status, -+ .led_brightness_set = as21xxx_led_brightness_set, -+ .led_hw_is_supported = as21xxx_led_hw_is_supported, -+ .led_hw_control_set = as21xxx_led_hw_control_set, -+ .led_hw_control_get = as21xxx_led_hw_control_get, -+ .led_polarity_set = as21xxx_led_polarity_set, -+ }, -+ { -+ PHY_ID_MATCH_EXACT(PHY_ID_AS21010PB1), -+ .name = "Aeonsemi AS21010PB1", -+ .probe = as21xxx_probe, -+ .match_phy_device = as21xxx_match_phy_device, -+ .read_status = as21xxx_read_status, -+ .led_brightness_set = as21xxx_led_brightness_set, -+ .led_hw_is_supported = as21xxx_led_hw_is_supported, -+ .led_hw_control_set = as21xxx_led_hw_control_set, -+ .led_hw_control_get = as21xxx_led_hw_control_get, -+ .led_polarity_set = as21xxx_led_polarity_set, -+ }, -+ { -+ PHY_ID_MATCH_EXACT(PHY_ID_AS21010JB1), -+ .name = "Aeonsemi AS21010JB1", -+ .probe = as21xxx_probe, -+ .match_phy_device = as21xxx_match_phy_device, -+ .read_status = as21xxx_read_status, -+ .led_brightness_set = as21xxx_led_brightness_set, -+ .led_hw_is_supported = as21xxx_led_hw_is_supported, -+ .led_hw_control_set = as21xxx_led_hw_control_set, -+ .led_hw_control_get = as21xxx_led_hw_control_get, -+ .led_polarity_set = as21xxx_led_polarity_set, -+ }, -+ { -+ PHY_ID_MATCH_EXACT(PHY_ID_AS21210PB1), -+ .name = "Aeonsemi AS21210PB1", -+ .probe = as21xxx_probe, -+ .match_phy_device = as21xxx_match_phy_device, -+ .read_status = as21xxx_read_status, -+ .led_brightness_set = as21xxx_led_brightness_set, -+ .led_hw_is_supported = as21xxx_led_hw_is_supported, -+ .led_hw_control_set = as21xxx_led_hw_control_set, -+ .led_hw_control_get = as21xxx_led_hw_control_get, -+ .led_polarity_set = as21xxx_led_polarity_set, -+ }, -+ { -+ PHY_ID_MATCH_EXACT(PHY_ID_AS21510JB1), -+ .name = "Aeonsemi AS21510JB1", -+ .probe = as21xxx_probe, -+ .match_phy_device = as21xxx_match_phy_device, -+ .read_status = as21xxx_read_status, -+ .led_brightness_set = as21xxx_led_brightness_set, -+ .led_hw_is_supported = as21xxx_led_hw_is_supported, -+ .led_hw_control_set = as21xxx_led_hw_control_set, -+ .led_hw_control_get = as21xxx_led_hw_control_get, -+ .led_polarity_set = as21xxx_led_polarity_set, -+ }, -+ { -+ PHY_ID_MATCH_EXACT(PHY_ID_AS21510PB1), -+ .name = "Aeonsemi AS21510PB1", -+ .probe = as21xxx_probe, -+ .match_phy_device = as21xxx_match_phy_device, -+ .read_status = as21xxx_read_status, -+ .led_brightness_set = as21xxx_led_brightness_set, -+ .led_hw_is_supported = as21xxx_led_hw_is_supported, -+ .led_hw_control_set = as21xxx_led_hw_control_set, -+ .led_hw_control_get = as21xxx_led_hw_control_get, -+ .led_polarity_set = as21xxx_led_polarity_set, -+ }, -+ { -+ PHY_ID_MATCH_EXACT(PHY_ID_AS21511JB1), -+ .name = "Aeonsemi AS21511JB1", -+ .probe = as21xxx_probe, -+ .match_phy_device = as21xxx_match_phy_device, -+ .read_status = as21xxx_read_status, -+ .led_brightness_set = as21xxx_led_brightness_set, -+ .led_hw_is_supported = as21xxx_led_hw_is_supported, -+ .led_hw_control_set = as21xxx_led_hw_control_set, -+ .led_hw_control_get = as21xxx_led_hw_control_get, -+ .led_polarity_set = as21xxx_led_polarity_set, -+ }, -+ { -+ PHY_ID_MATCH_EXACT(PHY_ID_AS21210JB1), -+ .name = "Aeonsemi AS21210JB1", -+ .probe = as21xxx_probe, -+ .match_phy_device = as21xxx_match_phy_device, -+ .read_status = as21xxx_read_status, -+ .led_brightness_set = as21xxx_led_brightness_set, -+ .led_hw_is_supported = as21xxx_led_hw_is_supported, -+ .led_hw_control_set = as21xxx_led_hw_control_set, -+ .led_hw_control_get = as21xxx_led_hw_control_get, -+ .led_polarity_set = as21xxx_led_polarity_set, -+ }, -+ { -+ PHY_ID_MATCH_EXACT(PHY_ID_AS21511PB1), -+ .name = "Aeonsemi AS21511PB1", -+ .probe = as21xxx_probe, -+ .match_phy_device = as21xxx_match_phy_device, -+ .read_status = as21xxx_read_status, -+ .led_brightness_set = as21xxx_led_brightness_set, -+ .led_hw_is_supported = as21xxx_led_hw_is_supported, -+ .led_hw_control_set = as21xxx_led_hw_control_set, -+ .led_hw_control_get = as21xxx_led_hw_control_get, -+ .led_polarity_set = as21xxx_led_polarity_set, -+ }, -+}; -+module_phy_driver(as21xxx_drivers); -+ -+static struct mdio_device_id __maybe_unused as21xxx_tbl[] = { -+ { PHY_ID_MATCH_VENDOR(PHY_VENDOR_AEONSEMI) }, -+ { } -+}; -+MODULE_DEVICE_TABLE(mdio, as21xxx_tbl); -+ -+MODULE_DESCRIPTION("Aeonsemi AS21xxx PHY driver"); -+MODULE_AUTHOR("Christian Marangi "); -+MODULE_LICENSE("GPL"); diff --git a/target/linux/generic/backport-6.18/783-01-v6.18-net-dsa-Move-KS8995-to-the-DSA-subsystem.patch b/target/linux/generic/backport-6.18/783-01-v6.18-net-dsa-Move-KS8995-to-the-DSA-subsystem.patch deleted file mode 100644 index b91c0cd8cf..0000000000 --- a/target/linux/generic/backport-6.18/783-01-v6.18-net-dsa-Move-KS8995-to-the-DSA-subsystem.patch +++ /dev/null @@ -1,1092 +0,0 @@ -From 9c370f7f92b0232fe925ca2caefb5e3126a0357d Mon Sep 17 00:00:00 2001 -From: Linus Walleij -Date: Wed, 13 Aug 2025 23:43:03 +0200 -Subject: [PATCH 1/4] net: dsa: Move KS8995 to the DSA subsystem - -By reading the datasheets for the KS8995 it is obvious that this -is a 100 Mbit DSA switch. - -Let us start the refactoring by moving it to the DSA subsystem to -preserve development history. - -Verified that the chip still probes the same after this patch -provided CONFIG_HAVE_NET_DSA, CONFIG_NET_DSA and CONFIG_DSA_KS8995 -are selected. - -Signed-off-by: Linus Walleij -Reviewed-by: Andrew Lunn -Link: https://patch.msgid.link/20250813-ks8995-to-dsa-v1-1-75c359ede3a5@linaro.org -Signed-off-by: Jakub Kicinski ---- - drivers/net/dsa/Kconfig | 7 +++++++ - drivers/net/dsa/Makefile | 1 + - drivers/net/{phy/spi_ks8995.c => dsa/ks8995.c} | 0 - drivers/net/phy/Kconfig | 4 ---- - drivers/net/phy/Makefile | 1 - - 5 files changed, 8 insertions(+), 5 deletions(-) - rename drivers/net/{phy/spi_ks8995.c => dsa/ks8995.c} (100%) - ---- a/drivers/net/dsa/Kconfig -+++ b/drivers/net/dsa/Kconfig -@@ -100,6 +100,13 @@ config NET_DSA_RZN1_A5PSW - This driver supports the A5PSW switch, which is embedded in Renesas - RZ/N1 SoC. - -+config NET_DSA_KS8995 -+ tristate "Micrel KS8995 family 5-ports 10/100 Ethernet switches" -+ depends on SPI -+ help -+ This driver supports the Micrel KS8995 family of 10/100 Mbit ethernet -+ switches, managed over SPI. -+ - config NET_DSA_SMSC_LAN9303 - tristate - select NET_DSA_TAG_LAN9303 ---- a/drivers/net/dsa/Makefile -+++ b/drivers/net/dsa/Makefile -@@ -5,6 +5,7 @@ obj-$(CONFIG_NET_DSA_LOOP) += dsa_loop.o - ifdef CONFIG_NET_DSA_LOOP - obj-$(CONFIG_FIXED_PHY) += dsa_loop_bdinfo.o - endif -+obj-$(CONFIG_NET_DSA_KS8995) += ks8995.o - obj-$(CONFIG_NET_DSA_LANTIQ_GSWIP) += lantiq_gswip.o - obj-$(CONFIG_NET_DSA_MT7530) += mt7530.o - obj-$(CONFIG_NET_DSA_MT7530_MDIO) += mt7530-mdio.o ---- a/drivers/net/phy/Kconfig -+++ b/drivers/net/phy/Kconfig -@@ -443,7 +443,3 @@ config XILINX_GMII2RGMII - Ethernet physical media devices and the Gigabit Ethernet controller. - - endif # PHYLIB -- --config MICREL_KS8995MA -- tristate "Micrel KS8995MA 5-ports 10/100 managed Ethernet switch" -- depends on SPI ---- a/drivers/net/phy/Makefile -+++ b/drivers/net/phy/Makefile -@@ -77,7 +77,6 @@ obj-$(CONFIG_MARVELL_88X2222_PHY) += mar - obj-$(CONFIG_MAXLINEAR_GPHY) += mxl-gpy.o - obj-y += mediatek/ - obj-$(CONFIG_MESON_GXL_PHY) += meson-gxl.o --obj-$(CONFIG_MICREL_KS8995MA) += spi_ks8995.o - obj-$(CONFIG_MICREL_PHY) += micrel.o - obj-$(CONFIG_MICROCHIP_PHY) += microchip.o - obj-$(CONFIG_MICROCHIP_T1_PHY) += microchip_t1.o ---- /dev/null -+++ b/drivers/net/dsa/ks8995.c -@@ -0,0 +1,506 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * SPI driver for Micrel/Kendin KS8995M and KSZ8864RMN ethernet switches -+ * -+ * Copyright (C) 2008 Gabor Juhos -+ * -+ * This file was based on: drivers/spi/at25.c -+ * Copyright (C) 2006 David Brownell -+ */ -+ -+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#define DRV_VERSION "0.1.1" -+#define DRV_DESC "Micrel KS8995 Ethernet switch SPI driver" -+ -+/* ------------------------------------------------------------------------ */ -+ -+#define KS8995_REG_ID0 0x00 /* Chip ID0 */ -+#define KS8995_REG_ID1 0x01 /* Chip ID1 */ -+ -+#define KS8995_REG_GC0 0x02 /* Global Control 0 */ -+#define KS8995_REG_GC1 0x03 /* Global Control 1 */ -+#define KS8995_REG_GC2 0x04 /* Global Control 2 */ -+#define KS8995_REG_GC3 0x05 /* Global Control 3 */ -+#define KS8995_REG_GC4 0x06 /* Global Control 4 */ -+#define KS8995_REG_GC5 0x07 /* Global Control 5 */ -+#define KS8995_REG_GC6 0x08 /* Global Control 6 */ -+#define KS8995_REG_GC7 0x09 /* Global Control 7 */ -+#define KS8995_REG_GC8 0x0a /* Global Control 8 */ -+#define KS8995_REG_GC9 0x0b /* Global Control 9 */ -+ -+#define KS8995_REG_PC(p, r) ((0x10 * p) + r) /* Port Control */ -+#define KS8995_REG_PS(p, r) ((0x10 * p) + r + 0xe) /* Port Status */ -+ -+#define KS8995_REG_TPC0 0x60 /* TOS Priority Control 0 */ -+#define KS8995_REG_TPC1 0x61 /* TOS Priority Control 1 */ -+#define KS8995_REG_TPC2 0x62 /* TOS Priority Control 2 */ -+#define KS8995_REG_TPC3 0x63 /* TOS Priority Control 3 */ -+#define KS8995_REG_TPC4 0x64 /* TOS Priority Control 4 */ -+#define KS8995_REG_TPC5 0x65 /* TOS Priority Control 5 */ -+#define KS8995_REG_TPC6 0x66 /* TOS Priority Control 6 */ -+#define KS8995_REG_TPC7 0x67 /* TOS Priority Control 7 */ -+ -+#define KS8995_REG_MAC0 0x68 /* MAC address 0 */ -+#define KS8995_REG_MAC1 0x69 /* MAC address 1 */ -+#define KS8995_REG_MAC2 0x6a /* MAC address 2 */ -+#define KS8995_REG_MAC3 0x6b /* MAC address 3 */ -+#define KS8995_REG_MAC4 0x6c /* MAC address 4 */ -+#define KS8995_REG_MAC5 0x6d /* MAC address 5 */ -+ -+#define KS8995_REG_IAC0 0x6e /* Indirect Access Control 0 */ -+#define KS8995_REG_IAC1 0x6f /* Indirect Access Control 0 */ -+#define KS8995_REG_IAD7 0x70 /* Indirect Access Data 7 */ -+#define KS8995_REG_IAD6 0x71 /* Indirect Access Data 6 */ -+#define KS8995_REG_IAD5 0x72 /* Indirect Access Data 5 */ -+#define KS8995_REG_IAD4 0x73 /* Indirect Access Data 4 */ -+#define KS8995_REG_IAD3 0x74 /* Indirect Access Data 3 */ -+#define KS8995_REG_IAD2 0x75 /* Indirect Access Data 2 */ -+#define KS8995_REG_IAD1 0x76 /* Indirect Access Data 1 */ -+#define KS8995_REG_IAD0 0x77 /* Indirect Access Data 0 */ -+ -+#define KSZ8864_REG_ID1 0xfe /* Chip ID in bit 7 */ -+ -+#define KS8995_REGS_SIZE 0x80 -+#define KSZ8864_REGS_SIZE 0x100 -+#define KSZ8795_REGS_SIZE 0x100 -+ -+#define ID1_CHIPID_M 0xf -+#define ID1_CHIPID_S 4 -+#define ID1_REVISION_M 0x7 -+#define ID1_REVISION_S 1 -+#define ID1_START_SW 1 /* start the switch */ -+ -+#define FAMILY_KS8995 0x95 -+#define FAMILY_KSZ8795 0x87 -+#define CHIPID_M 0 -+#define KS8995_CHIP_ID 0x00 -+#define KSZ8864_CHIP_ID 0x01 -+#define KSZ8795_CHIP_ID 0x09 -+ -+#define KS8995_CMD_WRITE 0x02U -+#define KS8995_CMD_READ 0x03U -+ -+#define KS8995_RESET_DELAY 10 /* usec */ -+ -+enum ks8995_chip_variant { -+ ks8995, -+ ksz8864, -+ ksz8795, -+ max_variant -+}; -+ -+struct ks8995_chip_params { -+ char *name; -+ int family_id; -+ int chip_id; -+ int regs_size; -+ int addr_width; -+ int addr_shift; -+}; -+ -+static const struct ks8995_chip_params ks8995_chip[] = { -+ [ks8995] = { -+ .name = "KS8995MA", -+ .family_id = FAMILY_KS8995, -+ .chip_id = KS8995_CHIP_ID, -+ .regs_size = KS8995_REGS_SIZE, -+ .addr_width = 8, -+ .addr_shift = 0, -+ }, -+ [ksz8864] = { -+ .name = "KSZ8864RMN", -+ .family_id = FAMILY_KS8995, -+ .chip_id = KSZ8864_CHIP_ID, -+ .regs_size = KSZ8864_REGS_SIZE, -+ .addr_width = 8, -+ .addr_shift = 0, -+ }, -+ [ksz8795] = { -+ .name = "KSZ8795CLX", -+ .family_id = FAMILY_KSZ8795, -+ .chip_id = KSZ8795_CHIP_ID, -+ .regs_size = KSZ8795_REGS_SIZE, -+ .addr_width = 12, -+ .addr_shift = 1, -+ }, -+}; -+ -+struct ks8995_switch { -+ struct spi_device *spi; -+ struct mutex lock; -+ struct gpio_desc *reset_gpio; -+ struct bin_attribute regs_attr; -+ const struct ks8995_chip_params *chip; -+ int revision_id; -+}; -+ -+static const struct spi_device_id ks8995_id[] = { -+ {"ks8995", ks8995}, -+ {"ksz8864", ksz8864}, -+ {"ksz8795", ksz8795}, -+ { } -+}; -+MODULE_DEVICE_TABLE(spi, ks8995_id); -+ -+static const struct of_device_id ks8895_spi_of_match[] = { -+ { .compatible = "micrel,ks8995" }, -+ { .compatible = "micrel,ksz8864" }, -+ { .compatible = "micrel,ksz8795" }, -+ { }, -+}; -+MODULE_DEVICE_TABLE(of, ks8895_spi_of_match); -+ -+static inline u8 get_chip_id(u8 val) -+{ -+ return (val >> ID1_CHIPID_S) & ID1_CHIPID_M; -+} -+ -+static inline u8 get_chip_rev(u8 val) -+{ -+ return (val >> ID1_REVISION_S) & ID1_REVISION_M; -+} -+ -+/* create_spi_cmd - create a chip specific SPI command header -+ * @ks: pointer to switch instance -+ * @cmd: SPI command for switch -+ * @address: register address for command -+ * -+ * Different chip families use different bit pattern to address the switches -+ * registers: -+ * -+ * KS8995: 8bit command + 8bit address -+ * KSZ8795: 3bit command + 12bit address + 1bit TR (?) -+ */ -+static inline __be16 create_spi_cmd(struct ks8995_switch *ks, int cmd, -+ unsigned address) -+{ -+ u16 result = cmd; -+ -+ /* make room for address (incl. address shift) */ -+ result <<= ks->chip->addr_width + ks->chip->addr_shift; -+ /* add address */ -+ result |= address << ks->chip->addr_shift; -+ /* SPI protocol needs big endian */ -+ return cpu_to_be16(result); -+} -+/* ------------------------------------------------------------------------ */ -+static int ks8995_read(struct ks8995_switch *ks, char *buf, -+ unsigned offset, size_t count) -+{ -+ __be16 cmd; -+ struct spi_transfer t[2]; -+ struct spi_message m; -+ int err; -+ -+ cmd = create_spi_cmd(ks, KS8995_CMD_READ, offset); -+ spi_message_init(&m); -+ -+ memset(&t, 0, sizeof(t)); -+ -+ t[0].tx_buf = &cmd; -+ t[0].len = sizeof(cmd); -+ spi_message_add_tail(&t[0], &m); -+ -+ t[1].rx_buf = buf; -+ t[1].len = count; -+ spi_message_add_tail(&t[1], &m); -+ -+ mutex_lock(&ks->lock); -+ err = spi_sync(ks->spi, &m); -+ mutex_unlock(&ks->lock); -+ -+ return err ? err : count; -+} -+ -+static int ks8995_write(struct ks8995_switch *ks, char *buf, -+ unsigned offset, size_t count) -+{ -+ __be16 cmd; -+ struct spi_transfer t[2]; -+ struct spi_message m; -+ int err; -+ -+ cmd = create_spi_cmd(ks, KS8995_CMD_WRITE, offset); -+ spi_message_init(&m); -+ -+ memset(&t, 0, sizeof(t)); -+ -+ t[0].tx_buf = &cmd; -+ t[0].len = sizeof(cmd); -+ spi_message_add_tail(&t[0], &m); -+ -+ t[1].tx_buf = buf; -+ t[1].len = count; -+ spi_message_add_tail(&t[1], &m); -+ -+ mutex_lock(&ks->lock); -+ err = spi_sync(ks->spi, &m); -+ mutex_unlock(&ks->lock); -+ -+ return err ? err : count; -+} -+ -+static inline int ks8995_read_reg(struct ks8995_switch *ks, u8 addr, u8 *buf) -+{ -+ return ks8995_read(ks, buf, addr, 1) != 1; -+} -+ -+static inline int ks8995_write_reg(struct ks8995_switch *ks, u8 addr, u8 val) -+{ -+ char buf = val; -+ -+ return ks8995_write(ks, &buf, addr, 1) != 1; -+} -+ -+/* ------------------------------------------------------------------------ */ -+ -+static int ks8995_stop(struct ks8995_switch *ks) -+{ -+ return ks8995_write_reg(ks, KS8995_REG_ID1, 0); -+} -+ -+static int ks8995_start(struct ks8995_switch *ks) -+{ -+ return ks8995_write_reg(ks, KS8995_REG_ID1, 1); -+} -+ -+static int ks8995_reset(struct ks8995_switch *ks) -+{ -+ int err; -+ -+ err = ks8995_stop(ks); -+ if (err) -+ return err; -+ -+ udelay(KS8995_RESET_DELAY); -+ -+ return ks8995_start(ks); -+} -+ -+static ssize_t ks8995_registers_read(struct file *filp, struct kobject *kobj, -+ struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) -+{ -+ struct device *dev; -+ struct ks8995_switch *ks8995; -+ -+ dev = kobj_to_dev(kobj); -+ ks8995 = dev_get_drvdata(dev); -+ -+ return ks8995_read(ks8995, buf, off, count); -+} -+ -+static ssize_t ks8995_registers_write(struct file *filp, struct kobject *kobj, -+ struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) -+{ -+ struct device *dev; -+ struct ks8995_switch *ks8995; -+ -+ dev = kobj_to_dev(kobj); -+ ks8995 = dev_get_drvdata(dev); -+ -+ return ks8995_write(ks8995, buf, off, count); -+} -+ -+/* ks8995_get_revision - get chip revision -+ * @ks: pointer to switch instance -+ * -+ * Verify chip family and id and get chip revision. -+ */ -+static int ks8995_get_revision(struct ks8995_switch *ks) -+{ -+ int err; -+ u8 id0, id1, ksz8864_id; -+ -+ /* read family id */ -+ err = ks8995_read_reg(ks, KS8995_REG_ID0, &id0); -+ if (err) { -+ err = -EIO; -+ goto err_out; -+ } -+ -+ /* verify family id */ -+ if (id0 != ks->chip->family_id) { -+ dev_err(&ks->spi->dev, "chip family id mismatch: expected 0x%02x but 0x%02x read\n", -+ ks->chip->family_id, id0); -+ err = -ENODEV; -+ goto err_out; -+ } -+ -+ switch (ks->chip->family_id) { -+ case FAMILY_KS8995: -+ /* try reading chip id at CHIP ID1 */ -+ err = ks8995_read_reg(ks, KS8995_REG_ID1, &id1); -+ if (err) { -+ err = -EIO; -+ goto err_out; -+ } -+ -+ /* verify chip id */ -+ if ((get_chip_id(id1) == CHIPID_M) && -+ (get_chip_id(id1) == ks->chip->chip_id)) { -+ /* KS8995MA */ -+ ks->revision_id = get_chip_rev(id1); -+ } else if (get_chip_id(id1) != CHIPID_M) { -+ /* KSZ8864RMN */ -+ err = ks8995_read_reg(ks, KS8995_REG_ID1, &ksz8864_id); -+ if (err) { -+ err = -EIO; -+ goto err_out; -+ } -+ -+ if ((ksz8864_id & 0x80) && -+ (ks->chip->chip_id == KSZ8864_CHIP_ID)) { -+ ks->revision_id = get_chip_rev(id1); -+ } -+ -+ } else { -+ dev_err(&ks->spi->dev, "unsupported chip id for KS8995 family: 0x%02x\n", -+ id1); -+ err = -ENODEV; -+ } -+ break; -+ case FAMILY_KSZ8795: -+ /* try reading chip id at CHIP ID1 */ -+ err = ks8995_read_reg(ks, KS8995_REG_ID1, &id1); -+ if (err) { -+ err = -EIO; -+ goto err_out; -+ } -+ -+ if (get_chip_id(id1) == ks->chip->chip_id) { -+ ks->revision_id = get_chip_rev(id1); -+ } else { -+ dev_err(&ks->spi->dev, "unsupported chip id for KSZ8795 family: 0x%02x\n", -+ id1); -+ err = -ENODEV; -+ } -+ break; -+ default: -+ dev_err(&ks->spi->dev, "unsupported family id: 0x%02x\n", id0); -+ err = -ENODEV; -+ break; -+ } -+err_out: -+ return err; -+} -+ -+static const struct bin_attribute ks8995_registers_attr = { -+ .attr = { -+ .name = "registers", -+ .mode = 0600, -+ }, -+ .size = KS8995_REGS_SIZE, -+ .read = ks8995_registers_read, -+ .write = ks8995_registers_write, -+}; -+ -+/* ------------------------------------------------------------------------ */ -+static int ks8995_probe(struct spi_device *spi) -+{ -+ struct ks8995_switch *ks; -+ int err; -+ int variant = spi_get_device_id(spi)->driver_data; -+ -+ if (variant >= max_variant) { -+ dev_err(&spi->dev, "bad chip variant %d\n", variant); -+ return -ENODEV; -+ } -+ -+ ks = devm_kzalloc(&spi->dev, sizeof(*ks), GFP_KERNEL); -+ if (!ks) -+ return -ENOMEM; -+ -+ mutex_init(&ks->lock); -+ ks->spi = spi; -+ ks->chip = &ks8995_chip[variant]; -+ -+ ks->reset_gpio = devm_gpiod_get_optional(&spi->dev, "reset", -+ GPIOD_OUT_HIGH); -+ err = PTR_ERR_OR_ZERO(ks->reset_gpio); -+ if (err) { -+ dev_err(&spi->dev, -+ "failed to get reset gpio: %d\n", err); -+ return err; -+ } -+ -+ err = gpiod_set_consumer_name(ks->reset_gpio, "switch-reset"); -+ if (err) -+ return err; -+ -+ /* de-assert switch reset */ -+ /* FIXME: this likely requires a delay */ -+ gpiod_set_value_cansleep(ks->reset_gpio, 0); -+ -+ spi_set_drvdata(spi, ks); -+ -+ spi->mode = SPI_MODE_0; -+ spi->bits_per_word = 8; -+ err = spi_setup(spi); -+ if (err) { -+ dev_err(&spi->dev, "spi_setup failed, err=%d\n", err); -+ return err; -+ } -+ -+ err = ks8995_get_revision(ks); -+ if (err) -+ return err; -+ -+ memcpy(&ks->regs_attr, &ks8995_registers_attr, sizeof(ks->regs_attr)); -+ ks->regs_attr.size = ks->chip->regs_size; -+ -+ err = ks8995_reset(ks); -+ if (err) -+ return err; -+ -+ sysfs_attr_init(&ks->regs_attr.attr); -+ err = sysfs_create_bin_file(&spi->dev.kobj, &ks->regs_attr); -+ if (err) { -+ dev_err(&spi->dev, "unable to create sysfs file, err=%d\n", -+ err); -+ return err; -+ } -+ -+ dev_info(&spi->dev, "%s device found, Chip ID:%x, Revision:%x\n", -+ ks->chip->name, ks->chip->chip_id, ks->revision_id); -+ -+ return 0; -+} -+ -+static void ks8995_remove(struct spi_device *spi) -+{ -+ struct ks8995_switch *ks = spi_get_drvdata(spi); -+ -+ sysfs_remove_bin_file(&spi->dev.kobj, &ks->regs_attr); -+ -+ /* assert reset */ -+ gpiod_set_value_cansleep(ks->reset_gpio, 1); -+} -+ -+/* ------------------------------------------------------------------------ */ -+static struct spi_driver ks8995_driver = { -+ .driver = { -+ .name = "spi-ks8995", -+ .of_match_table = ks8895_spi_of_match, -+ }, -+ .probe = ks8995_probe, -+ .remove = ks8995_remove, -+ .id_table = ks8995_id, -+}; -+ -+module_spi_driver(ks8995_driver); -+ -+MODULE_DESCRIPTION(DRV_DESC); -+MODULE_VERSION(DRV_VERSION); -+MODULE_AUTHOR("Gabor Juhos "); -+MODULE_LICENSE("GPL v2"); ---- a/drivers/net/phy/spi_ks8995.c -+++ /dev/null -@@ -1,506 +0,0 @@ --// SPDX-License-Identifier: GPL-2.0 --/* -- * SPI driver for Micrel/Kendin KS8995M and KSZ8864RMN ethernet switches -- * -- * Copyright (C) 2008 Gabor Juhos -- * -- * This file was based on: drivers/spi/at25.c -- * Copyright (C) 2006 David Brownell -- */ -- --#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -- --#include --#include --#include --#include --#include --#include --#include -- --#include -- --#define DRV_VERSION "0.1.1" --#define DRV_DESC "Micrel KS8995 Ethernet switch SPI driver" -- --/* ------------------------------------------------------------------------ */ -- --#define KS8995_REG_ID0 0x00 /* Chip ID0 */ --#define KS8995_REG_ID1 0x01 /* Chip ID1 */ -- --#define KS8995_REG_GC0 0x02 /* Global Control 0 */ --#define KS8995_REG_GC1 0x03 /* Global Control 1 */ --#define KS8995_REG_GC2 0x04 /* Global Control 2 */ --#define KS8995_REG_GC3 0x05 /* Global Control 3 */ --#define KS8995_REG_GC4 0x06 /* Global Control 4 */ --#define KS8995_REG_GC5 0x07 /* Global Control 5 */ --#define KS8995_REG_GC6 0x08 /* Global Control 6 */ --#define KS8995_REG_GC7 0x09 /* Global Control 7 */ --#define KS8995_REG_GC8 0x0a /* Global Control 8 */ --#define KS8995_REG_GC9 0x0b /* Global Control 9 */ -- --#define KS8995_REG_PC(p, r) ((0x10 * p) + r) /* Port Control */ --#define KS8995_REG_PS(p, r) ((0x10 * p) + r + 0xe) /* Port Status */ -- --#define KS8995_REG_TPC0 0x60 /* TOS Priority Control 0 */ --#define KS8995_REG_TPC1 0x61 /* TOS Priority Control 1 */ --#define KS8995_REG_TPC2 0x62 /* TOS Priority Control 2 */ --#define KS8995_REG_TPC3 0x63 /* TOS Priority Control 3 */ --#define KS8995_REG_TPC4 0x64 /* TOS Priority Control 4 */ --#define KS8995_REG_TPC5 0x65 /* TOS Priority Control 5 */ --#define KS8995_REG_TPC6 0x66 /* TOS Priority Control 6 */ --#define KS8995_REG_TPC7 0x67 /* TOS Priority Control 7 */ -- --#define KS8995_REG_MAC0 0x68 /* MAC address 0 */ --#define KS8995_REG_MAC1 0x69 /* MAC address 1 */ --#define KS8995_REG_MAC2 0x6a /* MAC address 2 */ --#define KS8995_REG_MAC3 0x6b /* MAC address 3 */ --#define KS8995_REG_MAC4 0x6c /* MAC address 4 */ --#define KS8995_REG_MAC5 0x6d /* MAC address 5 */ -- --#define KS8995_REG_IAC0 0x6e /* Indirect Access Control 0 */ --#define KS8995_REG_IAC1 0x6f /* Indirect Access Control 0 */ --#define KS8995_REG_IAD7 0x70 /* Indirect Access Data 7 */ --#define KS8995_REG_IAD6 0x71 /* Indirect Access Data 6 */ --#define KS8995_REG_IAD5 0x72 /* Indirect Access Data 5 */ --#define KS8995_REG_IAD4 0x73 /* Indirect Access Data 4 */ --#define KS8995_REG_IAD3 0x74 /* Indirect Access Data 3 */ --#define KS8995_REG_IAD2 0x75 /* Indirect Access Data 2 */ --#define KS8995_REG_IAD1 0x76 /* Indirect Access Data 1 */ --#define KS8995_REG_IAD0 0x77 /* Indirect Access Data 0 */ -- --#define KSZ8864_REG_ID1 0xfe /* Chip ID in bit 7 */ -- --#define KS8995_REGS_SIZE 0x80 --#define KSZ8864_REGS_SIZE 0x100 --#define KSZ8795_REGS_SIZE 0x100 -- --#define ID1_CHIPID_M 0xf --#define ID1_CHIPID_S 4 --#define ID1_REVISION_M 0x7 --#define ID1_REVISION_S 1 --#define ID1_START_SW 1 /* start the switch */ -- --#define FAMILY_KS8995 0x95 --#define FAMILY_KSZ8795 0x87 --#define CHIPID_M 0 --#define KS8995_CHIP_ID 0x00 --#define KSZ8864_CHIP_ID 0x01 --#define KSZ8795_CHIP_ID 0x09 -- --#define KS8995_CMD_WRITE 0x02U --#define KS8995_CMD_READ 0x03U -- --#define KS8995_RESET_DELAY 10 /* usec */ -- --enum ks8995_chip_variant { -- ks8995, -- ksz8864, -- ksz8795, -- max_variant --}; -- --struct ks8995_chip_params { -- char *name; -- int family_id; -- int chip_id; -- int regs_size; -- int addr_width; -- int addr_shift; --}; -- --static const struct ks8995_chip_params ks8995_chip[] = { -- [ks8995] = { -- .name = "KS8995MA", -- .family_id = FAMILY_KS8995, -- .chip_id = KS8995_CHIP_ID, -- .regs_size = KS8995_REGS_SIZE, -- .addr_width = 8, -- .addr_shift = 0, -- }, -- [ksz8864] = { -- .name = "KSZ8864RMN", -- .family_id = FAMILY_KS8995, -- .chip_id = KSZ8864_CHIP_ID, -- .regs_size = KSZ8864_REGS_SIZE, -- .addr_width = 8, -- .addr_shift = 0, -- }, -- [ksz8795] = { -- .name = "KSZ8795CLX", -- .family_id = FAMILY_KSZ8795, -- .chip_id = KSZ8795_CHIP_ID, -- .regs_size = KSZ8795_REGS_SIZE, -- .addr_width = 12, -- .addr_shift = 1, -- }, --}; -- --struct ks8995_switch { -- struct spi_device *spi; -- struct mutex lock; -- struct gpio_desc *reset_gpio; -- struct bin_attribute regs_attr; -- const struct ks8995_chip_params *chip; -- int revision_id; --}; -- --static const struct spi_device_id ks8995_id[] = { -- {"ks8995", ks8995}, -- {"ksz8864", ksz8864}, -- {"ksz8795", ksz8795}, -- { } --}; --MODULE_DEVICE_TABLE(spi, ks8995_id); -- --static const struct of_device_id ks8895_spi_of_match[] = { -- { .compatible = "micrel,ks8995" }, -- { .compatible = "micrel,ksz8864" }, -- { .compatible = "micrel,ksz8795" }, -- { }, --}; --MODULE_DEVICE_TABLE(of, ks8895_spi_of_match); -- --static inline u8 get_chip_id(u8 val) --{ -- return (val >> ID1_CHIPID_S) & ID1_CHIPID_M; --} -- --static inline u8 get_chip_rev(u8 val) --{ -- return (val >> ID1_REVISION_S) & ID1_REVISION_M; --} -- --/* create_spi_cmd - create a chip specific SPI command header -- * @ks: pointer to switch instance -- * @cmd: SPI command for switch -- * @address: register address for command -- * -- * Different chip families use different bit pattern to address the switches -- * registers: -- * -- * KS8995: 8bit command + 8bit address -- * KSZ8795: 3bit command + 12bit address + 1bit TR (?) -- */ --static inline __be16 create_spi_cmd(struct ks8995_switch *ks, int cmd, -- unsigned address) --{ -- u16 result = cmd; -- -- /* make room for address (incl. address shift) */ -- result <<= ks->chip->addr_width + ks->chip->addr_shift; -- /* add address */ -- result |= address << ks->chip->addr_shift; -- /* SPI protocol needs big endian */ -- return cpu_to_be16(result); --} --/* ------------------------------------------------------------------------ */ --static int ks8995_read(struct ks8995_switch *ks, char *buf, -- unsigned offset, size_t count) --{ -- __be16 cmd; -- struct spi_transfer t[2]; -- struct spi_message m; -- int err; -- -- cmd = create_spi_cmd(ks, KS8995_CMD_READ, offset); -- spi_message_init(&m); -- -- memset(&t, 0, sizeof(t)); -- -- t[0].tx_buf = &cmd; -- t[0].len = sizeof(cmd); -- spi_message_add_tail(&t[0], &m); -- -- t[1].rx_buf = buf; -- t[1].len = count; -- spi_message_add_tail(&t[1], &m); -- -- mutex_lock(&ks->lock); -- err = spi_sync(ks->spi, &m); -- mutex_unlock(&ks->lock); -- -- return err ? err : count; --} -- --static int ks8995_write(struct ks8995_switch *ks, char *buf, -- unsigned offset, size_t count) --{ -- __be16 cmd; -- struct spi_transfer t[2]; -- struct spi_message m; -- int err; -- -- cmd = create_spi_cmd(ks, KS8995_CMD_WRITE, offset); -- spi_message_init(&m); -- -- memset(&t, 0, sizeof(t)); -- -- t[0].tx_buf = &cmd; -- t[0].len = sizeof(cmd); -- spi_message_add_tail(&t[0], &m); -- -- t[1].tx_buf = buf; -- t[1].len = count; -- spi_message_add_tail(&t[1], &m); -- -- mutex_lock(&ks->lock); -- err = spi_sync(ks->spi, &m); -- mutex_unlock(&ks->lock); -- -- return err ? err : count; --} -- --static inline int ks8995_read_reg(struct ks8995_switch *ks, u8 addr, u8 *buf) --{ -- return ks8995_read(ks, buf, addr, 1) != 1; --} -- --static inline int ks8995_write_reg(struct ks8995_switch *ks, u8 addr, u8 val) --{ -- char buf = val; -- -- return ks8995_write(ks, &buf, addr, 1) != 1; --} -- --/* ------------------------------------------------------------------------ */ -- --static int ks8995_stop(struct ks8995_switch *ks) --{ -- return ks8995_write_reg(ks, KS8995_REG_ID1, 0); --} -- --static int ks8995_start(struct ks8995_switch *ks) --{ -- return ks8995_write_reg(ks, KS8995_REG_ID1, 1); --} -- --static int ks8995_reset(struct ks8995_switch *ks) --{ -- int err; -- -- err = ks8995_stop(ks); -- if (err) -- return err; -- -- udelay(KS8995_RESET_DELAY); -- -- return ks8995_start(ks); --} -- --static ssize_t ks8995_registers_read(struct file *filp, struct kobject *kobj, -- struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) --{ -- struct device *dev; -- struct ks8995_switch *ks8995; -- -- dev = kobj_to_dev(kobj); -- ks8995 = dev_get_drvdata(dev); -- -- return ks8995_read(ks8995, buf, off, count); --} -- --static ssize_t ks8995_registers_write(struct file *filp, struct kobject *kobj, -- struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) --{ -- struct device *dev; -- struct ks8995_switch *ks8995; -- -- dev = kobj_to_dev(kobj); -- ks8995 = dev_get_drvdata(dev); -- -- return ks8995_write(ks8995, buf, off, count); --} -- --/* ks8995_get_revision - get chip revision -- * @ks: pointer to switch instance -- * -- * Verify chip family and id and get chip revision. -- */ --static int ks8995_get_revision(struct ks8995_switch *ks) --{ -- int err; -- u8 id0, id1, ksz8864_id; -- -- /* read family id */ -- err = ks8995_read_reg(ks, KS8995_REG_ID0, &id0); -- if (err) { -- err = -EIO; -- goto err_out; -- } -- -- /* verify family id */ -- if (id0 != ks->chip->family_id) { -- dev_err(&ks->spi->dev, "chip family id mismatch: expected 0x%02x but 0x%02x read\n", -- ks->chip->family_id, id0); -- err = -ENODEV; -- goto err_out; -- } -- -- switch (ks->chip->family_id) { -- case FAMILY_KS8995: -- /* try reading chip id at CHIP ID1 */ -- err = ks8995_read_reg(ks, KS8995_REG_ID1, &id1); -- if (err) { -- err = -EIO; -- goto err_out; -- } -- -- /* verify chip id */ -- if ((get_chip_id(id1) == CHIPID_M) && -- (get_chip_id(id1) == ks->chip->chip_id)) { -- /* KS8995MA */ -- ks->revision_id = get_chip_rev(id1); -- } else if (get_chip_id(id1) != CHIPID_M) { -- /* KSZ8864RMN */ -- err = ks8995_read_reg(ks, KS8995_REG_ID1, &ksz8864_id); -- if (err) { -- err = -EIO; -- goto err_out; -- } -- -- if ((ksz8864_id & 0x80) && -- (ks->chip->chip_id == KSZ8864_CHIP_ID)) { -- ks->revision_id = get_chip_rev(id1); -- } -- -- } else { -- dev_err(&ks->spi->dev, "unsupported chip id for KS8995 family: 0x%02x\n", -- id1); -- err = -ENODEV; -- } -- break; -- case FAMILY_KSZ8795: -- /* try reading chip id at CHIP ID1 */ -- err = ks8995_read_reg(ks, KS8995_REG_ID1, &id1); -- if (err) { -- err = -EIO; -- goto err_out; -- } -- -- if (get_chip_id(id1) == ks->chip->chip_id) { -- ks->revision_id = get_chip_rev(id1); -- } else { -- dev_err(&ks->spi->dev, "unsupported chip id for KSZ8795 family: 0x%02x\n", -- id1); -- err = -ENODEV; -- } -- break; -- default: -- dev_err(&ks->spi->dev, "unsupported family id: 0x%02x\n", id0); -- err = -ENODEV; -- break; -- } --err_out: -- return err; --} -- --static const struct bin_attribute ks8995_registers_attr = { -- .attr = { -- .name = "registers", -- .mode = 0600, -- }, -- .size = KS8995_REGS_SIZE, -- .read = ks8995_registers_read, -- .write = ks8995_registers_write, --}; -- --/* ------------------------------------------------------------------------ */ --static int ks8995_probe(struct spi_device *spi) --{ -- struct ks8995_switch *ks; -- int err; -- int variant = spi_get_device_id(spi)->driver_data; -- -- if (variant >= max_variant) { -- dev_err(&spi->dev, "bad chip variant %d\n", variant); -- return -ENODEV; -- } -- -- ks = devm_kzalloc(&spi->dev, sizeof(*ks), GFP_KERNEL); -- if (!ks) -- return -ENOMEM; -- -- mutex_init(&ks->lock); -- ks->spi = spi; -- ks->chip = &ks8995_chip[variant]; -- -- ks->reset_gpio = devm_gpiod_get_optional(&spi->dev, "reset", -- GPIOD_OUT_HIGH); -- err = PTR_ERR_OR_ZERO(ks->reset_gpio); -- if (err) { -- dev_err(&spi->dev, -- "failed to get reset gpio: %d\n", err); -- return err; -- } -- -- err = gpiod_set_consumer_name(ks->reset_gpio, "switch-reset"); -- if (err) -- return err; -- -- /* de-assert switch reset */ -- /* FIXME: this likely requires a delay */ -- gpiod_set_value_cansleep(ks->reset_gpio, 0); -- -- spi_set_drvdata(spi, ks); -- -- spi->mode = SPI_MODE_0; -- spi->bits_per_word = 8; -- err = spi_setup(spi); -- if (err) { -- dev_err(&spi->dev, "spi_setup failed, err=%d\n", err); -- return err; -- } -- -- err = ks8995_get_revision(ks); -- if (err) -- return err; -- -- memcpy(&ks->regs_attr, &ks8995_registers_attr, sizeof(ks->regs_attr)); -- ks->regs_attr.size = ks->chip->regs_size; -- -- err = ks8995_reset(ks); -- if (err) -- return err; -- -- sysfs_attr_init(&ks->regs_attr.attr); -- err = sysfs_create_bin_file(&spi->dev.kobj, &ks->regs_attr); -- if (err) { -- dev_err(&spi->dev, "unable to create sysfs file, err=%d\n", -- err); -- return err; -- } -- -- dev_info(&spi->dev, "%s device found, Chip ID:%x, Revision:%x\n", -- ks->chip->name, ks->chip->chip_id, ks->revision_id); -- -- return 0; --} -- --static void ks8995_remove(struct spi_device *spi) --{ -- struct ks8995_switch *ks = spi_get_drvdata(spi); -- -- sysfs_remove_bin_file(&spi->dev.kobj, &ks->regs_attr); -- -- /* assert reset */ -- gpiod_set_value_cansleep(ks->reset_gpio, 1); --} -- --/* ------------------------------------------------------------------------ */ --static struct spi_driver ks8995_driver = { -- .driver = { -- .name = "spi-ks8995", -- .of_match_table = ks8895_spi_of_match, -- }, -- .probe = ks8995_probe, -- .remove = ks8995_remove, -- .id_table = ks8995_id, --}; -- --module_spi_driver(ks8995_driver); -- --MODULE_DESCRIPTION(DRV_DESC); --MODULE_VERSION(DRV_VERSION); --MODULE_AUTHOR("Gabor Juhos "); --MODULE_LICENSE("GPL v2"); diff --git a/target/linux/generic/backport-6.18/783-02-v6.18-net-dsa-ks8995-Add-proper-RESET-delay.patch b/target/linux/generic/backport-6.18/783-02-v6.18-net-dsa-ks8995-Add-proper-RESET-delay.patch deleted file mode 100644 index 3b0b731d4b..0000000000 --- a/target/linux/generic/backport-6.18/783-02-v6.18-net-dsa-ks8995-Add-proper-RESET-delay.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 7367bfc8b34d7ad5b0c06e19fe24533db22ed8ea Mon Sep 17 00:00:00 2001 -From: Linus Walleij -Date: Wed, 13 Aug 2025 23:43:04 +0200 -Subject: [PATCH 2/4] net: dsa: ks8995: Add proper RESET delay - -According to the datasheet we need to wait 100us before accessing -any registers in the KS8995 after a reset de-assertion. - -Add this delay, if and only if we obtained a GPIO descriptor, -otherwise it is just a pointless delay. - -Signed-off-by: Linus Walleij -Reviewed-by: Andrew Lunn -Link: https://patch.msgid.link/20250813-ks8995-to-dsa-v1-2-75c359ede3a5@linaro.org -Signed-off-by: Jakub Kicinski ---- - drivers/net/dsa/ks8995.c | 12 +++++++++--- - 1 file changed, 9 insertions(+), 3 deletions(-) - ---- a/drivers/net/dsa/ks8995.c -+++ b/drivers/net/dsa/ks8995.c -@@ -438,9 +438,15 @@ static int ks8995_probe(struct spi_devic - if (err) - return err; - -- /* de-assert switch reset */ -- /* FIXME: this likely requires a delay */ -- gpiod_set_value_cansleep(ks->reset_gpio, 0); -+ if (ks->reset_gpio) { -+ /* -+ * If a reset line was obtained, wait for 100us after -+ * de-asserting RESET before accessing any registers, see -+ * the KS8995MA datasheet, page 44. -+ */ -+ gpiod_set_value_cansleep(ks->reset_gpio, 0); -+ udelay(100); -+ } - - spi_set_drvdata(spi, ks); - diff --git a/target/linux/generic/backport-6.18/783-03-v6.18-net-dsa-ks8995-Delete-sysfs-register-access.patch b/target/linux/generic/backport-6.18/783-03-v6.18-net-dsa-ks8995-Delete-sysfs-register-access.patch deleted file mode 100644 index 78b9141ed7..0000000000 --- a/target/linux/generic/backport-6.18/783-03-v6.18-net-dsa-ks8995-Delete-sysfs-register-access.patch +++ /dev/null @@ -1,109 +0,0 @@ -From 0e8d3f3623a45f69b6641ff9921ecd0c5afaa4ca Mon Sep 17 00:00:00 2001 -From: Linus Walleij -Date: Wed, 13 Aug 2025 23:43:05 +0200 -Subject: [PATCH 3/4] net: dsa: ks8995: Delete sysfs register access - -There is some sysfs file to read and write registers randomly -in the ks8995 driver. - -The contemporary way to achieve the same thing is to implement -regmap abstractions, if needed. Delete this and implement -regmap later if we want to be able to inspect individual registers. - -Signed-off-by: Linus Walleij -Reviewed-by: Andrew Lunn -Link: https://patch.msgid.link/20250813-ks8995-to-dsa-v1-3-75c359ede3a5@linaro.org -Signed-off-by: Jakub Kicinski ---- - drivers/net/dsa/ks8995.c | 48 ---------------------------------------- - 1 file changed, 48 deletions(-) - ---- a/drivers/net/dsa/ks8995.c -+++ b/drivers/net/dsa/ks8995.c -@@ -140,7 +140,6 @@ struct ks8995_switch { - struct spi_device *spi; - struct mutex lock; - struct gpio_desc *reset_gpio; -- struct bin_attribute regs_attr; - const struct ks8995_chip_params *chip; - int revision_id; - }; -@@ -288,30 +287,6 @@ static int ks8995_reset(struct ks8995_sw - return ks8995_start(ks); - } - --static ssize_t ks8995_registers_read(struct file *filp, struct kobject *kobj, -- struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) --{ -- struct device *dev; -- struct ks8995_switch *ks8995; -- -- dev = kobj_to_dev(kobj); -- ks8995 = dev_get_drvdata(dev); -- -- return ks8995_read(ks8995, buf, off, count); --} -- --static ssize_t ks8995_registers_write(struct file *filp, struct kobject *kobj, -- struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) --{ -- struct device *dev; -- struct ks8995_switch *ks8995; -- -- dev = kobj_to_dev(kobj); -- ks8995 = dev_get_drvdata(dev); -- -- return ks8995_write(ks8995, buf, off, count); --} -- - /* ks8995_get_revision - get chip revision - * @ks: pointer to switch instance - * -@@ -395,16 +370,6 @@ err_out: - return err; - } - --static const struct bin_attribute ks8995_registers_attr = { -- .attr = { -- .name = "registers", -- .mode = 0600, -- }, -- .size = KS8995_REGS_SIZE, -- .read = ks8995_registers_read, -- .write = ks8995_registers_write, --}; -- - /* ------------------------------------------------------------------------ */ - static int ks8995_probe(struct spi_device *spi) - { -@@ -462,21 +427,10 @@ static int ks8995_probe(struct spi_devic - if (err) - return err; - -- memcpy(&ks->regs_attr, &ks8995_registers_attr, sizeof(ks->regs_attr)); -- ks->regs_attr.size = ks->chip->regs_size; -- - err = ks8995_reset(ks); - if (err) - return err; - -- sysfs_attr_init(&ks->regs_attr.attr); -- err = sysfs_create_bin_file(&spi->dev.kobj, &ks->regs_attr); -- if (err) { -- dev_err(&spi->dev, "unable to create sysfs file, err=%d\n", -- err); -- return err; -- } -- - dev_info(&spi->dev, "%s device found, Chip ID:%x, Revision:%x\n", - ks->chip->name, ks->chip->chip_id, ks->revision_id); - -@@ -487,8 +441,6 @@ static void ks8995_remove(struct spi_dev - { - struct ks8995_switch *ks = spi_get_drvdata(spi); - -- sysfs_remove_bin_file(&spi->dev.kobj, &ks->regs_attr); -- - /* assert reset */ - gpiod_set_value_cansleep(ks->reset_gpio, 1); - } diff --git a/target/linux/generic/backport-6.18/783-04-v6.18-net-dsa-ks8995-Add-basic-switch-set-up.patch b/target/linux/generic/backport-6.18/783-04-v6.18-net-dsa-ks8995-Add-basic-switch-set-up.patch deleted file mode 100644 index 3454e113ba..0000000000 --- a/target/linux/generic/backport-6.18/783-04-v6.18-net-dsa-ks8995-Add-basic-switch-set-up.patch +++ /dev/null @@ -1,546 +0,0 @@ -From 4b486b63e07313e1e3807f9d5e6636aa564e0fbc Mon Sep 17 00:00:00 2001 -From: Linus Walleij -Date: Wed, 13 Aug 2025 23:43:06 +0200 -Subject: [PATCH 4/4] net: dsa: ks8995: Add basic switch set-up - -We start to extend the KS8995 driver by simply registering it -as a DSA device and implementing a few switch callbacks for -STP set-up and such to begin with. - -No special tags or other advanced stuff: we use DSA_TAG_NONE -and rely on the default set-up in the switch with the special -DSA tags turned off. This makes the switch wire up properly -to all its PHY's and simple bridge traffic works properly. - -After this the bridge DT bindings are respected, ports and their -PHYs get connected to the switch and react appropriately through -the phylib when cables are plugged in etc. - -Tested like this in a hacky OpenWrt image: - -Bring up conduit interface manually: -ixp4xx_eth c8009000.ethernet eth0: eth0: link up, - speed 100 Mb/s, full duplex - -spi-ks8995 spi0.0: enable port 0 -spi-ks8995 spi0.0: set KS8995_REG_PC2 for port 0 to 06 -spi-ks8995 spi0.0 lan1: configuring for phy/mii link mode -spi-ks8995 spi0.0 lan1: Link is Up - 100Mbps/Full - flow control rx/tx - -PING 169.254.1.1 (169.254.1.1): 56 data bytes -64 bytes from 169.254.1.1: seq=0 ttl=64 time=1.629 ms -64 bytes from 169.254.1.1: seq=1 ttl=64 time=0.951 ms - -I also tested SSH from the device to the host and it works fine. - -It also works fine to ping the device from the host and to SSH -into the device from the host. - -This brings the ks8995 driver to a reasonable state where it can -be used from the current device tree bindings and the existing -device trees in the kernel. - -Signed-off-by: Linus Walleij -Reviewed-by: Andrew Lunn -Link: https://patch.msgid.link/20250813-ks8995-to-dsa-v1-4-75c359ede3a5@linaro.org -Signed-off-by: Jakub Kicinski ---- - drivers/net/dsa/Kconfig | 1 + - drivers/net/dsa/ks8995.c | 398 ++++++++++++++++++++++++++++++++++++++- - 2 files changed, 396 insertions(+), 3 deletions(-) - ---- a/drivers/net/dsa/Kconfig -+++ b/drivers/net/dsa/Kconfig -@@ -103,6 +103,7 @@ config NET_DSA_RZN1_A5PSW - config NET_DSA_KS8995 - tristate "Micrel KS8995 family 5-ports 10/100 Ethernet switches" - depends on SPI -+ select NET_DSA_TAG_NONE - help - This driver supports the Micrel KS8995 family of 10/100 Mbit ethernet - switches, managed over SPI. ---- a/drivers/net/dsa/ks8995.c -+++ b/drivers/net/dsa/ks8995.c -@@ -3,6 +3,7 @@ - * SPI driver for Micrel/Kendin KS8995M and KSZ8864RMN ethernet switches - * - * Copyright (C) 2008 Gabor Juhos -+ * Copyright (C) 2025 Linus Walleij - * - * This file was based on: drivers/spi/at25.c - * Copyright (C) 2006 David Brownell -@@ -10,6 +11,9 @@ - - #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -+#include -+#include -+#include - #include - #include - #include -@@ -17,8 +21,8 @@ - #include - #include - #include -- - #include -+#include - - #define DRV_VERSION "0.1.1" - #define DRV_DESC "Micrel KS8995 Ethernet switch SPI driver" -@@ -29,18 +33,59 @@ - #define KS8995_REG_ID1 0x01 /* Chip ID1 */ - - #define KS8995_REG_GC0 0x02 /* Global Control 0 */ -+ -+#define KS8995_GC0_P5_PHY BIT(3) /* Port 5 PHY enabled */ -+ - #define KS8995_REG_GC1 0x03 /* Global Control 1 */ - #define KS8995_REG_GC2 0x04 /* Global Control 2 */ -+ -+#define KS8995_GC2_HUGE BIT(2) /* Huge packet support */ -+#define KS8995_GC2_LEGAL BIT(1) /* Legal size override */ -+ - #define KS8995_REG_GC3 0x05 /* Global Control 3 */ - #define KS8995_REG_GC4 0x06 /* Global Control 4 */ -+ -+#define KS8995_GC4_10BT BIT(4) /* Force switch to 10Mbit */ -+#define KS8995_GC4_MII_FLOW BIT(5) /* MII full-duplex flow control enable */ -+#define KS8995_GC4_MII_HD BIT(6) /* MII half-duplex mode enable */ -+ - #define KS8995_REG_GC5 0x07 /* Global Control 5 */ - #define KS8995_REG_GC6 0x08 /* Global Control 6 */ - #define KS8995_REG_GC7 0x09 /* Global Control 7 */ - #define KS8995_REG_GC8 0x0a /* Global Control 8 */ - #define KS8995_REG_GC9 0x0b /* Global Control 9 */ - --#define KS8995_REG_PC(p, r) ((0x10 * p) + r) /* Port Control */ --#define KS8995_REG_PS(p, r) ((0x10 * p) + r + 0xe) /* Port Status */ -+#define KS8995_GC9_SPECIAL BIT(0) /* Special tagging mode (DSA) */ -+ -+/* In DSA the ports 1-4 are numbered 0-3 and the CPU port is port 4 */ -+#define KS8995_REG_PC(p, r) (0x10 + (0x10 * (p)) + (r)) /* Port Control */ -+#define KS8995_REG_PS(p, r) (0x1e + (0x10 * (p)) + (r)) /* Port Status */ -+ -+#define KS8995_REG_PC0 0x00 /* Port Control 0 */ -+#define KS8995_REG_PC1 0x01 /* Port Control 1 */ -+#define KS8995_REG_PC2 0x02 /* Port Control 2 */ -+#define KS8995_REG_PC3 0x03 /* Port Control 3 */ -+#define KS8995_REG_PC4 0x04 /* Port Control 4 */ -+#define KS8995_REG_PC5 0x05 /* Port Control 5 */ -+#define KS8995_REG_PC6 0x06 /* Port Control 6 */ -+#define KS8995_REG_PC7 0x07 /* Port Control 7 */ -+#define KS8995_REG_PC8 0x08 /* Port Control 8 */ -+#define KS8995_REG_PC9 0x09 /* Port Control 9 */ -+#define KS8995_REG_PC10 0x0a /* Port Control 10 */ -+#define KS8995_REG_PC11 0x0b /* Port Control 11 */ -+#define KS8995_REG_PC12 0x0c /* Port Control 12 */ -+#define KS8995_REG_PC13 0x0d /* Port Control 13 */ -+ -+#define KS8995_PC0_TAG_INS BIT(2) /* Enable tag insertion on port */ -+#define KS8995_PC0_TAG_REM BIT(1) /* Enable tag removal on port */ -+#define KS8995_PC0_PRIO_EN BIT(0) /* Enable priority handling */ -+ -+#define KS8995_PC2_TXEN BIT(2) /* Enable TX on port */ -+#define KS8995_PC2_RXEN BIT(1) /* Enable RX on port */ -+#define KS8995_PC2_LEARN_DIS BIT(0) /* Disable learning on port */ -+ -+#define KS8995_PC13_TXDIS BIT(6) /* Disable transmitter */ -+#define KS8995_PC13_PWDN BIT(3) /* Power down */ - - #define KS8995_REG_TPC0 0x60 /* TOS Priority Control 0 */ - #define KS8995_REG_TPC1 0x61 /* TOS Priority Control 1 */ -@@ -91,6 +136,8 @@ - #define KS8995_CMD_WRITE 0x02U - #define KS8995_CMD_READ 0x03U - -+#define KS8995_CPU_PORT 4 -+#define KS8995_NUM_PORTS 5 /* 5 ports including the CPU port */ - #define KS8995_RESET_DELAY 10 /* usec */ - - enum ks8995_chip_variant { -@@ -138,10 +185,13 @@ static const struct ks8995_chip_params k - - struct ks8995_switch { - struct spi_device *spi; -+ struct device *dev; -+ struct dsa_switch *ds; - struct mutex lock; - struct gpio_desc *reset_gpio; - const struct ks8995_chip_params *chip; - int revision_id; -+ unsigned int max_mtu[KS8995_NUM_PORTS]; - }; - - static const struct spi_device_id ks8995_id[] = { -@@ -370,6 +420,327 @@ err_out: - return err; - } - -+static int ks8995_check_config(struct ks8995_switch *ks) -+{ -+ int ret; -+ u8 val; -+ -+ ret = ks8995_read_reg(ks, KS8995_REG_GC0, &val); -+ if (ret) { -+ dev_err(ks->dev, "failed to read KS8995_REG_GC0\n"); -+ return ret; -+ } -+ -+ dev_dbg(ks->dev, "port 5 PHY %senabled\n", -+ (val & KS8995_GC0_P5_PHY) ? "" : "not "); -+ -+ val |= KS8995_GC0_P5_PHY; -+ ret = ks8995_write_reg(ks, KS8995_REG_GC0, val); -+ if (ret) -+ dev_err(ks->dev, "failed to set KS8995_REG_GC0\n"); -+ -+ dev_dbg(ks->dev, "set KS8995_REG_GC0 to 0x%02x\n", val); -+ -+ return 0; -+} -+ -+static void -+ks8995_mac_config(struct phylink_config *config, unsigned int mode, -+ const struct phylink_link_state *state) -+{ -+} -+ -+static void -+ks8995_mac_link_up(struct phylink_config *config, struct phy_device *phydev, -+ unsigned int mode, phy_interface_t interface, -+ int speed, int duplex, bool tx_pause, bool rx_pause) -+{ -+ struct dsa_port *dp = dsa_phylink_to_port(config); -+ struct ks8995_switch *ks = dp->ds->priv; -+ int port = dp->index; -+ int ret; -+ u8 val; -+ -+ /* Allow forcing the mode on the fixed CPU port, no autonegotiation. -+ * We assume autonegotiation works on the PHY-facing ports. -+ */ -+ if (port != KS8995_CPU_PORT) -+ return; -+ -+ dev_dbg(ks->dev, "MAC link up on CPU port (%d)\n", port); -+ -+ ret = ks8995_read_reg(ks, KS8995_REG_GC4, &val); -+ if (ret) { -+ dev_err(ks->dev, "failed to read KS8995_REG_GC4\n"); -+ return; -+ } -+ -+ /* Conjure port config */ -+ switch (speed) { -+ case SPEED_10: -+ dev_dbg(ks->dev, "set switch MII to 100Mbit mode\n"); -+ val |= KS8995_GC4_10BT; -+ break; -+ case SPEED_100: -+ default: -+ dev_dbg(ks->dev, "set switch MII to 100Mbit mode\n"); -+ val &= ~KS8995_GC4_10BT; -+ break; -+ } -+ -+ if (duplex == DUPLEX_HALF) { -+ dev_dbg(ks->dev, "set switch MII to half duplex\n"); -+ val |= KS8995_GC4_MII_HD; -+ } else { -+ dev_dbg(ks->dev, "set switch MII to full duplex\n"); -+ val &= ~KS8995_GC4_MII_HD; -+ } -+ -+ dev_dbg(ks->dev, "set KS8995_REG_GC4 to %02x\n", val); -+ -+ /* Enable the CPU port */ -+ ret = ks8995_write_reg(ks, KS8995_REG_GC4, val); -+ if (ret) -+ dev_err(ks->dev, "failed to set KS8995_REG_GC4\n"); -+} -+ -+static void -+ks8995_mac_link_down(struct phylink_config *config, unsigned int mode, -+ phy_interface_t interface) -+{ -+ struct dsa_port *dp = dsa_phylink_to_port(config); -+ struct ks8995_switch *ks = dp->ds->priv; -+ int port = dp->index; -+ -+ if (port != KS8995_CPU_PORT) -+ return; -+ -+ dev_dbg(ks->dev, "MAC link down on CPU port (%d)\n", port); -+ -+ /* Disable the CPU port */ -+} -+ -+static const struct phylink_mac_ops ks8995_phylink_mac_ops = { -+ .mac_config = ks8995_mac_config, -+ .mac_link_up = ks8995_mac_link_up, -+ .mac_link_down = ks8995_mac_link_down, -+}; -+ -+static enum -+dsa_tag_protocol ks8995_get_tag_protocol(struct dsa_switch *ds, -+ int port, -+ enum dsa_tag_protocol mp) -+{ -+ /* This switch actually uses the 6 byte KS8995 protocol */ -+ return DSA_TAG_PROTO_NONE; -+} -+ -+static int ks8995_setup(struct dsa_switch *ds) -+{ -+ return 0; -+} -+ -+static int ks8995_port_enable(struct dsa_switch *ds, int port, -+ struct phy_device *phy) -+{ -+ struct ks8995_switch *ks = ds->priv; -+ -+ dev_dbg(ks->dev, "enable port %d\n", port); -+ -+ return 0; -+} -+ -+static void ks8995_port_disable(struct dsa_switch *ds, int port) -+{ -+ struct ks8995_switch *ks = ds->priv; -+ -+ dev_dbg(ks->dev, "disable port %d\n", port); -+} -+ -+static int ks8995_port_pre_bridge_flags(struct dsa_switch *ds, int port, -+ struct switchdev_brport_flags flags, -+ struct netlink_ext_ack *extack) -+{ -+ /* We support enabling/disabling learning */ -+ if (flags.mask & ~(BR_LEARNING)) -+ return -EINVAL; -+ -+ return 0; -+} -+ -+static int ks8995_port_bridge_flags(struct dsa_switch *ds, int port, -+ struct switchdev_brport_flags flags, -+ struct netlink_ext_ack *extack) -+{ -+ struct ks8995_switch *ks = ds->priv; -+ int ret; -+ u8 val; -+ -+ if (flags.mask & BR_LEARNING) { -+ ret = ks8995_read_reg(ks, KS8995_REG_PC(port, KS8995_REG_PC2), &val); -+ if (ret) { -+ dev_err(ks->dev, "failed to read KS8995_REG_PC2 on port %d\n", port); -+ return ret; -+ } -+ -+ if (flags.val & BR_LEARNING) -+ val &= ~KS8995_PC2_LEARN_DIS; -+ else -+ val |= KS8995_PC2_LEARN_DIS; -+ -+ ret = ks8995_write_reg(ks, KS8995_REG_PC(port, KS8995_REG_PC2), val); -+ if (ret) { -+ dev_err(ks->dev, "failed to write KS8995_REG_PC2 on port %d\n", port); -+ return ret; -+ } -+ } -+ -+ return 0; -+} -+ -+static void ks8995_port_stp_state_set(struct dsa_switch *ds, int port, u8 state) -+{ -+ struct ks8995_switch *ks = ds->priv; -+ int ret; -+ u8 val; -+ -+ ret = ks8995_read_reg(ks, KS8995_REG_PC(port, KS8995_REG_PC2), &val); -+ if (ret) { -+ dev_err(ks->dev, "failed to read KS8995_REG_PC2 on port %d\n", port); -+ return; -+ } -+ -+ /* Set the bits for the different STP states in accordance with -+ * the datasheet, pages 36-37 "Spanning tree support". -+ */ -+ switch (state) { -+ case BR_STATE_DISABLED: -+ case BR_STATE_BLOCKING: -+ case BR_STATE_LISTENING: -+ val &= ~KS8995_PC2_TXEN; -+ val &= ~KS8995_PC2_RXEN; -+ val |= KS8995_PC2_LEARN_DIS; -+ break; -+ case BR_STATE_LEARNING: -+ val &= ~KS8995_PC2_TXEN; -+ val &= ~KS8995_PC2_RXEN; -+ val &= ~KS8995_PC2_LEARN_DIS; -+ break; -+ case BR_STATE_FORWARDING: -+ val |= KS8995_PC2_TXEN; -+ val |= KS8995_PC2_RXEN; -+ val &= ~KS8995_PC2_LEARN_DIS; -+ break; -+ default: -+ dev_err(ks->dev, "unknown bridge state requested\n"); -+ return; -+ } -+ -+ ret = ks8995_write_reg(ks, KS8995_REG_PC(port, KS8995_REG_PC2), val); -+ if (ret) { -+ dev_err(ks->dev, "failed to write KS8995_REG_PC2 on port %d\n", port); -+ return; -+ } -+ -+ dev_dbg(ks->dev, "set KS8995_REG_PC2 for port %d to %02x\n", port, val); -+} -+ -+static void ks8995_phylink_get_caps(struct dsa_switch *dsa, int port, -+ struct phylink_config *config) -+{ -+ unsigned long *interfaces = config->supported_interfaces; -+ -+ if (port == KS8995_CPU_PORT) -+ __set_bit(PHY_INTERFACE_MODE_MII, interfaces); -+ -+ if (port <= 3) { -+ /* Internal PHYs */ -+ __set_bit(PHY_INTERFACE_MODE_INTERNAL, interfaces); -+ /* phylib default */ -+ __set_bit(PHY_INTERFACE_MODE_MII, interfaces); -+ } -+ -+ config->mac_capabilities = MAC_SYM_PAUSE | MAC_10 | MAC_100; -+} -+ -+/* Huge packet support up to 1916 byte packages "inclusive" -+ * which means that tags are included. If the bit is not set -+ * it is 1536 bytes "inclusive". We present the length without -+ * tags or ethernet headers. The setting affects all ports. -+ */ -+static int ks8995_change_mtu(struct dsa_switch *ds, int port, int new_mtu) -+{ -+ struct ks8995_switch *ks = ds->priv; -+ unsigned int max_mtu; -+ int ret; -+ u8 val; -+ int i; -+ -+ ks->max_mtu[port] = new_mtu; -+ -+ /* Roof out the MTU for the entire switch to the greatest -+ * common denominator: the biggest set for any one port will -+ * be the biggest MTU for the switch. -+ */ -+ max_mtu = ETH_DATA_LEN; -+ for (i = 0; i < KS8995_NUM_PORTS; i++) { -+ if (ks->max_mtu[i] > max_mtu) -+ max_mtu = ks->max_mtu[i]; -+ } -+ -+ /* Translate to layer 2 size. -+ * Add ethernet and (possible) VLAN headers, and checksum to the size. -+ * For ETH_DATA_LEN (1500 bytes) this will add up to 1522 bytes. -+ */ -+ max_mtu += VLAN_ETH_HLEN; -+ max_mtu += ETH_FCS_LEN; -+ -+ ret = ks8995_read_reg(ks, KS8995_REG_GC2, &val); -+ if (ret) { -+ dev_err(ks->dev, "failed to read KS8995_REG_GC2\n"); -+ return ret; -+ } -+ -+ if (max_mtu <= 1522) { -+ val &= ~KS8995_GC2_HUGE; -+ val &= ~KS8995_GC2_LEGAL; -+ } else if (max_mtu > 1522 && max_mtu <= 1536) { -+ /* This accepts packets up to 1536 bytes */ -+ val &= ~KS8995_GC2_HUGE; -+ val |= KS8995_GC2_LEGAL; -+ } else { -+ /* This accepts packets up to 1916 bytes */ -+ val |= KS8995_GC2_HUGE; -+ val |= KS8995_GC2_LEGAL; -+ } -+ -+ dev_dbg(ks->dev, "new max MTU %d bytes (inclusive)\n", max_mtu); -+ -+ ret = ks8995_write_reg(ks, KS8995_REG_GC2, val); -+ if (ret) -+ dev_err(ks->dev, "failed to set KS8995_REG_GC2\n"); -+ -+ return ret; -+} -+ -+static int ks8995_get_max_mtu(struct dsa_switch *ds, int port) -+{ -+ return 1916 - ETH_HLEN - ETH_FCS_LEN; -+} -+ -+static const struct dsa_switch_ops ks8995_ds_ops = { -+ .get_tag_protocol = ks8995_get_tag_protocol, -+ .setup = ks8995_setup, -+ .port_pre_bridge_flags = ks8995_port_pre_bridge_flags, -+ .port_bridge_flags = ks8995_port_bridge_flags, -+ .port_enable = ks8995_port_enable, -+ .port_disable = ks8995_port_disable, -+ .port_stp_state_set = ks8995_port_stp_state_set, -+ .port_change_mtu = ks8995_change_mtu, -+ .port_max_mtu = ks8995_get_max_mtu, -+ .phylink_get_caps = ks8995_phylink_get_caps, -+}; -+ - /* ------------------------------------------------------------------------ */ - static int ks8995_probe(struct spi_device *spi) - { -@@ -388,6 +759,7 @@ static int ks8995_probe(struct spi_devic - - mutex_init(&ks->lock); - ks->spi = spi; -+ ks->dev = &spi->dev; - ks->chip = &ks8995_chip[variant]; - - ks->reset_gpio = devm_gpiod_get_optional(&spi->dev, "reset", -@@ -434,6 +806,25 @@ static int ks8995_probe(struct spi_devic - dev_info(&spi->dev, "%s device found, Chip ID:%x, Revision:%x\n", - ks->chip->name, ks->chip->chip_id, ks->revision_id); - -+ err = ks8995_check_config(ks); -+ if (err) -+ return err; -+ -+ ks->ds = devm_kzalloc(&spi->dev, sizeof(*ks->ds), GFP_KERNEL); -+ if (!ks->ds) -+ return -ENOMEM; -+ -+ ks->ds->dev = &spi->dev; -+ ks->ds->num_ports = KS8995_NUM_PORTS; -+ ks->ds->ops = &ks8995_ds_ops; -+ ks->ds->phylink_mac_ops = &ks8995_phylink_mac_ops; -+ ks->ds->priv = ks; -+ -+ err = dsa_register_switch(ks->ds); -+ if (err) -+ return dev_err_probe(&spi->dev, err, -+ "unable to register DSA switch\n"); -+ - return 0; - } - -@@ -441,6 +832,7 @@ static void ks8995_remove(struct spi_dev - { - struct ks8995_switch *ks = spi_get_drvdata(spi); - -+ dsa_unregister_switch(ks->ds); - /* assert reset */ - gpiod_set_value_cansleep(ks->reset_gpio, 1); - } diff --git a/target/linux/generic/backport-6.18/784-01-v6.17-net-phy-realtek-add-error-handling-to-rtl8211f_get_w.patch b/target/linux/generic/backport-6.18/784-01-v6.17-net-phy-realtek-add-error-handling-to-rtl8211f_get_w.patch deleted file mode 100644 index 5f3b119a89..0000000000 --- a/target/linux/generic/backport-6.18/784-01-v6.17-net-phy-realtek-add-error-handling-to-rtl8211f_get_w.patch +++ /dev/null @@ -1,39 +0,0 @@ -From a9b24b3583ae1da7dbda031f141264f2da260219 Mon Sep 17 00:00:00 2001 -From: Daniel Braunwarth -Date: Tue, 24 Jun 2025 16:17:33 +0200 -Subject: [PATCH] net: phy: realtek: add error handling to rtl8211f_get_wol - -We should check if the WOL settings was successfully read from the PHY. - -In case this fails we cannot just use the error code and proceed. - -Signed-off-by: Daniel Braunwarth -Reported-by: Jon Hunter -Closes: https://lore.kernel.org/baaa083b-9a69-460f-ab35-2a7cb3246ffd@nvidia.com -Reviewed-by: Andrew Lunn -Link: https://patch.msgid.link/20250624-realtek_fixes-v1-1-02a0b7c369bc@kuka.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/realtek/realtek_main.c | 10 ++++++++-- - 1 file changed, 8 insertions(+), 2 deletions(-) - ---- a/drivers/net/phy/realtek/realtek_main.c -+++ b/drivers/net/phy/realtek/realtek_main.c -@@ -436,9 +436,15 @@ static irqreturn_t rtl8211f_handle_inter - - static void rtl8211f_get_wol(struct phy_device *dev, struct ethtool_wolinfo *wol) - { -+ int wol_events; -+ - wol->supported = WAKE_MAGIC; -- if (phy_read_paged(dev, RTL8211F_WOL_SETTINGS_PAGE, RTL8211F_WOL_SETTINGS_EVENTS) -- & RTL8211F_WOL_EVENT_MAGIC) -+ -+ wol_events = phy_read_paged(dev, RTL8211F_WOL_SETTINGS_PAGE, RTL8211F_WOL_SETTINGS_EVENTS); -+ if (wol_events < 0) -+ return; -+ -+ if (wol_events & RTL8211F_WOL_EVENT_MAGIC) - wol->wolopts = WAKE_MAGIC; - } - diff --git a/target/linux/generic/backport-6.18/784-02-v6.18-net-phy-realtek-Avoid-PHYCR2-access-if-PHYCR2-not-pr.patch b/target/linux/generic/backport-6.18/784-02-v6.18-net-phy-realtek-Avoid-PHYCR2-access-if-PHYCR2-not-pr.patch deleted file mode 100644 index 681b234fc5..0000000000 --- a/target/linux/generic/backport-6.18/784-02-v6.18-net-phy-realtek-Avoid-PHYCR2-access-if-PHYCR2-not-pr.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 2c67301584f2671e320236df6bbe75ae09feb4d0 Mon Sep 17 00:00:00 2001 -From: Marek Vasut -Date: Sat, 11 Oct 2025 13:02:49 +0200 -Subject: [PATCH] net: phy: realtek: Avoid PHYCR2 access if PHYCR2 not present - -The driver is currently checking for PHYCR2 register presence in -rtl8211f_config_init(), but it does so after accessing PHYCR2 to -disable EEE. This was introduced in commit bfc17c165835 ("net: -phy: realtek: disable PHY-mode EEE"). Move the PHYCR2 presence -test before the EEE disablement and simplify the code. - -Fixes: bfc17c165835 ("net: phy: realtek: disable PHY-mode EEE") -Signed-off-by: Marek Vasut -Reviewed-by: Maxime Chevallier -Reviewed-by: Russell King (Oracle) -Link: https://patch.msgid.link/20251011110309.12664-1-marek.vasut@mailbox.org -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/realtek/realtek_main.c | 23 +++++++++++------------ - 1 file changed, 11 insertions(+), 12 deletions(-) - ---- a/drivers/net/phy/realtek/realtek_main.c -+++ b/drivers/net/phy/realtek/realtek_main.c -@@ -589,26 +589,25 @@ static int rtl8211f_config_init(struct p - str_enabled_disabled(val_rxdly)); - } - -+ if (!priv->has_phycr2) -+ return 0; -+ - /* Disable PHY-mode EEE so LPI is passed to the MAC */ - ret = phy_modify_paged(phydev, RTL8211F_PHYCR_PAGE, RTL8211F_PHYCR2, - RTL8211F_PHYCR2_PHY_EEE_ENABLE, 0); - if (ret) - return ret; - -- if (priv->has_phycr2) { -- ret = phy_modify_paged(phydev, RTL8211F_PHYCR_PAGE, -- RTL8211F_PHYCR2, RTL8211F_CLKOUT_EN, -- priv->phycr2); -- if (ret < 0) { -- dev_err(dev, "clkout configuration failed: %pe\n", -- ERR_PTR(ret)); -- return ret; -- } -- -- return genphy_soft_reset(phydev); -+ ret = phy_modify_paged(phydev, RTL8211F_PHYCR_PAGE, -+ RTL8211F_PHYCR2, RTL8211F_CLKOUT_EN, -+ priv->phycr2); -+ if (ret < 0) { -+ dev_err(dev, "clkout configuration failed: %pe\n", -+ ERR_PTR(ret)); -+ return ret; - } - -- return 0; -+ return genphy_soft_reset(phydev); - } - - static int rtl821x_suspend(struct phy_device *phydev) diff --git a/target/linux/generic/backport-6.18/784-02-v6.18-net-phy-realtek-fix-RTL8211F-wake-on-lan-support.patch b/target/linux/generic/backport-6.18/784-02-v6.18-net-phy-realtek-fix-RTL8211F-wake-on-lan-support.patch deleted file mode 100644 index b5c4f8f9fc..0000000000 --- a/target/linux/generic/backport-6.18/784-02-v6.18-net-phy-realtek-fix-RTL8211F-wake-on-lan-support.patch +++ /dev/null @@ -1,352 +0,0 @@ -From b826bf795564ddef6402cf2cb522ae035bd117ae Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Wed, 13 Aug 2025 11:04:45 +0100 -Subject: [PATCH] net: phy: realtek: fix RTL8211F wake-on-lan support - -Implement Wake-on-Lan for RTL8211F correctly. The existing -implementation has multiple issues: - -1. It assumes that Wake-on-Lan can always be used, whether or not the - interrupt is wired, and whether or not the interrupt is capable of - waking the system. This breaks the ability for MAC drivers to detect - whether the PHY WoL is functional. -2. switching the interrupt pin in the .set_wol() method to PMEB mode - immediately silences link-state interrupts, which breaks phylib - when interrupts are being used rather than polling mode. -3. the code claiming to "reset WOL status" was doing nothing of the - sort. Bit 15 in page 0xd8a register 17 controls WoL reset, and - needs to be pulsed low to reset the WoL state. This bit was always - written as '1', resulting in no reset. -4. not resetting WoL state results in the PMEB pin remaining asserted, - which in turn leads to an interrupt storm. Only resetting the WoL - state in .set_wol() is not sufficient. -5. PMEB mode does not allow software detection of the wake-up event as - there is no status bit to indicate we received the WoL packet. -6. across reboots of at least the Jetson Xavier NX system, the WoL - configuration is preserved. - -Fix all of these issues by essentially rewriting the support. We: -1. clear the WoL event enable register at probe time. -2. detect whether we can support wake-up by having a valid interrupt, - and the "wakeup-source" property in DT. If we can, then we mark - the MDIO device as wakeup capable, and associate the interrupt - with the wakeup source. -3. arrange for the get_wol() and set_wol() implementations to handle - the case where the MDIO device has not been marked as wakeup - capable (thereby returning no WoL support, and refusing to enable - WoL support.) -4. avoid switching to PMEB mode, instead using INTB mode with the - interrupt enable, reconfiguring the interrupt enables at suspend - time, and restoring their original state at resume time (we track - the state of the interrupt enable register in .config_intr() - register.) -5. move WoL reset from .set_wol() to the suspend function to ensure - that WoL state is cleared prior to suspend. This is necessary - after the PME interrupt has been enabled as a second WoL packet - will not re-raise a previously cleared PME interrupt. -6. when a PME interrupt (for wakeup) is asserted, pass this to the - PM wakeup so it knows which device woke the system. - -This fixes WoL support in the Realtek RTL8211F driver when used on the -nVidia Jetson Xavier NX platform, and needs to be applied before stmmac -patches which allow these platforms to forward the ethtool WoL commands -to the Realtek PHY. - -Signed-off-by: Russell King (Oracle) -Reviewed-by: Andrew Lunn -Link: https://patch.msgid.link/E1um8Ld-008jxD-Mc@rmk-PC.armlinux.org.uk -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/realtek/realtek_main.c | 172 ++++++++++++++++++++----- - 1 file changed, 140 insertions(+), 32 deletions(-) - ---- a/drivers/net/phy/realtek/realtek_main.c -+++ b/drivers/net/phy/realtek/realtek_main.c -@@ -10,6 +10,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -31,6 +32,7 @@ - #define RTL821x_INER 0x12 - #define RTL8211B_INER_INIT 0x6400 - #define RTL8211E_INER_LINK_STATUS BIT(10) -+#define RTL8211F_INER_PME BIT(7) - #define RTL8211F_INER_LINK_STATUS BIT(4) - - #define RTL821x_INSR 0x13 -@@ -96,17 +98,13 @@ - #define RTL8211F_RXCR 0x15 - #define RTL8211F_RX_DELAY BIT(3) - --/* RTL8211F WOL interrupt configuration */ --#define RTL8211F_INTBCR_PAGE 0xd40 --#define RTL8211F_INTBCR 0x16 --#define RTL8211F_INTBCR_INTB_PMEB BIT(5) -- - /* RTL8211F WOL settings */ --#define RTL8211F_WOL_SETTINGS_PAGE 0xd8a -+#define RTL8211F_WOL_PAGE 0xd8a - #define RTL8211F_WOL_SETTINGS_EVENTS 16 - #define RTL8211F_WOL_EVENT_MAGIC BIT(12) --#define RTL8211F_WOL_SETTINGS_STATUS 17 --#define RTL8211F_WOL_STATUS_RESET (BIT(15) | 0x1fff) -+#define RTL8211F_WOL_RST_RMSQ 17 -+#define RTL8211F_WOL_RG_RSTB BIT(15) -+#define RTL8211F_WOL_RMSQ 0x1fff - - /* RTL8211F Unique phyiscal and multicast address (WOL) */ - #define RTL8211F_PHYSICAL_ADDR_PAGE 0xd8c -@@ -172,7 +170,8 @@ struct rtl821x_priv { - u16 phycr2; - bool has_phycr2; - struct clk *clk; -- u32 saved_wolopts; -+ /* rtl8211f */ -+ u16 iner; - }; - - static int rtl821x_read_page(struct phy_device *phydev) -@@ -255,6 +254,34 @@ static int rtl821x_probe(struct phy_devi - return 0; - } - -+static int rtl8211f_probe(struct phy_device *phydev) -+{ -+ struct device *dev = &phydev->mdio.dev; -+ int ret; -+ -+ ret = rtl821x_probe(phydev); -+ if (ret < 0) -+ return ret; -+ -+ /* Disable all PME events */ -+ ret = phy_write_paged(phydev, RTL8211F_WOL_PAGE, -+ RTL8211F_WOL_SETTINGS_EVENTS, 0); -+ if (ret < 0) -+ return ret; -+ -+ /* Mark this PHY as wakeup capable and register the interrupt as a -+ * wakeup IRQ if the PHY is marked as a wakeup source in firmware, -+ * and the interrupt is valid. -+ */ -+ if (device_property_read_bool(dev, "wakeup-source") && -+ phy_interrupt_is_valid(phydev)) { -+ device_set_wakeup_capable(dev, true); -+ devm_pm_set_wake_irq(dev, phydev->irq); -+ } -+ -+ return ret; -+} -+ - static int rtl8201_ack_interrupt(struct phy_device *phydev) - { - int err; -@@ -352,6 +379,7 @@ static int rtl8211e_config_intr(struct p - - static int rtl8211f_config_intr(struct phy_device *phydev) - { -+ struct rtl821x_priv *priv = phydev->priv; - u16 val; - int err; - -@@ -362,8 +390,10 @@ static int rtl8211f_config_intr(struct p - - val = RTL8211F_INER_LINK_STATUS; - err = phy_write_paged(phydev, 0xa42, RTL821x_INER, val); -+ if (err == 0) -+ priv->iner = val; - } else { -- val = 0; -+ priv->iner = val = 0; - err = phy_write_paged(phydev, 0xa42, RTL821x_INER, val); - if (err) - return err; -@@ -426,21 +456,34 @@ static irqreturn_t rtl8211f_handle_inter - return IRQ_NONE; - } - -- if (!(irq_status & RTL8211F_INER_LINK_STATUS)) -- return IRQ_NONE; -+ if (irq_status & RTL8211F_INER_LINK_STATUS) { -+ phy_trigger_machine(phydev); -+ return IRQ_HANDLED; -+ } - -- phy_trigger_machine(phydev); -+ if (irq_status & RTL8211F_INER_PME) { -+ pm_wakeup_event(&phydev->mdio.dev, 0); -+ return IRQ_HANDLED; -+ } - -- return IRQ_HANDLED; -+ return IRQ_NONE; - } - - static void rtl8211f_get_wol(struct phy_device *dev, struct ethtool_wolinfo *wol) - { - int wol_events; - -+ /* If the PHY is not capable of waking the system, then WoL can not -+ * be supported. -+ */ -+ if (!device_can_wakeup(&dev->mdio.dev)) { -+ wol->supported = 0; -+ return; -+ } -+ - wol->supported = WAKE_MAGIC; - -- wol_events = phy_read_paged(dev, RTL8211F_WOL_SETTINGS_PAGE, RTL8211F_WOL_SETTINGS_EVENTS); -+ wol_events = phy_read_paged(dev, RTL8211F_WOL_PAGE, RTL8211F_WOL_SETTINGS_EVENTS); - if (wol_events < 0) - return; - -@@ -453,6 +496,9 @@ static int rtl8211f_set_wol(struct phy_d - const u8 *mac_addr = dev->attached_dev->dev_addr; - int oldpage; - -+ if (!device_can_wakeup(&dev->mdio.dev)) -+ return -EOPNOTSUPP; -+ - oldpage = phy_save_page(dev); - if (oldpage < 0) - goto err; -@@ -464,25 +510,23 @@ static int rtl8211f_set_wol(struct phy_d - __phy_write(dev, RTL8211F_PHYSICAL_ADDR_WORD1, mac_addr[3] << 8 | (mac_addr[2])); - __phy_write(dev, RTL8211F_PHYSICAL_ADDR_WORD2, mac_addr[5] << 8 | (mac_addr[4])); - -- /* Enable magic packet matching and reset WOL status */ -- rtl821x_write_page(dev, RTL8211F_WOL_SETTINGS_PAGE); -+ /* Enable magic packet matching */ -+ rtl821x_write_page(dev, RTL8211F_WOL_PAGE); - __phy_write(dev, RTL8211F_WOL_SETTINGS_EVENTS, RTL8211F_WOL_EVENT_MAGIC); -- __phy_write(dev, RTL8211F_WOL_SETTINGS_STATUS, RTL8211F_WOL_STATUS_RESET); -- -- /* Enable the WOL interrupt */ -- rtl821x_write_page(dev, RTL8211F_INTBCR_PAGE); -- __phy_set_bits(dev, RTL8211F_INTBCR, RTL8211F_INTBCR_INTB_PMEB); -+ /* Set the maximum packet size, and assert WoL reset */ -+ __phy_write(dev, RTL8211F_WOL_RST_RMSQ, RTL8211F_WOL_RMSQ); - } else { -- /* Disable the WOL interrupt */ -- rtl821x_write_page(dev, RTL8211F_INTBCR_PAGE); -- __phy_clear_bits(dev, RTL8211F_INTBCR, RTL8211F_INTBCR_INTB_PMEB); -- -- /* Disable magic packet matching and reset WOL status */ -- rtl821x_write_page(dev, RTL8211F_WOL_SETTINGS_PAGE); -+ /* Disable magic packet matching */ -+ rtl821x_write_page(dev, RTL8211F_WOL_PAGE); - __phy_write(dev, RTL8211F_WOL_SETTINGS_EVENTS, 0); -- __phy_write(dev, RTL8211F_WOL_SETTINGS_STATUS, RTL8211F_WOL_STATUS_RESET); -+ -+ /* Place WoL in reset */ -+ __phy_clear_bits(dev, RTL8211F_WOL_RST_RMSQ, -+ RTL8211F_WOL_RG_RSTB); - } - -+ device_set_wakeup_enable(&dev->mdio.dev, !!(wol->wolopts & WAKE_MAGIC)); -+ - err: - return phy_restore_page(dev, oldpage, 0); - } -@@ -627,6 +671,52 @@ static int rtl821x_suspend(struct phy_de - return ret; - } - -+static int rtl8211f_suspend(struct phy_device *phydev) -+{ -+ u16 wol_rst; -+ int ret; -+ -+ ret = rtl821x_suspend(phydev); -+ if (ret < 0) -+ return ret; -+ -+ /* If a PME event is enabled, then configure the interrupt for -+ * PME events only, disabling link interrupt. We avoid switching -+ * to PMEB mode as we don't have a status bit for that. -+ */ -+ if (device_may_wakeup(&phydev->mdio.dev)) { -+ ret = phy_write_paged(phydev, 0xa42, RTL821x_INER, -+ RTL8211F_INER_PME); -+ if (ret < 0) -+ goto err; -+ -+ /* Read the INSR to clear any pending interrupt */ -+ phy_read_paged(phydev, RTL8211F_INSR_PAGE, RTL8211F_INSR); -+ -+ /* Reset the WoL to ensure that an event is picked up. -+ * Unless we do this, even if we receive another packet, -+ * we may not have a PME interrupt raised. -+ */ -+ ret = phy_read_paged(phydev, RTL8211F_WOL_PAGE, -+ RTL8211F_WOL_RST_RMSQ); -+ if (ret < 0) -+ goto err; -+ -+ wol_rst = ret & ~RTL8211F_WOL_RG_RSTB; -+ ret = phy_write_paged(phydev, RTL8211F_WOL_PAGE, -+ RTL8211F_WOL_RST_RMSQ, wol_rst); -+ if (ret < 0) -+ goto err; -+ -+ wol_rst |= RTL8211F_WOL_RG_RSTB; -+ ret = phy_write_paged(phydev, RTL8211F_WOL_PAGE, -+ RTL8211F_WOL_RST_RMSQ, wol_rst); -+ } -+ -+err: -+ return ret; -+} -+ - static int rtl821x_resume(struct phy_device *phydev) - { - struct rtl821x_priv *priv = phydev->priv; -@@ -644,6 +734,24 @@ static int rtl821x_resume(struct phy_dev - return 0; - } - -+static int rtl8211f_resume(struct phy_device *phydev) -+{ -+ struct rtl821x_priv *priv = phydev->priv; -+ int ret; -+ -+ ret = rtl821x_resume(phydev); -+ if (ret < 0) -+ return ret; -+ -+ /* If the device was programmed for a PME event, restore the interrupt -+ * enable so phylib can receive link state interrupts. -+ */ -+ if (device_may_wakeup(&phydev->mdio.dev)) -+ ret = phy_write_paged(phydev, 0xa42, RTL821x_INER, priv->iner); -+ -+ return ret; -+} -+ - static int rtl8211x_led_hw_is_supported(struct phy_device *phydev, u8 index, - unsigned long rules) - { -@@ -1639,15 +1747,15 @@ static struct phy_driver realtek_drvs[] - }, { - PHY_ID_MATCH_EXACT(0x001cc916), - .name = "RTL8211F Gigabit Ethernet", -- .probe = rtl821x_probe, -+ .probe = rtl8211f_probe, - .config_init = &rtl8211f_config_init, - .read_status = rtlgen_read_status, - .config_intr = &rtl8211f_config_intr, - .handle_interrupt = rtl8211f_handle_interrupt, - .set_wol = rtl8211f_set_wol, - .get_wol = rtl8211f_get_wol, -- .suspend = rtl821x_suspend, -- .resume = rtl821x_resume, -+ .suspend = rtl8211f_suspend, -+ .resume = rtl8211f_resume, - .read_page = rtl821x_read_page, - .write_page = rtl821x_write_page, - .flags = PHY_ALWAYS_CALL_SUSPEND, diff --git a/target/linux/generic/backport-6.18/784-03-v6.18-net-phy-realtek-fix-rtl8221b-vm-cg-name.patch b/target/linux/generic/backport-6.18/784-03-v6.18-net-phy-realtek-fix-rtl8221b-vm-cg-name.patch deleted file mode 100644 index ab319f0806..0000000000 --- a/target/linux/generic/backport-6.18/784-03-v6.18-net-phy-realtek-fix-rtl8221b-vm-cg-name.patch +++ /dev/null @@ -1,70 +0,0 @@ -From ffff5c8fc2af2218a3332b3d5b97654599d50cde Mon Sep 17 00:00:00 2001 -From: Aleksander Jan Bajkowski -Date: Thu, 16 Oct 2025 21:22:52 +0200 -Subject: [PATCH] net: phy: realtek: fix rtl8221b-vm-cg name - -When splitting the RTL8221B-VM-CG into C22 and C45 variants, the name was -accidentally changed to RTL8221B-VN-CG. This patch brings back the previous -part number. - -Fixes: ad5ce743a6b0 ("net: phy: realtek: Add driver instances for rtl8221b via Clause 45") -Signed-off-by: Aleksander Jan Bajkowski -Reviewed-by: Simon Horman -Link: https://patch.msgid.link/20251016192325.2306757-1-olek2@wp.pl -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/realtek/realtek_main.c | 16 ++++++++-------- - 1 file changed, 8 insertions(+), 8 deletions(-) - ---- a/drivers/net/phy/realtek/realtek_main.c -+++ b/drivers/net/phy/realtek/realtek_main.c -@@ -154,7 +154,7 @@ - #define RTL_8211FVD_PHYID 0x001cc878 - #define RTL_8221B 0x001cc840 - #define RTL_8221B_VB_CG 0x001cc849 --#define RTL_8221B_VN_CG 0x001cc84a -+#define RTL_8221B_VM_CG 0x001cc84a - #define RTL_8251B 0x001cc862 - #define RTL_8261C 0x001cc890 - -@@ -1498,16 +1498,16 @@ static int rtl8221b_vb_cg_c45_match_phy_ - return rtlgen_is_c45_match(phydev, RTL_8221B_VB_CG, true); - } - --static int rtl8221b_vn_cg_c22_match_phy_device(struct phy_device *phydev, -+static int rtl8221b_vm_cg_c22_match_phy_device(struct phy_device *phydev, - const struct phy_driver *phydrv) - { -- return rtlgen_is_c45_match(phydev, RTL_8221B_VN_CG, false); -+ return rtlgen_is_c45_match(phydev, RTL_8221B_VM_CG, false); - } - --static int rtl8221b_vn_cg_c45_match_phy_device(struct phy_device *phydev, -+static int rtl8221b_vm_cg_c45_match_phy_device(struct phy_device *phydev, - const struct phy_driver *phydrv) - { -- return rtlgen_is_c45_match(phydev, RTL_8221B_VN_CG, true); -+ return rtlgen_is_c45_match(phydev, RTL_8221B_VM_CG, true); - } - - static int rtl_internal_nbaset_match_phy_device(struct phy_device *phydev, -@@ -1854,7 +1854,7 @@ static struct phy_driver realtek_drvs[] - .suspend = genphy_c45_pma_suspend, - .resume = rtlgen_c45_resume, - }, { -- .match_phy_device = rtl8221b_vn_cg_c22_match_phy_device, -+ .match_phy_device = rtl8221b_vm_cg_c22_match_phy_device, - .name = "RTL8221B-VM-CG 2.5Gbps PHY (C22)", - .probe = rtl822x_probe, - .get_features = rtl822x_get_features, -@@ -1867,8 +1867,8 @@ static struct phy_driver realtek_drvs[] - .read_page = rtl821x_read_page, - .write_page = rtl821x_write_page, - }, { -- .match_phy_device = rtl8221b_vn_cg_c45_match_phy_device, -- .name = "RTL8221B-VN-CG 2.5Gbps PHY (C45)", -+ .match_phy_device = rtl8221b_vm_cg_c45_match_phy_device, -+ .name = "RTL8221B-VM-CG 2.5Gbps PHY (C45)", - .probe = rtl822x_probe, - .config_init = rtl822xb_config_init, - .get_rate_matching = rtl822xb_get_rate_matching, diff --git a/target/linux/generic/backport-6.18/784-03-v6.18-net-phy-realtek-support-for-TRIGGER_NETDEV_LINK-on-R.patch b/target/linux/generic/backport-6.18/784-03-v6.18-net-phy-realtek-support-for-TRIGGER_NETDEV_LINK-on-R.patch deleted file mode 100644 index dc8d247dae..0000000000 --- a/target/linux/generic/backport-6.18/784-03-v6.18-net-phy-realtek-support-for-TRIGGER_NETDEV_LINK-on-R.patch +++ /dev/null @@ -1,105 +0,0 @@ -From f63f21e82ecafd288b100ea161247820bf1e92c4 Mon Sep 17 00:00:00 2001 -From: Aleksander Jan Bajkowski -Date: Mon, 25 Aug 2025 23:09:49 +0200 -Subject: [PATCH] net: phy: realtek: support for TRIGGER_NETDEV_LINK on - RTL8211E and RTL8211F - -This patch adds support for the TRIGGER_NETDEV_LINK trigger. It activates -the LED when a link is established, regardless of the speed. - -Tested on Orange Pi PC2 with RTL8211E PHY. - -Signed-off-by: Aleksander Jan Bajkowski -Reviewed-by: Andrew Lunn -Link: https://patch.msgid.link/20250825211059.143231-1-olek2@wp.pl -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/realtek/realtek_main.c | 39 +++++++++++++++++++++----- - 1 file changed, 32 insertions(+), 7 deletions(-) - ---- a/drivers/net/phy/realtek/realtek_main.c -+++ b/drivers/net/phy/realtek/realtek_main.c -@@ -755,7 +755,8 @@ static int rtl8211f_resume(struct phy_de - static int rtl8211x_led_hw_is_supported(struct phy_device *phydev, u8 index, - unsigned long rules) - { -- const unsigned long mask = BIT(TRIGGER_NETDEV_LINK_10) | -+ const unsigned long mask = BIT(TRIGGER_NETDEV_LINK) | -+ BIT(TRIGGER_NETDEV_LINK_10) | - BIT(TRIGGER_NETDEV_LINK_100) | - BIT(TRIGGER_NETDEV_LINK_1000) | - BIT(TRIGGER_NETDEV_RX) | -@@ -813,6 +814,12 @@ static int rtl8211f_led_hw_control_get(s - if (val & RTL8211F_LEDCR_LINK_1000) - __set_bit(TRIGGER_NETDEV_LINK_1000, rules); - -+ if ((val & RTL8211F_LEDCR_LINK_10) && -+ (val & RTL8211F_LEDCR_LINK_100) && -+ (val & RTL8211F_LEDCR_LINK_1000)) { -+ __set_bit(TRIGGER_NETDEV_LINK, rules); -+ } -+ - if (val & RTL8211F_LEDCR_ACT_TXRX) { - __set_bit(TRIGGER_NETDEV_RX, rules); - __set_bit(TRIGGER_NETDEV_TX, rules); -@@ -830,14 +837,20 @@ static int rtl8211f_led_hw_control_set(s - if (index >= RTL8211x_LED_COUNT) - return -EINVAL; - -- if (test_bit(TRIGGER_NETDEV_LINK_10, &rules)) -+ if (test_bit(TRIGGER_NETDEV_LINK, &rules) || -+ test_bit(TRIGGER_NETDEV_LINK_10, &rules)) { - reg |= RTL8211F_LEDCR_LINK_10; -+ } - -- if (test_bit(TRIGGER_NETDEV_LINK_100, &rules)) -+ if (test_bit(TRIGGER_NETDEV_LINK, &rules) || -+ test_bit(TRIGGER_NETDEV_LINK_100, &rules)) { - reg |= RTL8211F_LEDCR_LINK_100; -+ } - -- if (test_bit(TRIGGER_NETDEV_LINK_1000, &rules)) -+ if (test_bit(TRIGGER_NETDEV_LINK, &rules) || -+ test_bit(TRIGGER_NETDEV_LINK_1000, &rules)) { - reg |= RTL8211F_LEDCR_LINK_1000; -+ } - - if (test_bit(TRIGGER_NETDEV_RX, &rules) || - test_bit(TRIGGER_NETDEV_TX, &rules)) { -@@ -885,6 +898,12 @@ static int rtl8211e_led_hw_control_get(s - if (cr2 & RTL8211E_LEDCR2_LINK_1000) - __set_bit(TRIGGER_NETDEV_LINK_1000, rules); - -+ if ((cr2 & RTL8211E_LEDCR2_LINK_10) && -+ (cr2 & RTL8211E_LEDCR2_LINK_100) && -+ (cr2 & RTL8211E_LEDCR2_LINK_1000)) { -+ __set_bit(TRIGGER_NETDEV_LINK, rules); -+ } -+ - return ret; - } - -@@ -912,14 +931,20 @@ static int rtl8211e_led_hw_control_set(s - if (ret < 0) - return ret; - -- if (test_bit(TRIGGER_NETDEV_LINK_10, &rules)) -+ if (test_bit(TRIGGER_NETDEV_LINK, &rules) || -+ test_bit(TRIGGER_NETDEV_LINK_10, &rules)) { - cr2 |= RTL8211E_LEDCR2_LINK_10; -+ } - -- if (test_bit(TRIGGER_NETDEV_LINK_100, &rules)) -+ if (test_bit(TRIGGER_NETDEV_LINK, &rules) || -+ test_bit(TRIGGER_NETDEV_LINK_100, &rules)) { - cr2 |= RTL8211E_LEDCR2_LINK_100; -+ } - -- if (test_bit(TRIGGER_NETDEV_LINK_1000, &rules)) -+ if (test_bit(TRIGGER_NETDEV_LINK, &rules) || -+ test_bit(TRIGGER_NETDEV_LINK_1000, &rules)) { - cr2 |= RTL8211E_LEDCR2_LINK_1000; -+ } - - cr2 <<= RTL8211E_LEDCR2_SHIFT * index; - ret = rtl821x_modify_ext_page(phydev, RTL8211E_LEDCR_EXT_PAGE, diff --git a/target/linux/generic/backport-6.18/784-08-v6.19-net-phy-realtek-create-rtl8211f_config_rgmii_delay.patch b/target/linux/generic/backport-6.18/784-08-v6.19-net-phy-realtek-create-rtl8211f_config_rgmii_delay.patch deleted file mode 100644 index 0c523ee683..0000000000 --- a/target/linux/generic/backport-6.18/784-08-v6.19-net-phy-realtek-create-rtl8211f_config_rgmii_delay.patch +++ /dev/null @@ -1,128 +0,0 @@ -From 8e982441ba601d982dd0739972115d85ae01d99b Mon Sep 17 00:00:00 2001 -From: Vladimir Oltean -Date: Tue, 18 Nov 2025 01:40:28 +0200 -Subject: [PATCH] net: phy: realtek: create rtl8211f_config_rgmii_delay() - -The control flow in rtl8211f_config_init() has some pitfalls which were -probably unintended. Specifically it has an early return: - - switch (phydev->interface) { - ... - default: /* the rest of the modes imply leaving delay as is. */ - return 0; - } - -which exits the entire config_init() function. This means it also skips -doing things such as disabling CLKOUT or disabling PHY-mode EEE. - -For the RTL8211FS, which uses PHY_INTERFACE_MODE_SGMII, this might be a -problem. However, I don't know that it is, so there is no Fixes: tag. -The issue was observed through code inspection. - -Signed-off-by: Vladimir Oltean -Reviewed-by: Andrew Lunn -Link: https://patch.msgid.link/20251117234033.345679-2-vladimir.oltean@nxp.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/realtek/realtek_main.c | 65 +++++++++++++++----------- - 1 file changed, 39 insertions(+), 26 deletions(-) - ---- a/drivers/net/phy/realtek/realtek_main.c -+++ b/drivers/net/phy/realtek/realtek_main.c -@@ -587,22 +587,11 @@ static int rtl8211c_config_init(struct p - CTL1000_ENABLE_MASTER | CTL1000_AS_MASTER); - } - --static int rtl8211f_config_init(struct phy_device *phydev) -+static int rtl8211f_config_rgmii_delay(struct phy_device *phydev) - { -- struct rtl821x_priv *priv = phydev->priv; -- struct device *dev = &phydev->mdio.dev; - u16 val_txdly, val_rxdly; - int ret; - -- ret = phy_modify_paged_changed(phydev, RTL8211F_PHYCR_PAGE, RTL8211F_PHYCR1, -- RTL8211F_ALDPS_PLL_OFF | RTL8211F_ALDPS_ENABLE | RTL8211F_ALDPS_XTAL_OFF, -- priv->phycr1); -- if (ret < 0) { -- dev_err(dev, "aldps mode configuration failed: %pe\n", -- ERR_PTR(ret)); -- return ret; -- } -- - switch (phydev->interface) { - case PHY_INTERFACE_MODE_RGMII: - val_txdly = 0; -@@ -632,34 +621,58 @@ static int rtl8211f_config_init(struct p - RTL8211F_TXCR, RTL8211F_TX_DELAY, - val_txdly); - if (ret < 0) { -- dev_err(dev, "Failed to update the TX delay register\n"); -+ phydev_err(phydev, "Failed to update the TX delay register: %pe\n", -+ ERR_PTR(ret)); - return ret; - } else if (ret) { -- dev_dbg(dev, -- "%s 2ns TX delay (and changing the value from pin-strapping RXD1 or the bootloader)\n", -- str_enable_disable(val_txdly)); -+ phydev_dbg(phydev, -+ "%s 2ns TX delay (and changing the value from pin-strapping RXD1 or the bootloader)\n", -+ str_enable_disable(val_txdly)); - } else { -- dev_dbg(dev, -- "2ns TX delay was already %s (by pin-strapping RXD1 or bootloader configuration)\n", -- str_enabled_disabled(val_txdly)); -+ phydev_dbg(phydev, -+ "2ns TX delay was already %s (by pin-strapping RXD1 or bootloader configuration)\n", -+ str_enabled_disabled(val_txdly)); - } - - ret = phy_modify_paged_changed(phydev, RTL8211F_RGMII_PAGE, - RTL8211F_RXCR, RTL8211F_RX_DELAY, - val_rxdly); - if (ret < 0) { -- dev_err(dev, "Failed to update the RX delay register\n"); -+ phydev_err(phydev, "Failed to update the RX delay register: %pe\n", -+ ERR_PTR(ret)); - return ret; - } else if (ret) { -- dev_dbg(dev, -- "%s 2ns RX delay (and changing the value from pin-strapping RXD0 or the bootloader)\n", -- str_enable_disable(val_rxdly)); -+ phydev_dbg(phydev, -+ "%s 2ns RX delay (and changing the value from pin-strapping RXD0 or the bootloader)\n", -+ str_enable_disable(val_rxdly)); - } else { -- dev_dbg(dev, -- "2ns RX delay was already %s (by pin-strapping RXD0 or bootloader configuration)\n", -- str_enabled_disabled(val_rxdly)); -+ phydev_dbg(phydev, -+ "2ns RX delay was already %s (by pin-strapping RXD0 or bootloader configuration)\n", -+ str_enabled_disabled(val_rxdly)); - } - -+ return 0; -+} -+ -+static int rtl8211f_config_init(struct phy_device *phydev) -+{ -+ struct rtl821x_priv *priv = phydev->priv; -+ struct device *dev = &phydev->mdio.dev; -+ int ret; -+ -+ ret = phy_modify_paged_changed(phydev, RTL8211F_PHYCR_PAGE, RTL8211F_PHYCR1, -+ RTL8211F_ALDPS_PLL_OFF | RTL8211F_ALDPS_ENABLE | RTL8211F_ALDPS_XTAL_OFF, -+ priv->phycr1); -+ if (ret < 0) { -+ dev_err(dev, "aldps mode configuration failed: %pe\n", -+ ERR_PTR(ret)); -+ return ret; -+ } -+ -+ ret = rtl8211f_config_rgmii_delay(phydev); -+ if (ret) -+ return ret; -+ - if (!priv->has_phycr2) - return 0; - diff --git a/target/linux/generic/backport-6.18/784-09-v6.19-net-phy-realtek-eliminate-priv-phycr2-variable.patch b/target/linux/generic/backport-6.18/784-09-v6.19-net-phy-realtek-eliminate-priv-phycr2-variable.patch deleted file mode 100644 index 1c67961d2e..0000000000 --- a/target/linux/generic/backport-6.18/784-09-v6.19-net-phy-realtek-eliminate-priv-phycr2-variable.patch +++ /dev/null @@ -1,101 +0,0 @@ -From 27033d06917758d47162581da7e9de8004049dee Mon Sep 17 00:00:00 2001 -From: Vladimir Oltean -Date: Tue, 18 Nov 2025 01:40:29 +0200 -Subject: [PATCH] net: phy: realtek: eliminate priv->phycr2 variable - -The RTL8211F(D)(I)-VD-CG PHY also has support for disabling the CLKOUT, -and we'd like to introduce the "realtek,clkout-disable" property for -that. - -But it isn't done through the PHYCR2 register, and it becomes awkward to -have the driver pretend that it is. So just replace the machine-level -"u16 phycr2" variable with a logical "bool disable_clk_out", which -scales better to the other PHY as well. - -The change is a complete functional equivalent. Before, if the device -tree property was absent, priv->phycr2 would contain the RTL8211F_CLKOUT_EN -bit as read from hardware. Now, we don't save priv->phycr2, but we just -don't call phy_modify_paged() on it. Also, we can simply call -phy_modify_paged() with the "set" argument to 0. - -Signed-off-by: Vladimir Oltean -Link: https://patch.msgid.link/20251117234033.345679-3-vladimir.oltean@nxp.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/realtek/realtek_main.c | 38 ++++++++++++++++---------- - 1 file changed, 23 insertions(+), 15 deletions(-) - ---- a/drivers/net/phy/realtek/realtek_main.c -+++ b/drivers/net/phy/realtek/realtek_main.c -@@ -194,8 +194,8 @@ MODULE_LICENSE("GPL"); - - struct rtl821x_priv { - u16 phycr1; -- u16 phycr2; - bool has_phycr2; -+ bool disable_clk_out; - struct clk *clk; - /* rtl8211f */ - u16 iner; -@@ -266,15 +266,8 @@ static int rtl821x_probe(struct phy_devi - priv->phycr1 |= RTL8211F_ALDPS_PLL_OFF | RTL8211F_ALDPS_ENABLE | RTL8211F_ALDPS_XTAL_OFF; - - priv->has_phycr2 = !(phy_id == RTL_8211FVD_PHYID); -- if (priv->has_phycr2) { -- ret = phy_read_paged(phydev, RTL8211F_PHYCR_PAGE, RTL8211F_PHYCR2); -- if (ret < 0) -- return ret; -- -- priv->phycr2 = ret & RTL8211F_CLKOUT_EN; -- if (of_property_read_bool(dev->of_node, "realtek,clkout-disable")) -- priv->phycr2 &= ~RTL8211F_CLKOUT_EN; -- } -+ priv->disable_clk_out = of_property_read_bool(dev->of_node, -+ "realtek,clkout-disable"); - - phydev->priv = priv; - -@@ -654,6 +647,23 @@ static int rtl8211f_config_rgmii_delay(s - return 0; - } - -+static int rtl8211f_config_clk_out(struct phy_device *phydev) -+{ -+ struct rtl821x_priv *priv = phydev->priv; -+ int ret; -+ -+ /* The value is preserved if the device tree property is absent */ -+ if (!priv->disable_clk_out) -+ return 0; -+ -+ ret = phy_modify_paged(phydev, RTL8211F_PHYCR_PAGE, -+ RTL8211F_PHYCR2, RTL8211F_CLKOUT_EN, 0); -+ if (ret) -+ return ret; -+ -+ return genphy_soft_reset(phydev); -+} -+ - static int rtl8211f_config_init(struct phy_device *phydev) - { - struct rtl821x_priv *priv = phydev->priv; -@@ -682,16 +692,14 @@ static int rtl8211f_config_init(struct p - if (ret) - return ret; - -- ret = phy_modify_paged(phydev, RTL8211F_PHYCR_PAGE, -- RTL8211F_PHYCR2, RTL8211F_CLKOUT_EN, -- priv->phycr2); -- if (ret < 0) { -+ ret = rtl8211f_config_clk_out(phydev); -+ if (ret) { - dev_err(dev, "clkout configuration failed: %pe\n", - ERR_PTR(ret)); - return ret; - } - -- return genphy_soft_reset(phydev); -+ return 0; - } - - static int rtl821x_suspend(struct phy_device *phydev) diff --git a/target/linux/generic/backport-6.18/784-10-v6.19-net-phy-realtek-eliminate-has_phycr2-variable.patch b/target/linux/generic/backport-6.18/784-10-v6.19-net-phy-realtek-eliminate-has_phycr2-variable.patch deleted file mode 100644 index a78cb3d1cc..0000000000 --- a/target/linux/generic/backport-6.18/784-10-v6.19-net-phy-realtek-eliminate-has_phycr2-variable.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 910ac7bfb1af1ae4cd141ef80e03a6729213c189 Mon Sep 17 00:00:00 2001 -From: Vladimir Oltean -Date: Tue, 18 Nov 2025 01:40:30 +0200 -Subject: [PATCH] net: phy: realtek: eliminate has_phycr2 variable - -This variable is assigned in rtl821x_probe() and used in -rtl8211f_config_init(), which is more complex than it needs to be. -Simply testing the same condition from rtl821x_probe() in -rtl8211f_config_init() yields the same result (the PHY driver ID is a -runtime invariant), but with one temporary variable less. - -Signed-off-by: Vladimir Oltean -Reviewed-by: Andrew Lunn -Link: https://patch.msgid.link/20251117234033.345679-4-vladimir.oltean@nxp.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/realtek/realtek_main.c | 6 ++---- - 1 file changed, 2 insertions(+), 4 deletions(-) - ---- a/drivers/net/phy/realtek/realtek_main.c -+++ b/drivers/net/phy/realtek/realtek_main.c -@@ -194,7 +194,6 @@ MODULE_LICENSE("GPL"); - - struct rtl821x_priv { - u16 phycr1; -- bool has_phycr2; - bool disable_clk_out; - struct clk *clk; - /* rtl8211f */ -@@ -245,7 +244,6 @@ static int rtl821x_probe(struct phy_devi - { - struct device *dev = &phydev->mdio.dev; - struct rtl821x_priv *priv; -- u32 phy_id = phydev->drv->phy_id; - int ret; - - priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); -@@ -265,7 +263,6 @@ static int rtl821x_probe(struct phy_devi - if (of_property_read_bool(dev->of_node, "realtek,aldps-enable")) - priv->phycr1 |= RTL8211F_ALDPS_PLL_OFF | RTL8211F_ALDPS_ENABLE | RTL8211F_ALDPS_XTAL_OFF; - -- priv->has_phycr2 = !(phy_id == RTL_8211FVD_PHYID); - priv->disable_clk_out = of_property_read_bool(dev->of_node, - "realtek,clkout-disable"); - -@@ -683,7 +680,8 @@ static int rtl8211f_config_init(struct p - if (ret) - return ret; - -- if (!priv->has_phycr2) -+ /* RTL8211FVD has no PHYCR2 register */ -+ if (phydev->drv->phy_id == RTL_8211FVD_PHYID) - return 0; - - /* Disable PHY-mode EEE so LPI is passed to the MAC */ diff --git a/target/linux/generic/backport-6.18/784-11-v6.19-net-phy-realtek-allow-CLKOUT-to-be-disabled-on-RTL82.patch b/target/linux/generic/backport-6.18/784-11-v6.19-net-phy-realtek-allow-CLKOUT-to-be-disabled-on-RTL82.patch deleted file mode 100644 index 2a3239d4a2..0000000000 --- a/target/linux/generic/backport-6.18/784-11-v6.19-net-phy-realtek-allow-CLKOUT-to-be-disabled-on-RTL82.patch +++ /dev/null @@ -1,101 +0,0 @@ -From e1a31c41bef678afe0d99b7f0dc3711a80c68447 Mon Sep 17 00:00:00 2001 -From: Vladimir Oltean -Date: Tue, 18 Nov 2025 01:40:31 +0200 -Subject: [PATCH] net: phy: realtek: allow CLKOUT to be disabled on - RTL8211F(D)(I)-VD-CG - -Add CLKOUT disable support for RTL8211F(D)(I)-VD-CG. Like with other PHY -variants, this feature might be requested by customers when the clock -output is not used, in order to reduce electromagnetic interference (EMI). - -In the common driver, the CLKOUT configuration is done through PHYCR2. -The RTL_8211FVD_PHYID is singled out as not having that register, and -execution in rtl8211f_config_init() returns early after commit -2c67301584f2 ("net: phy: realtek: Avoid PHYCR2 access if PHYCR2 not -present"). - -But actually CLKOUT is configured through a different register for this -PHY. Instead of pretending this is PHYCR2 (which it is not), just add -some code for modifying this register inside the rtl8211f_disable_clk_out() -function, and move that outside the code portion that runs only if -PHYCR2 exists. - -In practice this reorders the PHYCR2 writes to disable PHY-mode EEE and -to disable the CLKOUT for the normal RTL8211F variants, but this should -be perfectly fine. - -It was not noted that RTL8211F(D)(I)-VD-CG would need a genphy_soft_reset() -call after disabling the CLKOUT. Despite that, we do it out of caution -and for symmetry with the other RTL8211F models. - -Co-developed-by: Clark Wang -Signed-off-by: Clark Wang -Signed-off-by: Vladimir Oltean -Reviewed-by: Andrew Lunn -Link: https://patch.msgid.link/20251117234033.345679-5-vladimir.oltean@nxp.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/realtek/realtek_main.c | 31 ++++++++++++++++++-------- - 1 file changed, 22 insertions(+), 9 deletions(-) - ---- a/drivers/net/phy/realtek/realtek_main.c -+++ b/drivers/net/phy/realtek/realtek_main.c -@@ -90,6 +90,14 @@ - #define RTL8211F_LEDCR_MASK GENMASK(4, 0) - #define RTL8211F_LEDCR_SHIFT 5 - -+/* RTL8211F(D)(I)-VD-CG CLKOUT configuration is specified via magic values -+ * to undocumented register pages. The names here do not reflect the datasheet. -+ * Unlike other PHY models, CLKOUT configuration does not go through PHYCR2. -+ */ -+#define RTL8211FVD_CLKOUT_PAGE 0xd05 -+#define RTL8211FVD_CLKOUT_REG 0x11 -+#define RTL8211FVD_CLKOUT_EN BIT(8) -+ - /* RTL8211F RGMII configuration */ - #define RTL8211F_RGMII_PAGE 0xd08 - -@@ -653,8 +661,13 @@ static int rtl8211f_config_clk_out(struc - if (!priv->disable_clk_out) - return 0; - -- ret = phy_modify_paged(phydev, RTL8211F_PHYCR_PAGE, -- RTL8211F_PHYCR2, RTL8211F_CLKOUT_EN, 0); -+ if (phydev->drv->phy_id == RTL_8211FVD_PHYID) -+ ret = phy_modify_paged(phydev, RTL8211FVD_CLKOUT_PAGE, -+ RTL8211FVD_CLKOUT_REG, -+ RTL8211FVD_CLKOUT_EN, 0); -+ else -+ ret = phy_modify_paged(phydev, RTL8211F_PHYCR_PAGE, -+ RTL8211F_PHYCR2, RTL8211F_CLKOUT_EN, 0); - if (ret) - return ret; - -@@ -680,6 +693,13 @@ static int rtl8211f_config_init(struct p - if (ret) - return ret; - -+ ret = rtl8211f_config_clk_out(phydev); -+ if (ret) { -+ dev_err(dev, "clkout configuration failed: %pe\n", -+ ERR_PTR(ret)); -+ return ret; -+ } -+ - /* RTL8211FVD has no PHYCR2 register */ - if (phydev->drv->phy_id == RTL_8211FVD_PHYID) - return 0; -@@ -690,13 +710,6 @@ static int rtl8211f_config_init(struct p - if (ret) - return ret; - -- ret = rtl8211f_config_clk_out(phydev); -- if (ret) { -- dev_err(dev, "clkout configuration failed: %pe\n", -- ERR_PTR(ret)); -- return ret; -- } -- - return 0; - } - diff --git a/target/linux/generic/backport-6.18/784-12-v6.19-net-phy-realtek-eliminate-priv-phycr1-variable.patch b/target/linux/generic/backport-6.18/784-12-v6.19-net-phy-realtek-eliminate-priv-phycr1-variable.patch deleted file mode 100644 index a2e5abe93f..0000000000 --- a/target/linux/generic/backport-6.18/784-12-v6.19-net-phy-realtek-eliminate-priv-phycr1-variable.patch +++ /dev/null @@ -1,107 +0,0 @@ -From bb78b71faf60d11a15f07e3390fcfd31e5e523bb Mon Sep 17 00:00:00 2001 -From: Vladimir Oltean -Date: Tue, 18 Nov 2025 01:40:32 +0200 -Subject: [PATCH] net: phy: realtek: eliminate priv->phycr1 variable - -Previous changes have replaced the machine-level priv->phycr2 with a -high-level priv->disable_clk_out. This created a discrepancy with -priv->phycr1 which is resolved here, for uniformity. - -One advantage of this new implementation is that we don't read -priv->phycr1 in rtl821x_probe() if we're never going to modify it. - -We never test the positive return code from phy_modify_mmd_changed(), so -we could just as well use phy_modify_mmd(). - -I took the ALDPS feature description from commit d90db36a9e74 ("net: -phy: realtek: add dt property to enable ALDPS mode") and transformed it -into a function comment - the feature is sufficiently non-obvious to -deserve that. - -Signed-off-by: Vladimir Oltean -Reviewed-by: Andrew Lunn -Link: https://patch.msgid.link/20251117234033.345679-6-vladimir.oltean@nxp.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/realtek/realtek_main.c | 44 ++++++++++++++++---------- - 1 file changed, 28 insertions(+), 16 deletions(-) - ---- a/drivers/net/phy/realtek/realtek_main.c -+++ b/drivers/net/phy/realtek/realtek_main.c -@@ -201,7 +201,7 @@ MODULE_AUTHOR("Johnson Leung"); - MODULE_LICENSE("GPL"); - - struct rtl821x_priv { -- u16 phycr1; -+ bool enable_aldps; - bool disable_clk_out; - struct clk *clk; - /* rtl8211f */ -@@ -252,7 +252,6 @@ static int rtl821x_probe(struct phy_devi - { - struct device *dev = &phydev->mdio.dev; - struct rtl821x_priv *priv; -- int ret; - - priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); - if (!priv) -@@ -263,14 +262,8 @@ static int rtl821x_probe(struct phy_devi - return dev_err_probe(dev, PTR_ERR(priv->clk), - "failed to get phy clock\n"); - -- ret = phy_read_paged(phydev, RTL8211F_PHYCR_PAGE, RTL8211F_PHYCR1); -- if (ret < 0) -- return ret; -- -- priv->phycr1 = ret & (RTL8211F_ALDPS_PLL_OFF | RTL8211F_ALDPS_ENABLE | RTL8211F_ALDPS_XTAL_OFF); -- if (of_property_read_bool(dev->of_node, "realtek,aldps-enable")) -- priv->phycr1 |= RTL8211F_ALDPS_PLL_OFF | RTL8211F_ALDPS_ENABLE | RTL8211F_ALDPS_XTAL_OFF; -- -+ priv->enable_aldps = of_property_read_bool(dev->of_node, -+ "realtek,aldps-enable"); - priv->disable_clk_out = of_property_read_bool(dev->of_node, - "realtek,clkout-disable"); - -@@ -674,17 +667,36 @@ static int rtl8211f_config_clk_out(struc - return genphy_soft_reset(phydev); - } - --static int rtl8211f_config_init(struct phy_device *phydev) -+/* Advance Link Down Power Saving (ALDPS) mode changes crystal/clock behaviour, -+ * which causes the RXC clock signal to stop for tens to hundreds of -+ * milliseconds. -+ * -+ * Some MACs need the RXC clock to support their internal RX logic, so ALDPS is -+ * only enabled based on an opt-in device tree property. -+ */ -+static int rtl8211f_config_aldps(struct phy_device *phydev) - { - struct rtl821x_priv *priv = phydev->priv; -+ u16 mask = RTL8211F_ALDPS_PLL_OFF | -+ RTL8211F_ALDPS_ENABLE | -+ RTL8211F_ALDPS_XTAL_OFF; -+ -+ /* The value is preserved if the device tree property is absent */ -+ if (!priv->enable_aldps) -+ return 0; -+ -+ return phy_modify_paged(phydev, RTL8211F_PHYCR_PAGE, RTL8211F_PHYCR1, -+ mask, mask); -+} -+ -+static int rtl8211f_config_init(struct phy_device *phydev) -+{ - struct device *dev = &phydev->mdio.dev; - int ret; - -- ret = phy_modify_paged_changed(phydev, RTL8211F_PHYCR_PAGE, RTL8211F_PHYCR1, -- RTL8211F_ALDPS_PLL_OFF | RTL8211F_ALDPS_ENABLE | RTL8211F_ALDPS_XTAL_OFF, -- priv->phycr1); -- if (ret < 0) { -- dev_err(dev, "aldps mode configuration failed: %pe\n", -+ ret = rtl8211f_config_aldps(phydev); -+ if (ret) { -+ dev_err(dev, "aldps mode configuration failed: %pe\n", - ERR_PTR(ret)); - return ret; - } diff --git a/target/linux/generic/backport-6.18/784-13-v6.19-net-phy-realtek-create-rtl8211f_config_phy_eee-helpe.patch b/target/linux/generic/backport-6.18/784-13-v6.19-net-phy-realtek-create-rtl8211f_config_phy_eee-helpe.patch deleted file mode 100644 index 54ec217aff..0000000000 --- a/target/linux/generic/backport-6.18/784-13-v6.19-net-phy-realtek-create-rtl8211f_config_phy_eee-helpe.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 4465ae435ddc0162d5033a543658449d53d46d08 Mon Sep 17 00:00:00 2001 -From: Vladimir Oltean -Date: Tue, 18 Nov 2025 01:40:33 +0200 -Subject: [PATCH] net: phy: realtek: create rtl8211f_config_phy_eee() helper - -To simplify the rtl8211f_config_init() control flow and get rid of -"early" returns for PHYs where the PHYCR2 register is absent, move the -entire logic sub-block that deals with disabling PHY-mode EEE to a -separate function. There, it is much more obvious what the early -"return 0" skips, and it becomes more difficult to accidentally skip -unintended stuff. - -Signed-off-by: Vladimir Oltean -Link: https://patch.msgid.link/20251117234033.345679-7-vladimir.oltean@nxp.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/realtek/realtek_main.c | 23 ++++++++++++----------- - 1 file changed, 12 insertions(+), 11 deletions(-) - ---- a/drivers/net/phy/realtek/realtek_main.c -+++ b/drivers/net/phy/realtek/realtek_main.c -@@ -689,6 +689,17 @@ static int rtl8211f_config_aldps(struct - mask, mask); - } - -+static int rtl8211f_config_phy_eee(struct phy_device *phydev) -+{ -+ /* RTL8211FVD has no PHYCR2 register */ -+ if (phydev->drv->phy_id == RTL_8211FVD_PHYID) -+ return 0; -+ -+ /* Disable PHY-mode EEE so LPI is passed to the MAC */ -+ return phy_modify_paged(phydev, RTL8211F_PHYCR_PAGE, RTL8211F_PHYCR2, -+ RTL8211F_PHYCR2_PHY_EEE_ENABLE, 0); -+} -+ - static int rtl8211f_config_init(struct phy_device *phydev) - { - struct device *dev = &phydev->mdio.dev; -@@ -712,17 +723,7 @@ static int rtl8211f_config_init(struct p - return ret; - } - -- /* RTL8211FVD has no PHYCR2 register */ -- if (phydev->drv->phy_id == RTL_8211FVD_PHYID) -- return 0; -- -- /* Disable PHY-mode EEE so LPI is passed to the MAC */ -- ret = phy_modify_paged(phydev, RTL8211F_PHYCR_PAGE, RTL8211F_PHYCR2, -- RTL8211F_PHYCR2_PHY_EEE_ENABLE, 0); -- if (ret) -- return ret; -- -- return 0; -+ return rtl8211f_config_phy_eee(phydev); - } - - static int rtl821x_suspend(struct phy_device *phydev) diff --git a/target/linux/generic/backport-6.18/785-v6.18-r8169-fix-RTL8127-hang-on-suspend-shutdown.patch b/target/linux/generic/backport-6.18/785-v6.18-r8169-fix-RTL8127-hang-on-suspend-shutdown.patch deleted file mode 100644 index 269fc89d26..0000000000 --- a/target/linux/generic/backport-6.18/785-v6.18-r8169-fix-RTL8127-hang-on-suspend-shutdown.patch +++ /dev/null @@ -1,50 +0,0 @@ -From ae1737e7339b513f8c2fc21b500a0fc215d155c3 Mon Sep 17 00:00:00 2001 -From: Heiner Kallweit -Date: Sat, 22 Nov 2025 15:23:02 +0100 -Subject: r8169: fix RTL8127 hang on suspend/shutdown - -There have been reports that RTL8127 hangs on suspend and shutdown, -partially disappearing from lspci until power-cycling. -According to Realtek disabling PLL's when switching to D3 should be -avoided on that chip version. Fix this by aligning disabling PLL's -with the vendor drivers, what in addition results in PLL's not being -disabled when switching to D3hot on other chip versions. - -Fixes: f24f7b2f3af9 ("r8169: add support for RTL8127A") -Tested-by: Fabio Baltieri -Cc: stable@vger.kernel.org -Signed-off-by: Heiner Kallweit -Link: https://patch.msgid.link/d7faae7e-66bc-404a-a432-3a496600575f@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/realtek/r8169_main.c | 19 ++++++++++++++----- - 1 file changed, 14 insertions(+), 5 deletions(-) - ---- a/drivers/net/ethernet/realtek/r8169_main.c -+++ b/drivers/net/ethernet/realtek/r8169_main.c -@@ -1516,11 +1516,20 @@ static enum rtl_dash_type rtl_get_dash_t - - static void rtl_set_d3_pll_down(struct rtl8169_private *tp, bool enable) - { -- if (tp->mac_version >= RTL_GIGA_MAC_VER_25 && -- tp->mac_version != RTL_GIGA_MAC_VER_28 && -- tp->mac_version != RTL_GIGA_MAC_VER_31 && -- tp->mac_version != RTL_GIGA_MAC_VER_38) -- r8169_mod_reg8_cond(tp, PMCH, D3_NO_PLL_DOWN, !enable); -+ switch (tp->mac_version) { -+ case RTL_GIGA_MAC_VER_02 ... RTL_GIGA_MAC_VER_24: -+ case RTL_GIGA_MAC_VER_28: -+ case RTL_GIGA_MAC_VER_31: -+ case RTL_GIGA_MAC_VER_38: -+ break; -+ case RTL_GIGA_MAC_VER_80: -+ r8169_mod_reg8_cond(tp, PMCH, D3_NO_PLL_DOWN, true); -+ break; -+ default: -+ r8169_mod_reg8_cond(tp, PMCH, D3HOT_NO_PLL_DOWN, true); -+ r8169_mod_reg8_cond(tp, PMCH, D3COLD_NO_PLL_DOWN, !enable); -+ break; -+ } - } - - static void rtl_reset_packet_filter(struct rtl8169_private *tp) diff --git a/target/linux/generic/backport-6.18/786-01-v6.18-net-phy-introduce-phy_id_compare_vendor-PHY-ID-helpe.patch b/target/linux/generic/backport-6.18/786-01-v6.18-net-phy-introduce-phy_id_compare_vendor-PHY-ID-helpe.patch deleted file mode 100644 index a69a564148..0000000000 --- a/target/linux/generic/backport-6.18/786-01-v6.18-net-phy-introduce-phy_id_compare_vendor-PHY-ID-helpe.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 1abe21ef1adf0c5b6dbb5878c2fa4573df8d29fc Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Sat, 23 Aug 2025 15:44:28 +0200 -Subject: net: phy: introduce phy_id_compare_vendor() PHY ID helper - -Introduce phy_id_compare_vendor() PHY ID helper to compare a PHY ID with -the PHY ID Vendor using the generic PHY ID Vendor mask. - -While at it also rework the PHY_ID_MATCH macro and move the mask to -dedicated define so that PHY driver can make use of the mask if needed. - -Signed-off-by: Christian Marangi -Reviewed-by: Andrew Lunn -Link: https://patch.msgid.link/20250823134431.4854-1-ansuelsmth@gmail.com -Signed-off-by: Jakub Kicinski ---- - include/linux/phy.h | 23 ++++++++++++++++++++--- - 1 file changed, 20 insertions(+), 3 deletions(-) - ---- a/include/linux/phy.h -+++ b/include/linux/phy.h -@@ -1266,9 +1266,13 @@ struct phy_driver { - #define PHY_ANY_ID "MATCH ANY PHY" - #define PHY_ANY_UID 0xffffffff - --#define PHY_ID_MATCH_EXACT(id) .phy_id = (id), .phy_id_mask = GENMASK(31, 0) --#define PHY_ID_MATCH_MODEL(id) .phy_id = (id), .phy_id_mask = GENMASK(31, 4) --#define PHY_ID_MATCH_VENDOR(id) .phy_id = (id), .phy_id_mask = GENMASK(31, 10) -+#define PHY_ID_MATCH_EXTACT_MASK GENMASK(31, 0) -+#define PHY_ID_MATCH_MODEL_MASK GENMASK(31, 4) -+#define PHY_ID_MATCH_VENDOR_MASK GENMASK(31, 10) -+ -+#define PHY_ID_MATCH_EXACT(id) .phy_id = (id), .phy_id_mask = PHY_ID_MATCH_EXTACT_MASK -+#define PHY_ID_MATCH_MODEL(id) .phy_id = (id), .phy_id_mask = PHY_ID_MATCH_MODEL_MASK -+#define PHY_ID_MATCH_VENDOR(id) .phy_id = (id), .phy_id_mask = PHY_ID_MATCH_VENDOR_MASK - - /** - * phy_id_compare - compare @id1 with @id2 taking account of @mask -@@ -1298,6 +1302,19 @@ static inline bool phy_id_compare_model( - } - - /** -+ * phy_id_compare_vendor - compare @id with @vendor mask -+ * @id: PHY ID -+ * @vendor_mask: PHY Vendor mask -+ * -+ * Return: true if the bits from @id match @vendor using the -+ * generic PHY Vendor mask. -+ */ -+static inline bool phy_id_compare_vendor(u32 id, u32 vendor_mask) -+{ -+ return phy_id_compare(id, vendor_mask, PHY_ID_MATCH_VENDOR_MASK); -+} -+ -+/** - * phydev_id_compare - compare @id with the PHY's Clause 22 ID - * @phydev: the PHY device - * @id: the PHY ID to be matched diff --git a/target/linux/generic/backport-6.18/786-02-v6.18-net-phy-as21xxx-better-handle-PHY-HW-reset-on-soft-r.patch b/target/linux/generic/backport-6.18/786-02-v6.18-net-phy-as21xxx-better-handle-PHY-HW-reset-on-soft-r.patch deleted file mode 100644 index 5b00da4024..0000000000 --- a/target/linux/generic/backport-6.18/786-02-v6.18-net-phy-as21xxx-better-handle-PHY-HW-reset-on-soft-r.patch +++ /dev/null @@ -1,45 +0,0 @@ -From b4d5cd20507b252c746fa6971d82ac96f3b3e5b7 Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Sat, 23 Aug 2025 15:44:29 +0200 -Subject: net: phy: as21xxx: better handle PHY HW reset on soft-reboot - -On soft-reboot, with a reset GPIO defined for an Aeonsemi PHY, the -special match_phy_device fails to correctly identify that the PHY -needs to load the firmware again. - -This is caused by the fact that PHY ID is read BEFORE the PHY reset -GPIO (if present) is asserted, so we can be in the scenario where the -phydev have the previous PHY ID (with the PHY firmware loaded) but -after reset the generic AS21xxx PHY is present in the PHY ID registers. - -To better handle this, skip reading the PHY ID register only for the PHY -that are not AS21xxx (by matching for the Aeonsemi Vendor) and always -read the PHY ID for the other case to handle both firmware already -loaded or an HW reset. - -Fixes: 830877d89edc ("net: phy: Add support for Aeonsemi AS21xxx PHYs") -Signed-off-by: Christian Marangi -Link: https://patch.msgid.link/20250823134431.4854-2-ansuelsmth@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/as21xxx.c | 7 ++++--- - 1 file changed, 4 insertions(+), 3 deletions(-) - ---- a/drivers/net/phy/as21xxx.c -+++ b/drivers/net/phy/as21xxx.c -@@ -884,11 +884,12 @@ static int as21xxx_match_phy_device(stru - u32 phy_id; - int ret; - -- /* Skip PHY that are not AS21xxx or already have firmware loaded */ -- if (phydev->c45_ids.device_ids[MDIO_MMD_PCS] != PHY_ID_AS21XXX) -+ /* Skip PHY that are not AS21xxx */ -+ if (!phy_id_compare_vendor(phydev->c45_ids.device_ids[MDIO_MMD_PCS], -+ PHY_VENDOR_AEONSEMI)) - return genphy_match_phy_device(phydev, phydrv); - -- /* Read PHY ID to handle firmware just loaded */ -+ /* Read PHY ID to handle firmware loaded or HW reset */ - ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MII_PHYSID1); - if (ret < 0) - return ret; diff --git a/target/linux/generic/backport-6.18/787-v6.19-net-phy-RTL8211FVD-Restore-disabling-of-PHY-mode-EEE.patch b/target/linux/generic/backport-6.18/787-v6.19-net-phy-RTL8211FVD-Restore-disabling-of-PHY-mode-EEE.patch deleted file mode 100644 index 37290c4e5d..0000000000 --- a/target/linux/generic/backport-6.18/787-v6.19-net-phy-RTL8211FVD-Restore-disabling-of-PHY-mode-EEE.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 4f0638b12451112de4138689fa679315c8d388dc Mon Sep 17 00:00:00 2001 -From: Ivan Galkin -Date: Tue, 2 Dec 2025 10:07:42 +0100 -Subject: net: phy: RTL8211FVD: Restore disabling of PHY-mode EEE - -When support for RTL8211F(D)(I)-VD-CG was introduced in commit -bb726b753f75 ("net: phy: realtek: add support for RTL8211F(D)(I)-VD-CG") -the implementation assumed that this PHY model doesn't have the -control register PHYCR2 (Page 0xa43 Address 0x19). This -assumption was based on the differences in CLKOUT configurations -between RTL8211FVD and the remaining RTL8211F PHYs. In the latter -commit 2c67301584f2 -("net: phy: realtek: Avoid PHYCR2 access if PHYCR2 not present") -this assumption was expanded to the PHY-mode EEE. - -I performed tests on RTL8211FI-VD-CG and confirmed that disabling -PHY-mode EEE works correctly and is uniform with other PHYs -supported by the driver. To validate the correctness, -I contacted Realtek support. Realtek confirmed that PHY-mode EEE on -RTL8211F(D)(I)-VD-CG is configured via Page 0xa43 Address 0x19 bit 5. - -Moreover, Realtek informed me that the most recent datasheet -for RTL8211F(D)(I)-VD-CG v1.1 is incomplete and the naming of -control registers is partly inconsistent. The errata I -received from Realtek corrects the naming as follows: - -| Register | Datasheet v1.1 | Errata | -|-------------------------|----------------|--------| -| Page 0xa44 Address 0x11 | PHYCR2 | PHYCR3 | -| Page 0xa43 Address 0x19 | N/A | PHYCR2 | - -This information confirms that the supposedly missing control register, -PHYCR2, exists in the RTL8211F(D)(I)-VD-CG under the same address and -the same name. It controls widely the same configs as other PHYs from -the RTL8211F series (e.g. PHY-mode EEE). Clock out configuration is an -exception. - -Given all this information, restore disabling of the PHY-mode EEE. - -Fixes: 2c67301584f2 ("net: phy: realtek: Avoid PHYCR2 access if PHYCR2 not present") -Signed-off-by: Ivan Galkin -Reviewed-by: Vladimir Oltean -Link: https://patch.msgid.link/20251202-phy_eee-v1-1-fe0bf6ab3df0@axis.com -Signed-off-by: Paolo Abeni ---- - drivers/net/phy/realtek/realtek_main.c | 4 ---- - 1 file changed, 4 deletions(-) - ---- a/drivers/net/phy/realtek/realtek_main.c -+++ b/drivers/net/phy/realtek/realtek_main.c -@@ -691,10 +691,6 @@ static int rtl8211f_config_aldps(struct - - static int rtl8211f_config_phy_eee(struct phy_device *phydev) - { -- /* RTL8211FVD has no PHYCR2 register */ -- if (phydev->drv->phy_id == RTL_8211FVD_PHYID) -- return 0; -- - /* Disable PHY-mode EEE so LPI is passed to the MAC */ - return phy_modify_paged(phydev, RTL8211F_PHYCR_PAGE, RTL8211F_PHYCR2, - RTL8211F_PHYCR2_PHY_EEE_ENABLE, 0); diff --git a/target/linux/generic/backport-6.18/800-v6.13-hwmon-Add-static-visibility-member-to-struct-hwmon_o.patch b/target/linux/generic/backport-6.18/800-v6.13-hwmon-Add-static-visibility-member-to-struct-hwmon_o.patch deleted file mode 100644 index 0c9f920562..0000000000 --- a/target/linux/generic/backport-6.18/800-v6.13-hwmon-Add-static-visibility-member-to-struct-hwmon_o.patch +++ /dev/null @@ -1,88 +0,0 @@ -From 79bc0af904db647979c735563299c9b0d820e432 Mon Sep 17 00:00:00 2001 -From: Heiner Kallweit -Date: Thu, 10 Oct 2024 21:35:42 +0200 -Subject: [PATCH] hwmon: Add static visibility member to struct hwmon_ops - -Several drivers return the same static value in their is_visible -callback, what results in code duplication. Therefore add an option -for drivers to specify a static visibility directly. - -Signed-off-by: Heiner Kallweit -Message-ID: <89690b81-2c73-47ae-9ae9-45c77b45ca0c@gmail.com> -groeck: Renamed hwmon_ops_is_visible -> hwmon_is_visible -Signed-off-by: Guenter Roeck ---- - drivers/hwmon/hwmon.c | 19 +++++++++++++++---- - include/linux/hwmon.h | 5 ++++- - 2 files changed, 19 insertions(+), 5 deletions(-) - ---- a/drivers/hwmon/hwmon.c -+++ b/drivers/hwmon/hwmon.c -@@ -145,6 +145,17 @@ static const struct class hwmon_class = - - static DEFINE_IDA(hwmon_ida); - -+static umode_t hwmon_is_visible(const struct hwmon_ops *ops, -+ const void *drvdata, -+ enum hwmon_sensor_types type, -+ u32 attr, int channel) -+{ -+ if (ops->visible) -+ return ops->visible; -+ -+ return ops->is_visible(drvdata, type, attr, channel); -+} -+ - /* Thermal zone handling */ - - /* -@@ -267,8 +278,8 @@ static int hwmon_thermal_register_sensor - int err; - - if (!(info[i]->config[j] & HWMON_T_INPUT) || -- !chip->ops->is_visible(drvdata, hwmon_temp, -- hwmon_temp_input, j)) -+ !hwmon_is_visible(chip->ops, drvdata, hwmon_temp, -+ hwmon_temp_input, j)) - continue; - - err = hwmon_thermal_add_sensor(dev, j); -@@ -506,7 +517,7 @@ static struct attribute *hwmon_genattr(c - const char *name; - bool is_string = is_string_attr(type, attr); - -- mode = ops->is_visible(drvdata, type, attr, index); -+ mode = hwmon_is_visible(ops, drvdata, type, attr, index); - if (!mode) - return ERR_PTR(-ENOENT); - -@@ -1033,7 +1044,7 @@ hwmon_device_register_with_info(struct d - if (!dev || !name || !chip) - return ERR_PTR(-EINVAL); - -- if (!chip->ops || !chip->ops->is_visible || !chip->info) -+ if (!chip->ops || !(chip->ops->visible || chip->ops->is_visible) || !chip->info) - return ERR_PTR(-EINVAL); - - return __hwmon_device_register(dev, name, drvdata, chip, extra_groups); ---- a/include/linux/hwmon.h -+++ b/include/linux/hwmon.h -@@ -368,7 +368,9 @@ enum hwmon_intrusion_attributes { - - /** - * struct hwmon_ops - hwmon device operations -- * @is_visible: Callback to return attribute visibility. Mandatory. -+ * @visible: Static visibility. If non-zero, 'is_visible' is ignored. -+ * @is_visible: Callback to return attribute visibility. Mandatory unless -+ * 'visible' is non-zero. - * Parameters are: - * @const void *drvdata: - * Pointer to driver-private data structure passed -@@ -412,6 +414,7 @@ enum hwmon_intrusion_attributes { - * The function returns 0 on success or a negative error number. - */ - struct hwmon_ops { -+ umode_t visible; - umode_t (*is_visible)(const void *drvdata, enum hwmon_sensor_types type, - u32 attr, int channel); - int (*read)(struct device *dev, enum hwmon_sensor_types type, diff --git a/target/linux/generic/backport-6.18/801-01-v6.13-dt-bindings-clocks-add-binding-for-gated-fixed-clock.patch b/target/linux/generic/backport-6.18/801-01-v6.13-dt-bindings-clocks-add-binding-for-gated-fixed-clock.patch deleted file mode 100644 index f5ab8a0e3b..0000000000 --- a/target/linux/generic/backport-6.18/801-01-v6.13-dt-bindings-clocks-add-binding-for-gated-fixed-clock.patch +++ /dev/null @@ -1,82 +0,0 @@ -From a4a7cbe36623ffaabbae413c0eacf40d033db71f Mon Sep 17 00:00:00 2001 -From: Heiko Stuebner -Date: Fri, 6 Sep 2024 10:25:07 +0200 -Subject: dt-bindings: clocks: add binding for gated-fixed-clocks - -In contrast to fixed clocks that are described as ungateable, boards -sometimes use additional oscillators for things like PCIe reference -clocks, that need actual supplies to get enabled and enable-gpios to be -toggled for them to work. - -This adds a binding for such oscillators that are not configurable -themself, but need to handle supplies for them to work. - -In schematics they often can be seen as - - ---------------- -Enable - | 100MHz,3.3V, | - VDD - | 3225 | - GND - | | - OUT - ---------------- - -or similar. The enable pin might be separate but can also just be tied -to the vdd supply, hence it is optional in the binding. - -Signed-off-by: Heiko Stuebner -Reviewed-by: Rob Herring (Arm) -Reviewed-by: Conor Dooley -Link: https://lore.kernel.org/r/20240906082511.2963890-2-heiko@sntech.de -Signed-off-by: Stephen Boyd - ---- /dev/null -+++ b/Documentation/devicetree/bindings/clock/gated-fixed-clock.yaml -@@ -0,0 +1,49 @@ -+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) -+%YAML 1.2 -+--- -+$id: http://devicetree.org/schemas/clock/gated-fixed-clock.yaml# -+$schema: http://devicetree.org/meta-schemas/core.yaml# -+ -+title: Gated Fixed clock -+ -+maintainers: -+ - Heiko Stuebner -+ -+properties: -+ compatible: -+ const: gated-fixed-clock -+ -+ "#clock-cells": -+ const: 0 -+ -+ clock-frequency: true -+ -+ clock-output-names: -+ maxItems: 1 -+ -+ enable-gpios: -+ description: -+ Contains a single GPIO specifier for the GPIO that enables and disables -+ the oscillator. -+ maxItems: 1 -+ -+ vdd-supply: -+ description: handle of the regulator that provides the supply voltage -+ -+required: -+ - compatible -+ - "#clock-cells" -+ - clock-frequency -+ - vdd-supply -+ -+additionalProperties: false -+ -+examples: -+ - | -+ clock-1000000000 { -+ compatible = "gated-fixed-clock"; -+ #clock-cells = <0>; -+ clock-frequency = <1000000000>; -+ vdd-supply = <®_vdd>; -+ }; -+... diff --git a/target/linux/generic/backport-6.18/801-02-v6.13-clk-clk-gpio-update-documentation-for-gpio-gate-cloc.patch b/target/linux/generic/backport-6.18/801-02-v6.13-clk-clk-gpio-update-documentation-for-gpio-gate-cloc.patch deleted file mode 100644 index 99e41a1e99..0000000000 --- a/target/linux/generic/backport-6.18/801-02-v6.13-clk-clk-gpio-update-documentation-for-gpio-gate-cloc.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 6cb137c7e99f8307f1f0fcccb1896f2d3b0651d3 Mon Sep 17 00:00:00 2001 -From: Heiko Stuebner -Date: Fri, 6 Sep 2024 10:25:08 +0200 -Subject: clk: clk-gpio: update documentation for gpio-gate clock - -The main documentation block seems to be from a time before the driver -handled sleeping and non-sleeping gpios and with that change it seems -updating the doc was overlooked. So do that now. - -Signed-off-by: Heiko Stuebner -Link: https://lore.kernel.org/r/20240906082511.2963890-3-heiko@sntech.de -Signed-off-by: Stephen Boyd - ---- a/drivers/clk/clk-gpio.c -+++ b/drivers/clk/clk-gpio.c -@@ -22,8 +22,9 @@ - * DOC: basic gpio gated clock which can be enabled and disabled - * with gpio output - * Traits of this clock: -- * prepare - clk_(un)prepare only ensures parent is (un)prepared -- * enable - clk_enable and clk_disable are functional & control gpio -+ * prepare - clk_(un)prepare are functional and control a gpio that can sleep -+ * enable - clk_enable and clk_disable are functional & control -+ * non-sleeping gpio - * rate - inherits rate from parent. No clk_set_rate support - * parent - fixed parent. No clk_set_parent support - */ diff --git a/target/linux/generic/backport-6.18/801-03-v6.13-clk-clk-gpio-use-dev_err_probe-for-gpio-get-failure.patch b/target/linux/generic/backport-6.18/801-03-v6.13-clk-clk-gpio-use-dev_err_probe-for-gpio-get-failure.patch deleted file mode 100644 index 1982bb365e..0000000000 --- a/target/linux/generic/backport-6.18/801-03-v6.13-clk-clk-gpio-use-dev_err_probe-for-gpio-get-failure.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 36abe81d9c3fa200a57ef2363e93a2991e387e19 Mon Sep 17 00:00:00 2001 -From: Heiko Stuebner -Date: Fri, 6 Sep 2024 10:25:09 +0200 -Subject: clk: clk-gpio: use dev_err_probe for gpio-get failure - -This is a real driver and dev_err_probe will hide the distinction between -EPROBE_DEFER and other errors automatically, so there is no need to -open-code this. - -Signed-off-by: Heiko Stuebner -Link: https://lore.kernel.org/r/20240906082511.2963890-4-heiko@sntech.de -Signed-off-by: Stephen Boyd - ---- a/drivers/clk/clk-gpio.c -+++ b/drivers/clk/clk-gpio.c -@@ -200,7 +200,6 @@ static int gpio_clk_driver_probe(struct - struct gpio_desc *gpiod; - struct clk_hw *hw; - bool is_mux; -- int ret; - - is_mux = of_device_is_compatible(node, "gpio-mux-clock"); - -@@ -212,17 +211,9 @@ static int gpio_clk_driver_probe(struct - - gpio_name = is_mux ? "select" : "enable"; - gpiod = devm_gpiod_get(dev, gpio_name, GPIOD_OUT_LOW); -- if (IS_ERR(gpiod)) { -- ret = PTR_ERR(gpiod); -- if (ret == -EPROBE_DEFER) -- pr_debug("%pOFn: %s: GPIOs not yet available, retry later\n", -- node, __func__); -- else -- pr_err("%pOFn: %s: Can't get '%s' named GPIO property\n", -- node, __func__, -- gpio_name); -- return ret; -- } -+ if (IS_ERR(gpiod)) -+ return dev_err_probe(dev, PTR_ERR(gpiod), -+ "Can't get '%s' named GPIO property\n", gpio_name); - - if (is_mux) - hw = clk_hw_register_gpio_mux(dev, gpiod); diff --git a/target/linux/generic/backport-6.18/801-04-v6.13-clk-clk-gpio-add-driver-for-gated-fixed-clocks.patch b/target/linux/generic/backport-6.18/801-04-v6.13-clk-clk-gpio-add-driver-for-gated-fixed-clocks.patch deleted file mode 100644 index 44da746fdc..0000000000 --- a/target/linux/generic/backport-6.18/801-04-v6.13-clk-clk-gpio-add-driver-for-gated-fixed-clocks.patch +++ /dev/null @@ -1,229 +0,0 @@ -From 4940071d962827467f7297be3b874c96186ca0b7 Mon Sep 17 00:00:00 2001 -From: Heiko Stuebner -Date: Fri, 6 Sep 2024 10:25:10 +0200 -Subject: clk: clk-gpio: add driver for gated-fixed-clocks - -In contrast to fixed clocks that are described as ungateable, boards -sometimes use additional oscillators for things like PCIe reference -clocks, that need actual supplies to get enabled and enable-gpios to be -toggled for them to work. - -This adds a driver for those generic gated-fixed-clocks -that can show up in schematics looking like - - ---------------- -Enable - | 100MHz,3.3V, | - VDD - | 3225 | - GND - | | - OUT - ---------------- - -The new driver gets grouped together with the existing gpio-gate and -gpio-mux, as it for one re-uses a lot of the gpio-gate functions -and also in its core it's just another gpio-controlled clock, just -with a fixed rate and a regulator-supply added in. - -The regulator-API provides function stubs for the !CONFIG_REGULATOR case, -so no special handling is necessary. - -Signed-off-by: Heiko Stuebner -Link: https://lore.kernel.org/r/20240906082511.2963890-5-heiko@sntech.de -Signed-off-by: Stephen Boyd - ---- a/drivers/clk/clk-gpio.c -+++ b/drivers/clk/clk-gpio.c -@@ -17,6 +17,7 @@ - #include - #include - #include -+#include - - /** - * DOC: basic gpio gated clock which can be enabled and disabled -@@ -239,3 +240,187 @@ static struct platform_driver gpio_clk_d - }, - }; - builtin_platform_driver(gpio_clk_driver); -+ -+/** -+ * DOC: gated fixed clock, controlled with a gpio output and a regulator -+ * Traits of this clock: -+ * prepare - clk_prepare and clk_unprepare are function & control regulator -+ * optionally a gpio that can sleep -+ * enable - clk_enable and clk_disable are functional & control gpio -+ * rate - rate is fixed and set on clock registration -+ * parent - fixed clock is a root clock and has no parent -+ */ -+ -+/** -+ * struct clk_gated_fixed - Gateable fixed rate clock -+ * @clk_gpio: instance of clk_gpio for gate-gpio -+ * @supply: supply regulator -+ * @rate: fixed rate -+ */ -+struct clk_gated_fixed { -+ struct clk_gpio clk_gpio; -+ struct regulator *supply; -+ unsigned long rate; -+}; -+ -+#define to_clk_gated_fixed(_clk_gpio) container_of(_clk_gpio, struct clk_gated_fixed, clk_gpio) -+ -+static unsigned long clk_gated_fixed_recalc_rate(struct clk_hw *hw, -+ unsigned long parent_rate) -+{ -+ return to_clk_gated_fixed(to_clk_gpio(hw))->rate; -+} -+ -+static int clk_gated_fixed_prepare(struct clk_hw *hw) -+{ -+ struct clk_gated_fixed *clk = to_clk_gated_fixed(to_clk_gpio(hw)); -+ -+ if (!clk->supply) -+ return 0; -+ -+ return regulator_enable(clk->supply); -+} -+ -+static void clk_gated_fixed_unprepare(struct clk_hw *hw) -+{ -+ struct clk_gated_fixed *clk = to_clk_gated_fixed(to_clk_gpio(hw)); -+ -+ if (!clk->supply) -+ return; -+ -+ regulator_disable(clk->supply); -+} -+ -+static int clk_gated_fixed_is_prepared(struct clk_hw *hw) -+{ -+ struct clk_gated_fixed *clk = to_clk_gated_fixed(to_clk_gpio(hw)); -+ -+ if (!clk->supply) -+ return true; -+ -+ return regulator_is_enabled(clk->supply); -+} -+ -+/* -+ * Fixed gated clock with non-sleeping gpio. -+ * -+ * Prepare operation turns on the supply regulator -+ * and the enable operation switches the enable-gpio. -+ */ -+static const struct clk_ops clk_gated_fixed_ops = { -+ .prepare = clk_gated_fixed_prepare, -+ .unprepare = clk_gated_fixed_unprepare, -+ .is_prepared = clk_gated_fixed_is_prepared, -+ .enable = clk_gpio_gate_enable, -+ .disable = clk_gpio_gate_disable, -+ .is_enabled = clk_gpio_gate_is_enabled, -+ .recalc_rate = clk_gated_fixed_recalc_rate, -+}; -+ -+static int clk_sleeping_gated_fixed_prepare(struct clk_hw *hw) -+{ -+ int ret; -+ -+ ret = clk_gated_fixed_prepare(hw); -+ if (ret) -+ return ret; -+ -+ ret = clk_sleeping_gpio_gate_prepare(hw); -+ if (ret) -+ clk_gated_fixed_unprepare(hw); -+ -+ return ret; -+} -+ -+static void clk_sleeping_gated_fixed_unprepare(struct clk_hw *hw) -+{ -+ clk_gated_fixed_unprepare(hw); -+ clk_sleeping_gpio_gate_unprepare(hw); -+} -+ -+/* -+ * Fixed gated clock with non-sleeping gpio. -+ * -+ * Enabling the supply regulator and switching the enable-gpio happens -+ * both in the prepare step. -+ * is_prepared only needs to check the gpio state, as toggling the -+ * gpio is the last step when preparing. -+ */ -+static const struct clk_ops clk_sleeping_gated_fixed_ops = { -+ .prepare = clk_sleeping_gated_fixed_prepare, -+ .unprepare = clk_sleeping_gated_fixed_unprepare, -+ .is_prepared = clk_sleeping_gpio_gate_is_prepared, -+ .recalc_rate = clk_gated_fixed_recalc_rate, -+}; -+ -+static int clk_gated_fixed_probe(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ struct clk_gated_fixed *clk; -+ const struct clk_ops *ops; -+ const char *clk_name; -+ u32 rate; -+ int ret; -+ -+ clk = devm_kzalloc(dev, sizeof(*clk), GFP_KERNEL); -+ if (!clk) -+ return -ENOMEM; -+ -+ ret = device_property_read_u32(dev, "clock-frequency", &rate); -+ if (ret) -+ return dev_err_probe(dev, ret, "Failed to get clock-frequency\n"); -+ clk->rate = rate; -+ -+ ret = device_property_read_string(dev, "clock-output-names", &clk_name); -+ if (ret) -+ clk_name = fwnode_get_name(dev->fwnode); -+ -+ clk->supply = devm_regulator_get_optional(dev, "vdd"); -+ if (IS_ERR(clk->supply)) { -+ if (PTR_ERR(clk->supply) != -ENODEV) -+ return dev_err_probe(dev, PTR_ERR(clk->supply), -+ "Failed to get regulator\n"); -+ clk->supply = NULL; -+ } -+ -+ clk->clk_gpio.gpiod = devm_gpiod_get_optional(dev, "enable", -+ GPIOD_OUT_LOW); -+ if (IS_ERR(clk->clk_gpio.gpiod)) -+ return dev_err_probe(dev, PTR_ERR(clk->clk_gpio.gpiod), -+ "Failed to get gpio\n"); -+ -+ if (gpiod_cansleep(clk->clk_gpio.gpiod)) -+ ops = &clk_sleeping_gated_fixed_ops; -+ else -+ ops = &clk_gated_fixed_ops; -+ -+ clk->clk_gpio.hw.init = CLK_HW_INIT_NO_PARENT(clk_name, ops, 0); -+ -+ /* register the clock */ -+ ret = devm_clk_hw_register(dev, &clk->clk_gpio.hw); -+ if (ret) -+ return dev_err_probe(dev, ret, -+ "Failed to register clock\n"); -+ -+ ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, -+ &clk->clk_gpio.hw); -+ if (ret) -+ return dev_err_probe(dev, ret, -+ "Failed to register clock provider\n"); -+ -+ return 0; -+} -+ -+static const struct of_device_id gated_fixed_clk_match_table[] = { -+ { .compatible = "gated-fixed-clock" }, -+ { /* sentinel */ } -+}; -+ -+static struct platform_driver gated_fixed_clk_driver = { -+ .probe = clk_gated_fixed_probe, -+ .driver = { -+ .name = "gated-fixed-clk", -+ .of_match_table = gated_fixed_clk_match_table, -+ }, -+}; -+builtin_platform_driver(gated_fixed_clk_driver); diff --git a/target/linux/generic/backport-6.18/810-v6.14-gpio-regmap-Use-generic-request-free-ops.patch b/target/linux/generic/backport-6.18/810-v6.14-gpio-regmap-Use-generic-request-free-ops.patch deleted file mode 100644 index d696acfea4..0000000000 --- a/target/linux/generic/backport-6.18/810-v6.14-gpio-regmap-Use-generic-request-free-ops.patch +++ /dev/null @@ -1,30 +0,0 @@ -From b0fa00fe38f673c986633c11087274deeb7ce7b0 Mon Sep 17 00:00:00 2001 -From: Sander Vanheule -Date: Tue, 7 Jan 2025 21:16:20 +0100 -Subject: [PATCH] gpio: regmap: Use generic request/free ops - -Set the gpiochip request and free ops to the generic implementations. -This way a user can provide a gpio-ranges property defined for a pinmux, -easing muxing of gpio functions. Provided that the pin controller -implementents the pinmux op .gpio_request_enable(), pins will -automatically be muxed to their GPIO function when requested. - -Signed-off-by: Sander Vanheule -Acked-by: Michael Walle -Link: https://lore.kernel.org/r/20250107201621.12467-1-sander@svanheule.net -Signed-off-by: Bartosz Golaszewski ---- - drivers/gpio/gpio-regmap.c | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/drivers/gpio/gpio-regmap.c -+++ b/drivers/gpio/gpio-regmap.c -@@ -276,6 +276,8 @@ struct gpio_regmap *gpio_regmap_register - chip->label = config->label ?: dev_name(config->parent); - chip->can_sleep = regmap_might_sleep(config->regmap); - -+ chip->request = gpiochip_generic_request; -+ chip->free = gpiochip_generic_free; - chip->get = gpio_regmap_get; - if (gpio->reg_set_base && gpio->reg_clr_base) - chip->set = gpio_regmap_set_with_clear; diff --git a/target/linux/generic/backport-6.18/813-v6.16-pinctrl-aw9523-fix-can_sleep-flag-for-GPIO-chip.patch b/target/linux/generic/backport-6.18/813-v6.16-pinctrl-aw9523-fix-can_sleep-flag-for-GPIO-chip.patch deleted file mode 100644 index 97b39215e0..0000000000 --- a/target/linux/generic/backport-6.18/813-v6.16-pinctrl-aw9523-fix-can_sleep-flag-for-GPIO-chip.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 5285b5ed04ab6ad40f7b654eefbccd6ae8cbf415 Mon Sep 17 00:00:00 2001 -From: Milan Krstic -Date: Thu, 3 Jul 2025 14:30:39 +0000 -Subject: [PATCH] pinctrl: aw9523: fix can_sleep flag for GPIO chip - -The GPIO expander is connected via I2C, thus the can_sleep flag has to -be set to true. This fixes spurious "scheduling while atomic" bugs -in the kernel ringbuffer. - -Signed-off-by: David Bauer -Signed-off-by: Milan Krstic -Link: https://lore.kernel.org/20250703143039.5809-1-milan.krstic@gmail.com -Signed-off-by: Linus Walleij ---- - drivers/pinctrl/pinctrl-aw9523.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/pinctrl/pinctrl-aw9523.c -+++ b/drivers/pinctrl/pinctrl-aw9523.c -@@ -784,7 +784,7 @@ static int aw9523_init_gpiochip(struct a - gc->set_config = gpiochip_generic_config; - gc->parent = dev; - gc->owner = THIS_MODULE; -- gc->can_sleep = false; -+ gc->can_sleep = true; - - return 0; - } diff --git a/target/linux/generic/backport-6.18/820-v6.15-power-supply-sysfs-remove-duplicate-nul-termination-to-fix-build-with-GCC15.patch b/target/linux/generic/backport-6.18/820-v6.15-power-supply-sysfs-remove-duplicate-nul-termination-to-fix-build-with-GCC15.patch deleted file mode 100644 index 48f9c1c264..0000000000 --- a/target/linux/generic/backport-6.18/820-v6.15-power-supply-sysfs-remove-duplicate-nul-termination-to-fix-build-with-GCC15.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 77f5bb150132bbbcd6bc37ffdc80c9e140e373a4 Mon Sep 17 00:00:00 2001 -From: Kees Cook -Date: Wed, 16 Apr 2025 15:27:41 -0700 -Subject: [PATCH] power: supply: sysfs: Remove duplicate NUL termination - -GCC 15's new -Wunterminated-string-initialization notices that one of -the sysfs attr strings would lack the implicit trailing NUL byte during -initialization: - -drivers/power/supply/power_supply_sysfs.c:183:57: warning: initializer-string for array of 'char' truncates NUL terminator but destination lacks 'nonstring' attribute (32 chars into 31 available) [-Wunterminated-string-initialization] - 183 | POWER_SUPPLY_ATTR(CHARGE_CONTROL_START_THRESHOLD), - | ^ -drivers/power/supply/power_supply_sysfs.c:36:23: note: in definition of macro '_POWER_SUPPLY_ATTR' - 36 | .attr_name = #_name "\0", \ - | ^~~~~ -drivers/power/supply/power_supply_sysfs.c:183:9: note: in expansion of macro 'POWER_SUPPLY_ATTR' - 183 | POWER_SUPPLY_ATTR(CHARGE_CONTROL_START_THRESHOLD), - | ^~~~~~~~~~~~~~~~~ - -However, the macro used was explicitly adding a trailing NUL byte (which -is not needed). Remove this to avoid the GCC warning. No binary -differences are seen after this change (there was always run for a NUL -byte, it's just that the _second_ NUL byte was getting truncated). - -Signed-off-by: Kees Cook -Link: https://lore.kernel.org/r/20250416222740.work.569-kees@kernel.org -Signed-off-by: Sebastian Reichel - ---- a/drivers/power/supply/power_supply_sysfs.c -+++ b/drivers/power/supply/power_supply_sysfs.c -@@ -33,7 +33,7 @@ struct power_supply_attr { - [POWER_SUPPLY_PROP_ ## _name] = \ - { \ - .prop_name = #_name, \ -- .attr_name = #_name "\0", \ -+ .attr_name = #_name, \ - .text_values = _text, \ - .text_values_len = _len, \ - } diff --git a/target/linux/generic/backport-6.18/891-v6.14-dt-bindings-leds-Add-LED1202-LED-Controller.patch b/target/linux/generic/backport-6.18/891-v6.14-dt-bindings-leds-Add-LED1202-LED-Controller.patch deleted file mode 100644 index 9901d13241..0000000000 --- a/target/linux/generic/backport-6.18/891-v6.14-dt-bindings-leds-Add-LED1202-LED-Controller.patch +++ /dev/null @@ -1,160 +0,0 @@ -From 599b92fd0efa8b7c43e7f58c9dd0f7951f7cbf09 Mon Sep 17 00:00:00 2001 -From: Vicentiu Galanopulo -Date: Wed, 18 Dec 2024 18:33:58 +0000 -Subject: dt-bindings: leds: Add LED1202 LED Controller - -The LED1202 is a 12-channel low quiescent current LED driver with: - * Supply range from 2.6 V to 5 V - * 20 mA current capability per channel - * 1.8 V compatible I2C control interface - * 8-bit analog dimming individual control - * 12-bit local PWM resolution - * 8 programmable patterns - -If the led node is present in the controller then the channel is -set to active. - -Signed-off-by: Vicentiu Galanopulo -Reviewed-by: Krzysztof Kozlowski -Link: https://lore.kernel.org/r/20241218183401.41687-3-vicentiu.galanopulo@remote-tech.co.uk -Signed-off-by: Lee Jones ---- - .../devicetree/bindings/leds/st,led1202.yaml | 132 ++++++++++++++++++ - 1 file changed, 132 insertions(+) - create mode 100644 Documentation/devicetree/bindings/leds/st,led1202.yaml - ---- /dev/null -+++ b/Documentation/devicetree/bindings/leds/st,led1202.yaml -@@ -0,0 +1,132 @@ -+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause -+%YAML 1.2 -+--- -+$id: http://devicetree.org/schemas/leds/st,led1202.yaml# -+$schema: http://devicetree.org/meta-schemas/core.yaml# -+ -+title: ST LED1202 LED controllers -+ -+maintainers: -+ - Vicentiu Galanopulo -+ -+description: | -+ The LED1202 is a 12-channel low quiescent current LED controller -+ programmable via I2C; The output current can be adjusted separately -+ for each channel by 8-bit analog and 12-bit digital dimming control. -+ Datasheet available at -+ https://www.st.com/en/power-management/led1202.html -+ -+properties: -+ compatible: -+ const: st,led1202 -+ -+ reg: -+ maxItems: 1 -+ -+ "#address-cells": -+ const: 1 -+ -+ "#size-cells": -+ const: 0 -+ -+patternProperties: -+ "^led@[0-9a-f]$": -+ type: object -+ $ref: common.yaml# -+ unevaluatedProperties: false -+ -+ properties: -+ reg: -+ minimum: 0 -+ maximum: 11 -+ -+ required: -+ - reg -+ -+required: -+ - compatible -+ - reg -+ - "#address-cells" -+ - "#size-cells" -+ -+additionalProperties: false -+ -+examples: -+ - | -+ #include -+ -+ i2c { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ led-controller@58 { -+ compatible = "st,led1202"; -+ reg = <0x58>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ led@0 { -+ reg = <0x0>; -+ function = LED_FUNCTION_STATUS; -+ color = ; -+ function-enumerator = <1>; -+ }; -+ -+ led@1 { -+ reg = <0x1>; -+ function = LED_FUNCTION_STATUS; -+ color = ; -+ function-enumerator = <2>; -+ }; -+ -+ led@2 { -+ reg = <0x2>; -+ function = LED_FUNCTION_STATUS; -+ color = ; -+ function-enumerator = <3>; -+ }; -+ -+ led@3 { -+ reg = <0x3>; -+ function = LED_FUNCTION_STATUS; -+ color = ; -+ function-enumerator = <4>; -+ }; -+ -+ led@4 { -+ reg = <0x4>; -+ function = LED_FUNCTION_STATUS; -+ color = ; -+ function-enumerator = <5>; -+ }; -+ -+ led@5 { -+ reg = <0x5>; -+ function = LED_FUNCTION_STATUS; -+ color = ; -+ function-enumerator = <6>; -+ }; -+ -+ led@6 { -+ reg = <0x6>; -+ function = LED_FUNCTION_STATUS; -+ color = ; -+ function-enumerator = <7>; -+ }; -+ -+ led@7 { -+ reg = <0x7>; -+ function = LED_FUNCTION_STATUS; -+ color = ; -+ function-enumerator = <8>; -+ }; -+ -+ led@8 { -+ reg = <0x8>; -+ function = LED_FUNCTION_STATUS; -+ color = ; -+ function-enumerator = <9>; -+ }; -+ }; -+ }; -+... diff --git a/target/linux/generic/backport-6.18/892-v6.14-leds-Add-LED1202-I2C-driver.patch b/target/linux/generic/backport-6.18/892-v6.14-leds-Add-LED1202-I2C-driver.patch deleted file mode 100644 index ee2ea076fa..0000000000 --- a/target/linux/generic/backport-6.18/892-v6.14-leds-Add-LED1202-I2C-driver.patch +++ /dev/null @@ -1,475 +0,0 @@ -From 939757aafeb9c266dda37657ee5f7a73ffd35ae2 Mon Sep 17 00:00:00 2001 -From: Vicentiu Galanopulo -Date: Wed, 18 Dec 2024 18:33:59 +0000 -Subject: leds: Add LED1202 I2C driver - -The output current can be adjusted separately for each channel by 8-bit -analog (current sink input) and 12-bit digital (PWM) dimming control. The -LED1202 implements 12 low-side current generators with independent dimming -control. -Internal volatile memory allows the user to store up to 8 different patterns, -each pattern is a particular output configuration in terms of PWM -duty-cycle (on 4096 steps). Analog dimming (on 256 steps) is per channel but -common to all patterns. Each device tree LED node will have a corresponding -entry in /sys/class/leds with the label name. The brightness property -corresponds to the per channel analog dimming, while the patterns[1-8] to the -PWM dimming control. - -Signed-off-by: Vicentiu Galanopulo -Link: https://lore.kernel.org/r/20241218183401.41687-4-vicentiu.galanopulo@remote-tech.co.uk -Signed-off-by: Lee Jones ---- - drivers/leds/Kconfig | 10 + - drivers/leds/Makefile | 1 + - drivers/leds/leds-st1202.c | 416 +++++++++++++++++++++++++++++++++++++ - 3 files changed, 427 insertions(+) - create mode 100644 drivers/leds/leds-st1202.c - ---- a/drivers/leds/Kconfig -+++ b/drivers/leds/Kconfig -@@ -931,6 +931,16 @@ config LEDS_LM36274 - Say Y to enable the LM36274 LED driver for TI LMU devices. - This supports the LED device LM36274. - -+config LEDS_ST1202 -+ tristate "LED Support for STMicroelectronics LED1202 I2C chips" -+ depends on LEDS_CLASS -+ depends on I2C -+ depends on OF -+ select LEDS_TRIGGERS -+ help -+ Say Y to enable support for LEDs connected to LED1202 -+ LED driver chips accessed via the I2C bus. -+ - config LEDS_TPS6105X - tristate "LED support for TI TPS6105X" - depends on LEDS_CLASS ---- a/drivers/leds/Makefile -+++ b/drivers/leds/Makefile -@@ -81,6 +81,7 @@ obj-$(CONFIG_LEDS_POWERNV) += leds-powe - obj-$(CONFIG_LEDS_PWM) += leds-pwm.o - obj-$(CONFIG_LEDS_REGULATOR) += leds-regulator.o - obj-$(CONFIG_LEDS_SC27XX_BLTC) += leds-sc27xx-bltc.o -+obj-$(CONFIG_LEDS_ST1202) += leds-st1202.o - obj-$(CONFIG_LEDS_SUN50I_A100) += leds-sun50i-a100.o - obj-$(CONFIG_LEDS_SUNFIRE) += leds-sunfire.o - obj-$(CONFIG_LEDS_SYSCON) += leds-syscon.o ---- /dev/null -+++ b/drivers/leds/leds-st1202.c -@@ -0,0 +1,416 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* -+ * LED driver for STMicroelectronics LED1202 chip -+ * -+ * Copyright (C) 2024 Remote-Tech Ltd. UK -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define ST1202_CHAN_DISABLE_ALL 0x00 -+#define ST1202_CHAN_ENABLE_HIGH 0x03 -+#define ST1202_CHAN_ENABLE_LOW 0x02 -+#define ST1202_CONFIG_REG 0x04 -+/* PATS: Pattern sequence feature enable */ -+#define ST1202_CONFIG_REG_PATS BIT(7) -+/* PATSR: Pattern sequence runs (self-clear when sequence is finished) */ -+#define ST1202_CONFIG_REG_PATSR BIT(6) -+#define ST1202_CONFIG_REG_SHFT BIT(3) -+#define ST1202_DEV_ENABLE 0x01 -+#define ST1202_DEV_ENABLE_ON BIT(0) -+#define ST1202_DEV_ENABLE_RESET BIT(7) -+#define ST1202_DEVICE_ID 0x00 -+#define ST1202_ILED_REG0 0x09 -+#define ST1202_MAX_LEDS 12 -+#define ST1202_MAX_PATTERNS 8 -+#define ST1202_MILLIS_PATTERN_DUR_MAX 5660 -+#define ST1202_MILLIS_PATTERN_DUR_MIN 22 -+#define ST1202_PATTERN_DUR 0x16 -+#define ST1202_PATTERN_PWM 0x1E -+#define ST1202_PATTERN_REP 0x15 -+ -+struct st1202_led { -+ struct fwnode_handle *fwnode; -+ struct led_classdev led_cdev; -+ struct st1202_chip *chip; -+ bool is_active; -+ int led_num; -+}; -+ -+struct st1202_chip { -+ struct i2c_client *client; -+ struct mutex lock; -+ struct st1202_led leds[ST1202_MAX_LEDS]; -+}; -+ -+static struct st1202_led *cdev_to_st1202_led(struct led_classdev *cdev) -+{ -+ return container_of(cdev, struct st1202_led, led_cdev); -+} -+ -+static int st1202_read_reg(struct st1202_chip *chip, int reg, uint8_t *val) -+{ -+ struct device *dev = &chip->client->dev; -+ int ret; -+ -+ ret = i2c_smbus_read_byte_data(chip->client, reg); -+ if (ret < 0) { -+ dev_err(dev, "Failed to read register [0x%x]: %d\n", reg, ret); -+ return ret; -+ } -+ -+ *val = (uint8_t)ret; -+ return 0; -+} -+ -+static int st1202_write_reg(struct st1202_chip *chip, int reg, uint8_t val) -+{ -+ struct device *dev = &chip->client->dev; -+ int ret; -+ -+ ret = i2c_smbus_write_byte_data(chip->client, reg, val); -+ if (ret != 0) -+ dev_err(dev, "Failed to write %d to register [0x%x]: %d\n", val, reg, ret); -+ -+ return ret; -+} -+ -+static uint8_t st1202_prescalar_to_miliseconds(unsigned int value) -+{ -+ return value / ST1202_MILLIS_PATTERN_DUR_MIN - 1; -+} -+ -+static int st1202_pwm_pattern_write(struct st1202_chip *chip, int led_num, -+ int pattern, unsigned int value) -+{ -+ u8 value_l, value_h; -+ int ret; -+ -+ value_l = (u8)value; -+ value_h = (u8)(value >> 8); -+ -+ /* -+ * Datasheet: Register address low = 1Eh + 2*(xh) + 18h*(yh), -+ * where x is the channel number (led number) in hexadecimal (x = 00h .. 0Bh) -+ * and y is the pattern number in hexadecimal (y = 00h .. 07h) -+ */ -+ ret = st1202_write_reg(chip, (ST1202_PATTERN_PWM + (led_num * 2) + 0x18 * pattern), -+ value_l); -+ if (ret != 0) -+ return ret; -+ -+ /* -+ * Datasheet: Register address high = 1Eh + 01h + 2(xh) +18h*(yh), -+ * where x is the channel number in hexadecimal (x = 00h .. 0Bh) -+ * and y is the pattern number in hexadecimal (y = 00h .. 07h) -+ */ -+ ret = st1202_write_reg(chip, (ST1202_PATTERN_PWM + 0x1 + (led_num * 2) + 0x18 * pattern), -+ value_h); -+ if (ret != 0) -+ return ret; -+ -+ return 0; -+} -+ -+static int st1202_duration_pattern_write(struct st1202_chip *chip, int pattern, -+ unsigned int value) -+{ -+ return st1202_write_reg(chip, (ST1202_PATTERN_DUR + pattern), -+ st1202_prescalar_to_miliseconds(value)); -+} -+ -+static void st1202_brightness_set(struct led_classdev *led_cdev, -+ enum led_brightness value) -+{ -+ struct st1202_led *led = cdev_to_st1202_led(led_cdev); -+ struct st1202_chip *chip = led->chip; -+ -+ guard(mutex)(&chip->lock); -+ -+ st1202_write_reg(chip, ST1202_ILED_REG0 + led->led_num, value); -+} -+ -+static enum led_brightness st1202_brightness_get(struct led_classdev *led_cdev) -+{ -+ struct st1202_led *led = cdev_to_st1202_led(led_cdev); -+ struct st1202_chip *chip = led->chip; -+ u8 value = 0; -+ -+ guard(mutex)(&chip->lock); -+ -+ st1202_read_reg(chip, ST1202_ILED_REG0 + led->led_num, &value); -+ -+ return value; -+} -+ -+static int st1202_channel_set(struct st1202_chip *chip, int led_num, bool active) -+{ -+ u8 chan_low, chan_high; -+ int ret; -+ -+ guard(mutex)(&chip->lock); -+ -+ if (led_num <= 7) { -+ ret = st1202_read_reg(chip, ST1202_CHAN_ENABLE_LOW, &chan_low); -+ if (ret < 0) -+ return ret; -+ -+ chan_low = active ? chan_low | BIT(led_num) : chan_low & ~BIT(led_num); -+ -+ ret = st1202_write_reg(chip, ST1202_CHAN_ENABLE_LOW, chan_low); -+ if (ret < 0) -+ return ret; -+ -+ } else { -+ ret = st1202_read_reg(chip, ST1202_CHAN_ENABLE_HIGH, &chan_high); -+ if (ret < 0) -+ return ret; -+ -+ chan_high = active ? chan_high | (BIT(led_num) >> 8) : -+ chan_high & ~(BIT(led_num) >> 8); -+ -+ ret = st1202_write_reg(chip, ST1202_CHAN_ENABLE_HIGH, chan_high); -+ if (ret < 0) -+ return ret; -+ } -+ -+ return 0; -+} -+ -+static int st1202_led_set(struct led_classdev *ldev, enum led_brightness value) -+{ -+ struct st1202_led *led = cdev_to_st1202_led(ldev); -+ struct st1202_chip *chip = led->chip; -+ -+ return st1202_channel_set(chip, led->led_num, value == LED_OFF ? false : true); -+} -+ -+static int st1202_led_pattern_clear(struct led_classdev *ldev) -+{ -+ struct st1202_led *led = cdev_to_st1202_led(ldev); -+ struct st1202_chip *chip = led->chip; -+ int ret; -+ -+ guard(mutex)(&chip->lock); -+ -+ for (int patt = 0; patt < ST1202_MAX_PATTERNS; patt++) { -+ ret = st1202_pwm_pattern_write(chip, led->led_num, patt, LED_OFF); -+ if (ret != 0) -+ return ret; -+ -+ ret = st1202_duration_pattern_write(chip, patt, ST1202_MILLIS_PATTERN_DUR_MIN); -+ if (ret != 0) -+ return ret; -+ } -+ -+ return 0; -+} -+ -+static int st1202_led_pattern_set(struct led_classdev *ldev, -+ struct led_pattern *pattern, -+ u32 len, int repeat) -+{ -+ struct st1202_led *led = cdev_to_st1202_led(ldev); -+ struct st1202_chip *chip = led->chip; -+ int ret; -+ -+ if (len > ST1202_MAX_PATTERNS) -+ return -EINVAL; -+ -+ guard(mutex)(&chip->lock); -+ -+ for (int patt = 0; patt < len; patt++) { -+ if (pattern[patt].delta_t < ST1202_MILLIS_PATTERN_DUR_MIN || -+ pattern[patt].delta_t > ST1202_MILLIS_PATTERN_DUR_MAX) -+ return -EINVAL; -+ -+ ret = st1202_pwm_pattern_write(chip, led->led_num, patt, pattern[patt].brightness); -+ if (ret != 0) -+ return ret; -+ -+ ret = st1202_duration_pattern_write(chip, patt, pattern[patt].delta_t); -+ if (ret != 0) -+ return ret; -+ } -+ -+ ret = st1202_write_reg(chip, ST1202_PATTERN_REP, repeat); -+ if (ret != 0) -+ return ret; -+ -+ ret = st1202_write_reg(chip, ST1202_CONFIG_REG, (ST1202_CONFIG_REG_PATSR | -+ ST1202_CONFIG_REG_PATS | ST1202_CONFIG_REG_SHFT)); -+ if (ret != 0) -+ return ret; -+ -+ return 0; -+} -+ -+static int st1202_dt_init(struct st1202_chip *chip) -+{ -+ struct device *dev = &chip->client->dev; -+ struct st1202_led *led; -+ int err, reg; -+ -+ for_each_available_child_of_node_scoped(dev_of_node(dev), child) { -+ struct led_init_data init_data = {}; -+ -+ err = of_property_read_u32(child, "reg", ®); -+ if (err) -+ return dev_err_probe(dev, err, "Invalid register\n"); -+ -+ led = &chip->leds[reg]; -+ led->is_active = true; -+ led->fwnode = of_fwnode_handle(child); -+ -+ led->led_cdev.max_brightness = U8_MAX; -+ led->led_cdev.brightness_set_blocking = st1202_led_set; -+ led->led_cdev.pattern_set = st1202_led_pattern_set; -+ led->led_cdev.pattern_clear = st1202_led_pattern_clear; -+ led->led_cdev.default_trigger = "pattern"; -+ -+ init_data.fwnode = led->fwnode; -+ init_data.devicename = "st1202"; -+ init_data.default_label = ":"; -+ -+ err = devm_led_classdev_register_ext(dev, &led->led_cdev, &init_data); -+ if (err < 0) -+ return dev_err_probe(dev, err, "Failed to register LED class device\n"); -+ -+ led->led_cdev.brightness_set = st1202_brightness_set; -+ led->led_cdev.brightness_get = st1202_brightness_get; -+ } -+ -+ return 0; -+} -+ -+static int st1202_setup(struct st1202_chip *chip) -+{ -+ int ret; -+ -+ guard(mutex)(&chip->lock); -+ -+ /* -+ * Once the supply voltage is applied, the LED1202 executes some internal checks, -+ * afterwords it stops the oscillator and puts the internal LDO in quiescent mode. -+ * To start the device, EN bit must be set inside the “Device Enable” register at -+ * address 01h. As soon as EN is set, the LED1202 loads the adjustment parameters -+ * from the internal non-volatile memory and performs an auto-calibration procedure -+ * in order to increase the output current precision. -+ * Such initialization lasts about 6.5 ms. -+ */ -+ -+ /* Reset the chip during setup */ -+ ret = st1202_write_reg(chip, ST1202_DEV_ENABLE, ST1202_DEV_ENABLE_RESET); -+ if (ret < 0) -+ return ret; -+ -+ /* Enable phase-shift delay feature */ -+ ret = st1202_write_reg(chip, ST1202_CONFIG_REG, ST1202_CONFIG_REG_SHFT); -+ if (ret < 0) -+ return ret; -+ -+ /* Enable the device */ -+ ret = st1202_write_reg(chip, ST1202_DEV_ENABLE, ST1202_DEV_ENABLE_ON); -+ if (ret < 0) -+ return ret; -+ -+ /* Duration of initialization */ -+ usleep_range(6500, 10000); -+ -+ /* Deactivate all LEDS (channels) and activate only the ones found in Device Tree */ -+ ret = st1202_write_reg(chip, ST1202_CHAN_ENABLE_LOW, ST1202_CHAN_DISABLE_ALL); -+ if (ret < 0) -+ return ret; -+ -+ ret = st1202_write_reg(chip, ST1202_CHAN_ENABLE_HIGH, ST1202_CHAN_DISABLE_ALL); -+ if (ret < 0) -+ return ret; -+ -+ ret = st1202_write_reg(chip, ST1202_CONFIG_REG, -+ ST1202_CONFIG_REG_PATS | ST1202_CONFIG_REG_PATSR); -+ if (ret < 0) -+ return ret; -+ -+ return 0; -+} -+ -+static int st1202_probe(struct i2c_client *client) -+{ -+ struct st1202_chip *chip; -+ struct st1202_led *led; -+ int ret; -+ -+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) -+ return dev_err_probe(&client->dev, -EIO, "SMBUS Byte Data not Supported\n"); -+ -+ chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL); -+ if (!chip) -+ return -ENOMEM; -+ -+ devm_mutex_init(&client->dev, &chip->lock); -+ chip->client = client; -+ -+ ret = st1202_dt_init(chip); -+ if (ret < 0) -+ return ret; -+ -+ ret = st1202_setup(chip); -+ if (ret < 0) -+ return ret; -+ -+ for (int i = 0; i < ST1202_MAX_LEDS; i++) { -+ led = &chip->leds[i]; -+ led->chip = chip; -+ led->led_num = i; -+ -+ if (!led->is_active) -+ continue; -+ -+ ret = st1202_channel_set(led->chip, led->led_num, true); -+ if (ret < 0) -+ return dev_err_probe(&client->dev, ret, -+ "Failed to activate LED channel\n"); -+ -+ ret = st1202_led_pattern_clear(&led->led_cdev); -+ if (ret < 0) -+ return dev_err_probe(&client->dev, ret, -+ "Failed to clear LED pattern\n"); -+ } -+ -+ return 0; -+} -+ -+static const struct i2c_device_id st1202_id[] = { -+ { "st1202-i2c" }, -+ { /* sentinel */ } -+}; -+MODULE_DEVICE_TABLE(i2c, st1202_id); -+ -+static const struct of_device_id st1202_dt_ids[] = { -+ { .compatible = "st,led1202" }, -+ { /* sentinel */ } -+}; -+MODULE_DEVICE_TABLE(of, st1202_dt_ids); -+ -+static struct i2c_driver st1202_driver = { -+ .driver = { -+ .name = "leds-st1202", -+ .of_match_table = of_match_ptr(st1202_dt_ids), -+ }, -+ .probe = st1202_probe, -+ .id_table = st1202_id, -+}; -+module_i2c_driver(st1202_driver); -+ -+MODULE_AUTHOR("Remote Tech LTD"); -+MODULE_DESCRIPTION("STMicroelectronics LED1202 : 12-channel constant current LED driver"); -+MODULE_LICENSE("GPL"); diff --git a/target/linux/generic/backport-6.18/893-v6.14-leds_st1202-Fix-NULL-pointer-access-error.patch b/target/linux/generic/backport-6.18/893-v6.14-leds_st1202-Fix-NULL-pointer-access-error.patch deleted file mode 100644 index 39d8ddbf74..0000000000 --- a/target/linux/generic/backport-6.18/893-v6.14-leds_st1202-Fix-NULL-pointer-access-error.patch +++ /dev/null @@ -1,73 +0,0 @@ -From c72e455b89f216b43cd0dbb518036ec4c98f5c46 Mon Sep 17 00:00:00 2001 -From: Manuel Fombuena -Date: Tue, 25 Feb 2025 22:01:02 +0000 -Subject: leds: leds-st1202: Fix NULL pointer access on race condition - -st1202_dt_init() calls devm_led_classdev_register_ext() before the -internal data structures are properly set up, so the LEDs become visible -to user space while being partially initialized, leading to a window -where trying to access them causes a NULL pointer access. - -Move devm_led_classdev_register_ext() from DT initialization -to the end of the probe function when DT and hardware are fully -initialized and ready to interact with user space. - -Fixes: 259230378c65 ("leds: Add LED1202 I2C driver") -Signed-off-by: Manuel Fombuena -Link: https://lore.kernel.org/r/CWLP123MB54732771AC0CE5491B3C84DCC5C32@CWLP123MB5473.GBRP123.PROD.OUTLOOK.COM -Signed-off-by: Lee Jones ---- - drivers/leds/leds-st1202.c | 21 ++++++++++----------- - 1 file changed, 10 insertions(+), 11 deletions(-) - ---- a/drivers/leds/leds-st1202.c -+++ b/drivers/leds/leds-st1202.c -@@ -261,8 +261,6 @@ static int st1202_dt_init(struct st1202_ - int err, reg; - - for_each_available_child_of_node_scoped(dev_of_node(dev), child) { -- struct led_init_data init_data = {}; -- - err = of_property_read_u32(child, "reg", ®); - if (err) - return dev_err_probe(dev, err, "Invalid register\n"); -@@ -276,15 +274,6 @@ static int st1202_dt_init(struct st1202_ - led->led_cdev.pattern_set = st1202_led_pattern_set; - led->led_cdev.pattern_clear = st1202_led_pattern_clear; - led->led_cdev.default_trigger = "pattern"; -- -- init_data.fwnode = led->fwnode; -- init_data.devicename = "st1202"; -- init_data.default_label = ":"; -- -- err = devm_led_classdev_register_ext(dev, &led->led_cdev, &init_data); -- if (err < 0) -- return dev_err_probe(dev, err, "Failed to register LED class device\n"); -- - led->led_cdev.brightness_set = st1202_brightness_set; - led->led_cdev.brightness_get = st1202_brightness_get; - } -@@ -368,6 +357,7 @@ static int st1202_probe(struct i2c_clien - return ret; - - for (int i = 0; i < ST1202_MAX_LEDS; i++) { -+ struct led_init_data init_data = {}; - led = &chip->leds[i]; - led->chip = chip; - led->led_num = i; -@@ -384,6 +374,15 @@ static int st1202_probe(struct i2c_clien - if (ret < 0) - return dev_err_probe(&client->dev, ret, - "Failed to clear LED pattern\n"); -+ -+ init_data.fwnode = led->fwnode; -+ init_data.devicename = "st1202"; -+ init_data.default_label = ":"; -+ -+ ret = devm_led_classdev_register_ext(&client->dev, &led->led_cdev, &init_data); -+ if (ret < 0) -+ return dev_err_probe(&client->dev, ret, -+ "Failed to register LED class device\n"); - } - - return 0; diff --git a/target/linux/generic/backport-6.18/900-v6.14-driver-core-add-a-faux-bus-for-use-when-a-simple-dev.patch b/target/linux/generic/backport-6.18/900-v6.14-driver-core-add-a-faux-bus-for-use-when-a-simple-dev.patch deleted file mode 100644 index 1ada8a6ef4..0000000000 --- a/target/linux/generic/backport-6.18/900-v6.14-driver-core-add-a-faux-bus-for-use-when-a-simple-dev.patch +++ /dev/null @@ -1,386 +0,0 @@ -From 35fa2d88ca9481e5caf533d58b99ca259c63b2fe Mon Sep 17 00:00:00 2001 -From: Greg Kroah-Hartman -Date: Mon, 10 Feb 2025 13:30:25 +0100 -Subject: [PATCH] driver core: add a faux bus for use when a simple device/bus - is needed -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Many drivers abuse the platform driver/bus system as it provides a -simple way to create and bind a device to a driver-specific set of -probe/release functions. Instead of doing that, and wasting all of the -memory associated with a platform device, here is a "faux" bus that -can be used instead. - -Reviewed-by: Jonathan Cameron -Reviewed-by: Danilo Krummrich -Reviewed-by: Lyude Paul -Reviewed-by: Thomas Weißschuh -Reviewed-by: Zijun Hu -Link: https://lore.kernel.org/r/2025021026-atlantic-gibberish-3f0c@gregkh -Signed-off-by: Greg Kroah-Hartman ---- - Documentation/driver-api/infrastructure.rst | 6 + - drivers/base/Makefile | 2 +- - drivers/base/base.h | 1 + - drivers/base/faux.c | 232 ++++++++++++++++++++ - drivers/base/init.c | 1 + - include/linux/device/faux.h | 69 ++++++ - 6 files changed, 310 insertions(+), 1 deletion(-) - create mode 100644 drivers/base/faux.c - create mode 100644 include/linux/device/faux.h - ---- a/Documentation/driver-api/infrastructure.rst -+++ b/Documentation/driver-api/infrastructure.rst -@@ -41,6 +41,12 @@ Device Drivers Base - .. kernel-doc:: drivers/base/class.c - :export: - -+.. kernel-doc:: include/linux/device/faux.h -+ :internal: -+ -+.. kernel-doc:: drivers/base/faux.c -+ :export: -+ - .. kernel-doc:: drivers/base/node.c - :internal: - ---- a/drivers/base/Makefile -+++ b/drivers/base/Makefile -@@ -6,7 +6,7 @@ obj-y := component.o core.o bus.o dd.o - cpu.o firmware.o init.o map.o devres.o \ - attribute_container.o transport_class.o \ - topology.o container.o property.o cacheinfo.o \ -- swnode.o -+ swnode.o faux.o - obj-$(CONFIG_AUXILIARY_BUS) += auxiliary.o - obj-$(CONFIG_DEVTMPFS) += devtmpfs.o - obj-y += power/ ---- a/drivers/base/base.h -+++ b/drivers/base/base.h -@@ -138,6 +138,7 @@ int hypervisor_init(void); - static inline int hypervisor_init(void) { return 0; } - #endif - int platform_bus_init(void); -+int faux_bus_init(void); - void cpu_dev_init(void); - void container_dev_init(void); - #ifdef CONFIG_AUXILIARY_BUS ---- /dev/null -+++ b/drivers/base/faux.c -@@ -0,0 +1,232 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* -+ * Copyright (c) 2025 Greg Kroah-Hartman -+ * Copyright (c) 2025 The Linux Foundation -+ * -+ * A "simple" faux bus that allows devices to be created and added -+ * automatically to it. This is to be used whenever you need to create a -+ * device that is not associated with any "real" system resources, and do -+ * not want to have to deal with a bus/driver binding logic. It is -+ * intended to be very simple, with only a create and a destroy function -+ * available. -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include "base.h" -+ -+/* -+ * Internal wrapper structure so we can hold a pointer to the -+ * faux_device_ops for this device. -+ */ -+struct faux_object { -+ struct faux_device faux_dev; -+ const struct faux_device_ops *faux_ops; -+}; -+#define to_faux_object(dev) container_of_const(dev, struct faux_object, faux_dev.dev) -+ -+static struct device faux_bus_root = { -+ .init_name = "faux", -+}; -+ -+static int faux_match(struct device *dev, const struct device_driver *drv) -+{ -+ /* Match always succeeds, we only have one driver */ -+ return 1; -+} -+ -+static int faux_probe(struct device *dev) -+{ -+ struct faux_object *faux_obj = to_faux_object(dev); -+ struct faux_device *faux_dev = &faux_obj->faux_dev; -+ const struct faux_device_ops *faux_ops = faux_obj->faux_ops; -+ int ret = 0; -+ -+ if (faux_ops && faux_ops->probe) -+ ret = faux_ops->probe(faux_dev); -+ -+ return ret; -+} -+ -+static void faux_remove(struct device *dev) -+{ -+ struct faux_object *faux_obj = to_faux_object(dev); -+ struct faux_device *faux_dev = &faux_obj->faux_dev; -+ const struct faux_device_ops *faux_ops = faux_obj->faux_ops; -+ -+ if (faux_ops && faux_ops->remove) -+ faux_ops->remove(faux_dev); -+} -+ -+static const struct bus_type faux_bus_type = { -+ .name = "faux", -+ .match = faux_match, -+ .probe = faux_probe, -+ .remove = faux_remove, -+}; -+ -+static struct device_driver faux_driver = { -+ .name = "faux_driver", -+ .bus = &faux_bus_type, -+ .probe_type = PROBE_FORCE_SYNCHRONOUS, -+}; -+ -+static void faux_device_release(struct device *dev) -+{ -+ struct faux_object *faux_obj = to_faux_object(dev); -+ -+ kfree(faux_obj); -+} -+ -+/** -+ * faux_device_create_with_groups - Create and register with the driver -+ * core a faux device and populate the device with an initial -+ * set of sysfs attributes. -+ * @name: The name of the device we are adding, must be unique for -+ * all faux devices. -+ * @parent: Pointer to a potential parent struct device. If set to -+ * NULL, the device will be created in the "root" of the faux -+ * device tree in sysfs. -+ * @faux_ops: struct faux_device_ops that the new device will call back -+ * into, can be NULL. -+ * @groups: The set of sysfs attributes that will be created for this -+ * device when it is registered with the driver core. -+ * -+ * Create a new faux device and register it in the driver core properly. -+ * If present, callbacks in @faux_ops will be called with the device that -+ * for the caller to do something with at the proper time given the -+ * device's lifecycle. -+ * -+ * Note, when this function is called, the functions specified in struct -+ * faux_ops can be called before the function returns, so be prepared for -+ * everything to be properly initialized before that point in time. -+ * -+ * Return: -+ * * NULL if an error happened with creating the device -+ * * pointer to a valid struct faux_device that is registered with sysfs -+ */ -+struct faux_device *faux_device_create_with_groups(const char *name, -+ struct device *parent, -+ const struct faux_device_ops *faux_ops, -+ const struct attribute_group **groups) -+{ -+ struct faux_object *faux_obj; -+ struct faux_device *faux_dev; -+ struct device *dev; -+ int ret; -+ -+ faux_obj = kzalloc(sizeof(*faux_obj), GFP_KERNEL); -+ if (!faux_obj) -+ return NULL; -+ -+ /* Save off the callbacks so we can use them in the future */ -+ faux_obj->faux_ops = faux_ops; -+ -+ /* Initialize the device portion and register it with the driver core */ -+ faux_dev = &faux_obj->faux_dev; -+ dev = &faux_dev->dev; -+ -+ device_initialize(dev); -+ dev->release = faux_device_release; -+ if (parent) -+ dev->parent = parent; -+ else -+ dev->parent = &faux_bus_root; -+ dev->bus = &faux_bus_type; -+ dev->groups = groups; -+ dev_set_name(dev, "%s", name); -+ -+ ret = device_add(dev); -+ if (ret) { -+ pr_err("%s: device_add for faux device '%s' failed with %d\n", -+ __func__, name, ret); -+ put_device(dev); -+ return NULL; -+ } -+ -+ return faux_dev; -+} -+EXPORT_SYMBOL_GPL(faux_device_create_with_groups); -+ -+/** -+ * faux_device_create - create and register with the driver core a faux device -+ * @name: The name of the device we are adding, must be unique for all -+ * faux devices. -+ * @parent: Pointer to a potential parent struct device. If set to -+ * NULL, the device will be created in the "root" of the faux -+ * device tree in sysfs. -+ * @faux_ops: struct faux_device_ops that the new device will call back -+ * into, can be NULL. -+ * -+ * Create a new faux device and register it in the driver core properly. -+ * If present, callbacks in @faux_ops will be called with the device that -+ * for the caller to do something with at the proper time given the -+ * device's lifecycle. -+ * -+ * Note, when this function is called, the functions specified in struct -+ * faux_ops can be called before the function returns, so be prepared for -+ * everything to be properly initialized before that point in time. -+ * -+ * Return: -+ * * NULL if an error happened with creating the device -+ * * pointer to a valid struct faux_device that is registered with sysfs -+ */ -+struct faux_device *faux_device_create(const char *name, -+ struct device *parent, -+ const struct faux_device_ops *faux_ops) -+{ -+ return faux_device_create_with_groups(name, parent, faux_ops, NULL); -+} -+EXPORT_SYMBOL_GPL(faux_device_create); -+ -+/** -+ * faux_device_destroy - destroy a faux device -+ * @faux_dev: faux device to destroy -+ * -+ * Unregisters and cleans up a device that was created with a call to -+ * faux_device_create() -+ */ -+void faux_device_destroy(struct faux_device *faux_dev) -+{ -+ struct device *dev = &faux_dev->dev; -+ -+ if (!faux_dev) -+ return; -+ -+ device_del(dev); -+ -+ /* The final put_device() will clean up the memory we allocated for this device. */ -+ put_device(dev); -+} -+EXPORT_SYMBOL_GPL(faux_device_destroy); -+ -+int __init faux_bus_init(void) -+{ -+ int ret; -+ -+ ret = device_register(&faux_bus_root); -+ if (ret) { -+ put_device(&faux_bus_root); -+ return ret; -+ } -+ -+ ret = bus_register(&faux_bus_type); -+ if (ret) -+ goto error_bus; -+ -+ ret = driver_register(&faux_driver); -+ if (ret) -+ goto error_driver; -+ -+ return ret; -+ -+error_driver: -+ bus_unregister(&faux_bus_type); -+ -+error_bus: -+ device_unregister(&faux_bus_root); -+ return ret; -+} ---- a/drivers/base/init.c -+++ b/drivers/base/init.c -@@ -32,6 +32,7 @@ void __init driver_init(void) - /* These are also core pieces, but must come after the - * core core pieces. - */ -+ faux_bus_init(); - of_core_init(); - platform_bus_init(); - auxiliary_bus_init(); ---- /dev/null -+++ b/include/linux/device/faux.h -@@ -0,0 +1,69 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+/* -+ * Copyright (c) 2025 Greg Kroah-Hartman -+ * Copyright (c) 2025 The Linux Foundation -+ * -+ * A "simple" faux bus that allows devices to be created and added -+ * automatically to it. This is to be used whenever you need to create a -+ * device that is not associated with any "real" system resources, and do -+ * not want to have to deal with a bus/driver binding logic. It is -+ * intended to be very simple, with only a create and a destroy function -+ * available. -+ */ -+#ifndef _FAUX_DEVICE_H_ -+#define _FAUX_DEVICE_H_ -+ -+#include -+#include -+ -+/** -+ * struct faux_device - a "faux" device -+ * @dev: internal struct device of the object -+ * -+ * A simple faux device that can be created/destroyed. To be used when a -+ * driver only needs to have a device to "hang" something off. This can be -+ * used for downloading firmware or other basic tasks. Use this instead of -+ * a struct platform_device if the device has no resources assigned to -+ * it at all. -+ */ -+struct faux_device { -+ struct device dev; -+}; -+#define to_faux_device(x) container_of_const((x), struct faux_device, dev) -+ -+/** -+ * struct faux_device_ops - a set of callbacks for a struct faux_device -+ * @probe: called when a faux device is probed by the driver core -+ * before the device is fully bound to the internal faux bus -+ * code. If probe succeeds, return 0, otherwise return a -+ * negative error number to stop the probe sequence from -+ * succeeding. -+ * @remove: called when a faux device is removed from the system -+ * -+ * Both @probe and @remove are optional, if not needed, set to NULL. -+ */ -+struct faux_device_ops { -+ int (*probe)(struct faux_device *faux_dev); -+ void (*remove)(struct faux_device *faux_dev); -+}; -+ -+struct faux_device *faux_device_create(const char *name, -+ struct device *parent, -+ const struct faux_device_ops *faux_ops); -+struct faux_device *faux_device_create_with_groups(const char *name, -+ struct device *parent, -+ const struct faux_device_ops *faux_ops, -+ const struct attribute_group **groups); -+void faux_device_destroy(struct faux_device *faux_dev); -+ -+static inline void *faux_device_get_drvdata(const struct faux_device *faux_dev) -+{ -+ return dev_get_drvdata(&faux_dev->dev); -+} -+ -+static inline void faux_device_set_drvdata(struct faux_device *faux_dev, void *data) -+{ -+ dev_set_drvdata(&faux_dev->dev, data); -+} -+ -+#endif /* _FAUX_DEVICE_H_ */